Lines Matching +full:rcar +full:- +full:gen3 +full:- +full:rpc +full:- +full:if

1 // SPDX-License-Identifier: GPL-2.0
3 * Renesas RPC-IF core driver
5 * Copyright (C) 2018-2019 Renesas Solutions Corp.
7 * Copyright (C) 2019-2020 Cogent Embedded, Inc.
19 #include <memory/renesas-rpc-if.h>
45 #define RPCIF_DRCR_RBURST(v) ((((v) - 1) & 0x1F) << 16)
113 #define RPCIF_DMDMCR_DMCYC(v) ((((v) - 1) & 0x1F) << 0)
122 #define RPCIF_SMDMCR_DMCYC(v) ((((v) - 1) & 0x1F) << 0)
173 int rpcif_sw_init(struct rpcif *rpc, struct device *dev) in rpcif_sw_init() argument
179 rpc->dev = dev; in rpcif_sw_init()
182 base = devm_ioremap_resource(&pdev->dev, res); in rpcif_sw_init()
183 if (IS_ERR(base)) in rpcif_sw_init()
186 rpc->regmap = devm_regmap_init_mmio(&pdev->dev, base, in rpcif_sw_init()
188 if (IS_ERR(rpc->regmap)) { in rpcif_sw_init()
189 dev_err(&pdev->dev, in rpcif_sw_init()
191 PTR_ERR(rpc->regmap)); in rpcif_sw_init()
192 return PTR_ERR(rpc->regmap); in rpcif_sw_init()
196 rpc->size = resource_size(res); in rpcif_sw_init()
197 rpc->dirmap = devm_ioremap_resource(&pdev->dev, res); in rpcif_sw_init()
198 if (IS_ERR(rpc->dirmap)) in rpcif_sw_init()
199 rpc->dirmap = NULL; in rpcif_sw_init()
201 rpc->rstc = devm_reset_control_get_exclusive(&pdev->dev, NULL); in rpcif_sw_init()
203 return PTR_ERR_OR_ZERO(rpc->rstc); in rpcif_sw_init()
207 void rpcif_enable_rpm(struct rpcif *rpc) in rpcif_enable_rpm() argument
209 pm_runtime_enable(rpc->dev); in rpcif_enable_rpm()
213 void rpcif_disable_rpm(struct rpcif *rpc) in rpcif_disable_rpm() argument
215 pm_runtime_put_sync(rpc->dev); in rpcif_disable_rpm()
219 void rpcif_hw_init(struct rpcif *rpc, bool hyperflash) in rpcif_hw_init() argument
223 pm_runtime_get_sync(rpc->dev); in rpcif_hw_init()
233 regmap_write(rpc->regmap, RPCIF_PHYCNT, RPCIF_PHYCNT_STRTIM(7) | in rpcif_hw_init()
242 regmap_write(rpc->regmap, RPCIF_PHYOFFSET1, 0x1511144 | in rpcif_hw_init()
244 regmap_write(rpc->regmap, RPCIF_PHYOFFSET2, 0x31 | in rpcif_hw_init()
247 if (hyperflash) in rpcif_hw_init()
248 regmap_update_bits(rpc->regmap, RPCIF_PHYINT, in rpcif_hw_init()
251 regmap_write(rpc->regmap, RPCIF_CMNCR, RPCIF_CMNCR_SFDE | in rpcif_hw_init()
255 regmap_write(rpc->regmap, RPCIF_DRCR, RPCIF_DRCR_RCF); in rpcif_hw_init()
257 regmap_read(rpc->regmap, RPCIF_DRCR, &dummy); in rpcif_hw_init()
258 regmap_write(rpc->regmap, RPCIF_SSLDR, RPCIF_SSLDR_SPNDL(7) | in rpcif_hw_init()
261 pm_runtime_put(rpc->dev); in rpcif_hw_init()
263 rpc->bus_size = hyperflash ? 2 : 1; in rpcif_hw_init()
267 static int wait_msg_xfer_end(struct rpcif *rpc) in wait_msg_xfer_end() argument
271 return regmap_read_poll_timeout(rpc->regmap, RPCIF_CMNSR, sts, in wait_msg_xfer_end()
276 static u8 rpcif_bits_set(struct rpcif *rpc, u32 nbytes) in rpcif_bits_set() argument
278 if (rpc->bus_size == 2) in rpcif_bits_set()
281 return GENMASK(3, 4 - nbytes); in rpcif_bits_set()
289 void rpcif_prepare(struct rpcif *rpc, const struct rpcif_op *op, u64 *offs, in rpcif_prepare() argument
292 rpc->smcr = 0; in rpcif_prepare()
293 rpc->smadr = 0; in rpcif_prepare()
294 rpc->enable = 0; in rpcif_prepare()
295 rpc->command = 0; in rpcif_prepare()
296 rpc->option = 0; in rpcif_prepare()
297 rpc->dummy = 0; in rpcif_prepare()
298 rpc->ddr = 0; in rpcif_prepare()
299 rpc->xferlen = 0; in rpcif_prepare()
301 if (op->cmd.buswidth) { in rpcif_prepare()
302 rpc->enable = RPCIF_SMENR_CDE | in rpcif_prepare()
303 RPCIF_SMENR_CDB(rpcif_bit_size(op->cmd.buswidth)); in rpcif_prepare()
304 rpc->command = RPCIF_SMCMR_CMD(op->cmd.opcode); in rpcif_prepare()
305 if (op->cmd.ddr) in rpcif_prepare()
306 rpc->ddr = RPCIF_SMDRENR_HYPE(0x5); in rpcif_prepare()
308 if (op->ocmd.buswidth) { in rpcif_prepare()
309 rpc->enable |= RPCIF_SMENR_OCDE | in rpcif_prepare()
310 RPCIF_SMENR_OCDB(rpcif_bit_size(op->ocmd.buswidth)); in rpcif_prepare()
311 rpc->command |= RPCIF_SMCMR_OCMD(op->ocmd.opcode); in rpcif_prepare()
314 if (op->addr.buswidth) { in rpcif_prepare()
315 rpc->enable |= in rpcif_prepare()
316 RPCIF_SMENR_ADB(rpcif_bit_size(op->addr.buswidth)); in rpcif_prepare()
317 if (op->addr.nbytes == 4) in rpcif_prepare()
318 rpc->enable |= RPCIF_SMENR_ADE(0xF); in rpcif_prepare()
320 rpc->enable |= RPCIF_SMENR_ADE(GENMASK( in rpcif_prepare()
321 2, 3 - op->addr.nbytes)); in rpcif_prepare()
322 if (op->addr.ddr) in rpcif_prepare()
323 rpc->ddr |= RPCIF_SMDRENR_ADDRE; in rpcif_prepare()
325 if (offs && len) in rpcif_prepare()
326 rpc->smadr = *offs; in rpcif_prepare()
328 rpc->smadr = op->addr.val; in rpcif_prepare()
331 if (op->dummy.buswidth) { in rpcif_prepare()
332 rpc->enable |= RPCIF_SMENR_DME; in rpcif_prepare()
333 rpc->dummy = RPCIF_SMDMCR_DMCYC(op->dummy.ncycles / in rpcif_prepare()
334 op->dummy.buswidth); in rpcif_prepare()
337 if (op->option.buswidth) { in rpcif_prepare()
338 rpc->enable |= RPCIF_SMENR_OPDE( in rpcif_prepare()
339 rpcif_bits_set(rpc, op->option.nbytes)) | in rpcif_prepare()
340 RPCIF_SMENR_OPDB(rpcif_bit_size(op->option.buswidth)); in rpcif_prepare()
341 if (op->option.ddr) in rpcif_prepare()
342 rpc->ddr |= RPCIF_SMDRENR_OPDRE; in rpcif_prepare()
343 rpc->option = op->option.val; in rpcif_prepare()
346 rpc->dir = op->data.dir; in rpcif_prepare()
347 if (op->data.buswidth) { in rpcif_prepare()
350 rpc->buffer = op->data.buf.in; in rpcif_prepare()
351 switch (op->data.dir) { in rpcif_prepare()
353 rpc->smcr = RPCIF_SMCR_SPIRE; in rpcif_prepare()
356 rpc->smcr = RPCIF_SMCR_SPIWE; in rpcif_prepare()
361 if (op->data.ddr) in rpcif_prepare()
362 rpc->ddr |= RPCIF_SMDRENR_SPIDRE; in rpcif_prepare()
364 if (offs && len) in rpcif_prepare()
367 nbytes = op->data.nbytes; in rpcif_prepare()
368 rpc->xferlen = nbytes; in rpcif_prepare()
370 rpc->enable |= RPCIF_SMENR_SPIDE(rpcif_bits_set(rpc, nbytes)) | in rpcif_prepare()
371 RPCIF_SMENR_SPIDB(rpcif_bit_size(op->data.buswidth)); in rpcif_prepare()
376 int rpcif_manual_xfer(struct rpcif *rpc) in rpcif_manual_xfer() argument
381 if (rpc->bus_size == 2) in rpcif_manual_xfer()
384 pm_runtime_get_sync(rpc->dev); in rpcif_manual_xfer()
386 regmap_update_bits(rpc->regmap, RPCIF_PHYCNT, in rpcif_manual_xfer()
388 regmap_update_bits(rpc->regmap, RPCIF_CMNCR, in rpcif_manual_xfer()
390 regmap_write(rpc->regmap, RPCIF_SMCMR, rpc->command); in rpcif_manual_xfer()
391 regmap_write(rpc->regmap, RPCIF_SMOPR, rpc->option); in rpcif_manual_xfer()
392 regmap_write(rpc->regmap, RPCIF_SMDMCR, rpc->dummy); in rpcif_manual_xfer()
393 regmap_write(rpc->regmap, RPCIF_SMDRENR, rpc->ddr); in rpcif_manual_xfer()
394 smenr = rpc->enable; in rpcif_manual_xfer()
396 switch (rpc->dir) { in rpcif_manual_xfer()
398 while (pos < rpc->xferlen) { in rpcif_manual_xfer()
399 u32 nbytes = rpc->xferlen - pos; in rpcif_manual_xfer()
402 smcr = rpc->smcr | RPCIF_SMCR_SPIE; in rpcif_manual_xfer()
403 if (nbytes > max) { in rpcif_manual_xfer()
408 memcpy(data, rpc->buffer + pos, nbytes); in rpcif_manual_xfer()
409 if (nbytes > 4) { in rpcif_manual_xfer()
410 regmap_write(rpc->regmap, RPCIF_SMWDR1, in rpcif_manual_xfer()
412 regmap_write(rpc->regmap, RPCIF_SMWDR0, in rpcif_manual_xfer()
414 } else if (nbytes > 2) { in rpcif_manual_xfer()
415 regmap_write(rpc->regmap, RPCIF_SMWDR0, in rpcif_manual_xfer()
418 regmap_write(rpc->regmap, RPCIF_SMWDR0, in rpcif_manual_xfer()
422 regmap_write(rpc->regmap, RPCIF_SMADR, in rpcif_manual_xfer()
423 rpc->smadr + pos); in rpcif_manual_xfer()
424 regmap_write(rpc->regmap, RPCIF_SMENR, smenr); in rpcif_manual_xfer()
425 regmap_write(rpc->regmap, RPCIF_SMCR, smcr); in rpcif_manual_xfer()
426 ret = wait_msg_xfer_end(rpc); in rpcif_manual_xfer()
427 if (ret) in rpcif_manual_xfer()
431 smenr = rpc->enable & in rpcif_manual_xfer()
437 * RPC-IF spoils the data for the commands without an address in rpcif_manual_xfer()
442 if (!(smenr & RPCIF_SMENR_ADE(0xF)) && rpc->dirmap) { in rpcif_manual_xfer()
445 regmap_update_bits(rpc->regmap, RPCIF_CMNCR, in rpcif_manual_xfer()
447 regmap_write(rpc->regmap, RPCIF_DRCR, in rpcif_manual_xfer()
449 regmap_write(rpc->regmap, RPCIF_DRCMR, rpc->command); in rpcif_manual_xfer()
450 regmap_write(rpc->regmap, RPCIF_DREAR, in rpcif_manual_xfer()
452 regmap_write(rpc->regmap, RPCIF_DROPR, rpc->option); in rpcif_manual_xfer()
453 regmap_write(rpc->regmap, RPCIF_DRENR, in rpcif_manual_xfer()
455 regmap_write(rpc->regmap, RPCIF_DRDMCR, rpc->dummy); in rpcif_manual_xfer()
456 regmap_write(rpc->regmap, RPCIF_DRDRENR, rpc->ddr); in rpcif_manual_xfer()
457 memcpy_fromio(rpc->buffer, rpc->dirmap, rpc->xferlen); in rpcif_manual_xfer()
458 regmap_write(rpc->regmap, RPCIF_DRCR, RPCIF_DRCR_RCF); in rpcif_manual_xfer()
460 regmap_read(rpc->regmap, RPCIF_DRCR, &dummy); in rpcif_manual_xfer()
463 while (pos < rpc->xferlen) { in rpcif_manual_xfer()
464 u32 nbytes = rpc->xferlen - pos; in rpcif_manual_xfer()
467 if (nbytes > max) in rpcif_manual_xfer()
470 regmap_write(rpc->regmap, RPCIF_SMADR, in rpcif_manual_xfer()
471 rpc->smadr + pos); in rpcif_manual_xfer()
472 regmap_write(rpc->regmap, RPCIF_SMENR, smenr); in rpcif_manual_xfer()
473 regmap_write(rpc->regmap, RPCIF_SMCR, in rpcif_manual_xfer()
474 rpc->smcr | RPCIF_SMCR_SPIE); in rpcif_manual_xfer()
475 ret = wait_msg_xfer_end(rpc); in rpcif_manual_xfer()
476 if (ret) in rpcif_manual_xfer()
479 if (nbytes > 4) { in rpcif_manual_xfer()
480 regmap_read(rpc->regmap, RPCIF_SMRDR1, in rpcif_manual_xfer()
482 regmap_read(rpc->regmap, RPCIF_SMRDR0, in rpcif_manual_xfer()
484 } else if (nbytes > 2) { in rpcif_manual_xfer()
485 regmap_read(rpc->regmap, RPCIF_SMRDR0, in rpcif_manual_xfer()
488 regmap_read(rpc->regmap, RPCIF_SMRDR0, in rpcif_manual_xfer()
492 memcpy(rpc->buffer + pos, data, nbytes); in rpcif_manual_xfer()
498 regmap_write(rpc->regmap, RPCIF_SMENR, rpc->enable); in rpcif_manual_xfer()
499 regmap_write(rpc->regmap, RPCIF_SMCR, in rpcif_manual_xfer()
500 rpc->smcr | RPCIF_SMCR_SPIE); in rpcif_manual_xfer()
501 ret = wait_msg_xfer_end(rpc); in rpcif_manual_xfer()
502 if (ret) in rpcif_manual_xfer()
507 pm_runtime_put(rpc->dev); in rpcif_manual_xfer()
511 ret = reset_control_reset(rpc->rstc); in rpcif_manual_xfer()
512 rpcif_hw_init(rpc, rpc->bus_size == 2); in rpcif_manual_xfer()
517 ssize_t rpcif_dirmap_read(struct rpcif *rpc, u64 offs, size_t len, void *buf) in rpcif_dirmap_read() argument
519 loff_t from = offs & (RPCIF_DIRMAP_SIZE - 1); in rpcif_dirmap_read()
520 size_t size = RPCIF_DIRMAP_SIZE - from; in rpcif_dirmap_read()
522 if (len > size) in rpcif_dirmap_read()
525 pm_runtime_get_sync(rpc->dev); in rpcif_dirmap_read()
527 regmap_update_bits(rpc->regmap, RPCIF_CMNCR, RPCIF_CMNCR_MD, 0); in rpcif_dirmap_read()
528 regmap_write(rpc->regmap, RPCIF_DRCR, 0); in rpcif_dirmap_read()
529 regmap_write(rpc->regmap, RPCIF_DRCMR, rpc->command); in rpcif_dirmap_read()
530 regmap_write(rpc->regmap, RPCIF_DREAR, in rpcif_dirmap_read()
532 regmap_write(rpc->regmap, RPCIF_DROPR, rpc->option); in rpcif_dirmap_read()
533 regmap_write(rpc->regmap, RPCIF_DRENR, in rpcif_dirmap_read()
534 rpc->enable & ~RPCIF_SMENR_SPIDE(0xF)); in rpcif_dirmap_read()
535 regmap_write(rpc->regmap, RPCIF_DRDMCR, rpc->dummy); in rpcif_dirmap_read()
536 regmap_write(rpc->regmap, RPCIF_DRDRENR, rpc->ddr); in rpcif_dirmap_read()
538 memcpy_fromio(buf, rpc->dirmap + from, len); in rpcif_dirmap_read()
540 pm_runtime_put(rpc->dev); in rpcif_dirmap_read()
552 flash = of_get_next_child(pdev->dev.of_node, NULL); in rpcif_probe()
553 if (!flash) { in rpcif_probe()
554 dev_warn(&pdev->dev, "no flash node found\n"); in rpcif_probe()
555 return -ENODEV; in rpcif_probe()
558 if (of_device_is_compatible(flash, "jedec,spi-nor")) { in rpcif_probe()
559 name = "rpc-if-spi"; in rpcif_probe()
560 } else if (of_device_is_compatible(flash, "cfi-flash")) { in rpcif_probe()
561 name = "rpc-if-hyperflash"; in rpcif_probe()
563 dev_warn(&pdev->dev, "unknown flash type\n"); in rpcif_probe()
564 return -ENODEV; in rpcif_probe()
567 vdev = platform_device_alloc(name, pdev->id); in rpcif_probe()
568 if (!vdev) in rpcif_probe()
569 return -ENOMEM; in rpcif_probe()
570 vdev->dev.parent = &pdev->dev; in rpcif_probe()
585 { .compatible = "renesas,rcar-gen3-rpc-if", },
594 .name = "rpc-if",
600 MODULE_DESCRIPTION("Renesas RPC-IF core driver");