Lines Matching +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>
43 #define RPCIF_DRCR_RBURST(v) ((((v) - 1) & 0x1F) << 16)
111 #define RPCIF_DMDMCR_DMCYC(v) ((((v) - 1) & 0x1F) << 0)
120 #define RPCIF_SMDMCR_DMCYC(v) ((((v) - 1) & 0x1F) << 0)
128 #define RPCIF_PHYADD 0x0070 /* R/W available on R-Car E3/D3/V3M and RZ/G2{E,L} */
129 #define RPCIF_PHYWR 0x0074 /* R/W available on R-Car E3/D3/V3M and RZ/G2{E,L} */
139 #define RPCIF_PHYCNT_STRTIM(v) (((v) & 0x7) << 15 | ((v) & 0x8) << 24) /* valid for R-Car and RZ/G2…
220 struct rpcif_priv *rpc = context; in rpcif_reg_read() local
225 switch (rpc->xfer_size) { in rpcif_reg_read()
227 *val = readb(rpc->base + reg); in rpcif_reg_read()
231 *val = readw(rpc->base + reg); in rpcif_reg_read()
236 *val = readl(rpc->base + reg); in rpcif_reg_read()
240 return -EILSEQ; in rpcif_reg_read()
245 if (rpc->xfer_size != 8) in rpcif_reg_read()
246 return -EILSEQ; in rpcif_reg_read()
250 *val = readl(rpc->base + reg); in rpcif_reg_read()
256 struct rpcif_priv *rpc = context; in rpcif_reg_write() local
260 switch (rpc->xfer_size) { in rpcif_reg_write()
262 writeb(val, rpc->base + reg); in rpcif_reg_write()
266 writew(val, rpc->base + reg); in rpcif_reg_write()
271 writel(val, rpc->base + reg); in rpcif_reg_write()
275 return -EILSEQ; in rpcif_reg_write()
279 if (rpc->xfer_size != 8) in rpcif_reg_write()
280 return -EILSEQ; in rpcif_reg_write()
285 return -EPERM; in rpcif_reg_write()
288 writel(val, rpc->base + reg); in rpcif_reg_write()
305 struct rpcif_priv *rpc = dev_get_drvdata(dev); in rpcif_sw_init() local
307 rpcif->dev = dev; in rpcif_sw_init()
308 rpcif->dirmap = rpc->dirmap; in rpcif_sw_init()
309 rpcif->size = rpc->size; in rpcif_sw_init()
314 static void rpcif_rzg2l_timing_adjust_sdr(struct rpcif_priv *rpc) in rpcif_rzg2l_timing_adjust_sdr() argument
316 regmap_write(rpc->regmap, RPCIF_PHYWR, 0xa5390000); in rpcif_rzg2l_timing_adjust_sdr()
317 regmap_write(rpc->regmap, RPCIF_PHYADD, 0x80000000); in rpcif_rzg2l_timing_adjust_sdr()
318 regmap_write(rpc->regmap, RPCIF_PHYWR, 0x00008080); in rpcif_rzg2l_timing_adjust_sdr()
319 regmap_write(rpc->regmap, RPCIF_PHYADD, 0x80000022); in rpcif_rzg2l_timing_adjust_sdr()
320 regmap_write(rpc->regmap, RPCIF_PHYWR, 0x00008080); in rpcif_rzg2l_timing_adjust_sdr()
321 regmap_write(rpc->regmap, RPCIF_PHYADD, 0x80000024); in rpcif_rzg2l_timing_adjust_sdr()
322 regmap_update_bits(rpc->regmap, RPCIF_PHYCNT, RPCIF_PHYCNT_CKSEL(3), in rpcif_rzg2l_timing_adjust_sdr()
324 regmap_write(rpc->regmap, RPCIF_PHYWR, 0x00000030); in rpcif_rzg2l_timing_adjust_sdr()
325 regmap_write(rpc->regmap, RPCIF_PHYADD, 0x80000032); in rpcif_rzg2l_timing_adjust_sdr()
330 struct rpcif_priv *rpc = dev_get_drvdata(dev); in rpcif_hw_init() local
335 if (ret) in rpcif_hw_init()
338 if (rpc->info->type == RPCIF_RZ_G2L) { in rpcif_hw_init()
339 ret = reset_control_reset(rpc->rstc); in rpcif_hw_init()
340 if (ret) in rpcif_hw_init()
343 rpcif_rzg2l_timing_adjust_sdr(rpc); in rpcif_hw_init()
346 regmap_update_bits(rpc->regmap, RPCIF_PHYCNT, RPCIF_PHYCNT_PHYMEM_MASK, in rpcif_hw_init()
350 regmap_update_bits(rpc->regmap, RPCIF_PHYCNT, RPCIF_PHYCNT_HS, 0); in rpcif_hw_init()
352 regmap_update_bits(rpc->regmap, RPCIF_PHYCNT, in rpcif_hw_init()
354 RPCIF_PHYCNT_STRTIM(BIT(fls(rpc->info->strtim)) - 1), in rpcif_hw_init()
355 RPCIF_PHYCNT_STRTIM(rpc->info->strtim)); in rpcif_hw_init()
357 regmap_update_bits(rpc->regmap, RPCIF_PHYOFFSET1, RPCIF_PHYOFFSET1_DDRTMG(3), in rpcif_hw_init()
359 regmap_update_bits(rpc->regmap, RPCIF_PHYOFFSET2, RPCIF_PHYOFFSET2_OCTTMG(7), in rpcif_hw_init()
362 if (hyperflash) in rpcif_hw_init()
363 regmap_update_bits(rpc->regmap, RPCIF_PHYINT, in rpcif_hw_init()
366 if (rpc->info->type == RPCIF_RZ_G2L) in rpcif_hw_init()
367 regmap_update_bits(rpc->regmap, RPCIF_CMNCR, in rpcif_hw_init()
373 regmap_update_bits(rpc->regmap, RPCIF_CMNCR, in rpcif_hw_init()
379 regmap_write(rpc->regmap, RPCIF_DRCR, RPCIF_DRCR_RCF); in rpcif_hw_init()
381 regmap_read(rpc->regmap, RPCIF_DRCR, &dummy); in rpcif_hw_init()
382 regmap_write(rpc->regmap, RPCIF_SSLDR, RPCIF_SSLDR_SPNDL(7) | in rpcif_hw_init()
387 rpc->bus_size = hyperflash ? 2 : 1; in rpcif_hw_init()
393 static int wait_msg_xfer_end(struct rpcif_priv *rpc) in wait_msg_xfer_end() argument
397 return regmap_read_poll_timeout(rpc->regmap, RPCIF_CMNSR, sts, in wait_msg_xfer_end()
402 static u8 rpcif_bits_set(struct rpcif_priv *rpc, u32 nbytes) in rpcif_bits_set() argument
404 if (rpc->bus_size == 2) in rpcif_bits_set()
407 return GENMASK(3, 4 - nbytes); in rpcif_bits_set()
418 struct rpcif_priv *rpc = dev_get_drvdata(dev); in rpcif_prepare() local
420 rpc->smcr = 0; in rpcif_prepare()
421 rpc->smadr = 0; in rpcif_prepare()
422 rpc->enable = 0; in rpcif_prepare()
423 rpc->command = 0; in rpcif_prepare()
424 rpc->option = 0; in rpcif_prepare()
425 rpc->dummy = 0; in rpcif_prepare()
426 rpc->ddr = 0; in rpcif_prepare()
427 rpc->xferlen = 0; in rpcif_prepare()
429 if (op->cmd.buswidth) { in rpcif_prepare()
430 rpc->enable = RPCIF_SMENR_CDE | in rpcif_prepare()
431 RPCIF_SMENR_CDB(rpcif_bit_size(op->cmd.buswidth)); in rpcif_prepare()
432 rpc->command = RPCIF_SMCMR_CMD(op->cmd.opcode); in rpcif_prepare()
433 if (op->cmd.ddr) in rpcif_prepare()
434 rpc->ddr = RPCIF_SMDRENR_HYPE(0x5); in rpcif_prepare()
436 if (op->ocmd.buswidth) { in rpcif_prepare()
437 rpc->enable |= RPCIF_SMENR_OCDE | in rpcif_prepare()
438 RPCIF_SMENR_OCDB(rpcif_bit_size(op->ocmd.buswidth)); in rpcif_prepare()
439 rpc->command |= RPCIF_SMCMR_OCMD(op->ocmd.opcode); in rpcif_prepare()
442 if (op->addr.buswidth) { in rpcif_prepare()
443 rpc->enable |= in rpcif_prepare()
444 RPCIF_SMENR_ADB(rpcif_bit_size(op->addr.buswidth)); in rpcif_prepare()
445 if (op->addr.nbytes == 4) in rpcif_prepare()
446 rpc->enable |= RPCIF_SMENR_ADE(0xF); in rpcif_prepare()
448 rpc->enable |= RPCIF_SMENR_ADE(GENMASK( in rpcif_prepare()
449 2, 3 - op->addr.nbytes)); in rpcif_prepare()
450 if (op->addr.ddr) in rpcif_prepare()
451 rpc->ddr |= RPCIF_SMDRENR_ADDRE; in rpcif_prepare()
453 if (offs && len) in rpcif_prepare()
454 rpc->smadr = *offs; in rpcif_prepare()
456 rpc->smadr = op->addr.val; in rpcif_prepare()
459 if (op->dummy.buswidth) { in rpcif_prepare()
460 rpc->enable |= RPCIF_SMENR_DME; in rpcif_prepare()
461 rpc->dummy = RPCIF_SMDMCR_DMCYC(op->dummy.ncycles); in rpcif_prepare()
464 if (op->option.buswidth) { in rpcif_prepare()
465 rpc->enable |= RPCIF_SMENR_OPDE( in rpcif_prepare()
466 rpcif_bits_set(rpc, op->option.nbytes)) | in rpcif_prepare()
467 RPCIF_SMENR_OPDB(rpcif_bit_size(op->option.buswidth)); in rpcif_prepare()
468 if (op->option.ddr) in rpcif_prepare()
469 rpc->ddr |= RPCIF_SMDRENR_OPDRE; in rpcif_prepare()
470 rpc->option = op->option.val; in rpcif_prepare()
473 rpc->dir = op->data.dir; in rpcif_prepare()
474 if (op->data.buswidth) { in rpcif_prepare()
477 rpc->buffer = op->data.buf.in; in rpcif_prepare()
478 switch (op->data.dir) { in rpcif_prepare()
480 rpc->smcr = RPCIF_SMCR_SPIRE; in rpcif_prepare()
483 rpc->smcr = RPCIF_SMCR_SPIWE; in rpcif_prepare()
488 if (op->data.ddr) in rpcif_prepare()
489 rpc->ddr |= RPCIF_SMDRENR_SPIDRE; in rpcif_prepare()
491 if (offs && len) in rpcif_prepare()
494 nbytes = op->data.nbytes; in rpcif_prepare()
495 rpc->xferlen = nbytes; in rpcif_prepare()
497 rpc->enable |= RPCIF_SMENR_SPIDB(rpcif_bit_size(op->data.buswidth)); in rpcif_prepare()
504 struct rpcif_priv *rpc = dev_get_drvdata(dev); in rpcif_manual_xfer() local
505 u32 smenr, smcr, pos = 0, max = rpc->bus_size == 2 ? 8 : 4; in rpcif_manual_xfer()
509 if (ret < 0) in rpcif_manual_xfer()
512 regmap_update_bits(rpc->regmap, RPCIF_PHYCNT, in rpcif_manual_xfer()
514 regmap_update_bits(rpc->regmap, RPCIF_CMNCR, in rpcif_manual_xfer()
516 regmap_write(rpc->regmap, RPCIF_SMCMR, rpc->command); in rpcif_manual_xfer()
517 regmap_write(rpc->regmap, RPCIF_SMOPR, rpc->option); in rpcif_manual_xfer()
518 regmap_write(rpc->regmap, RPCIF_SMDMCR, rpc->dummy); in rpcif_manual_xfer()
519 regmap_write(rpc->regmap, RPCIF_SMDRENR, rpc->ddr); in rpcif_manual_xfer()
520 regmap_write(rpc->regmap, RPCIF_SMADR, rpc->smadr); in rpcif_manual_xfer()
521 smenr = rpc->enable; in rpcif_manual_xfer()
523 switch (rpc->dir) { in rpcif_manual_xfer()
525 while (pos < rpc->xferlen) { in rpcif_manual_xfer()
526 u32 bytes_left = rpc->xferlen - pos; in rpcif_manual_xfer()
529 smcr = rpc->smcr | RPCIF_SMCR_SPIE; in rpcif_manual_xfer()
533 if (bytes_left > nbytes) in rpcif_manual_xfer()
536 smenr |= RPCIF_SMENR_SPIDE(rpcif_bits_set(rpc, nbytes)); in rpcif_manual_xfer()
537 regmap_write(rpc->regmap, RPCIF_SMENR, smenr); in rpcif_manual_xfer()
538 rpc->xfer_size = nbytes; in rpcif_manual_xfer()
540 memcpy(data, rpc->buffer + pos, nbytes); in rpcif_manual_xfer()
541 if (nbytes == 8) in rpcif_manual_xfer()
542 regmap_write(rpc->regmap, RPCIF_SMWDR1, *p++); in rpcif_manual_xfer()
543 regmap_write(rpc->regmap, RPCIF_SMWDR0, *p); in rpcif_manual_xfer()
545 regmap_write(rpc->regmap, RPCIF_SMCR, smcr); in rpcif_manual_xfer()
546 ret = wait_msg_xfer_end(rpc); in rpcif_manual_xfer()
547 if (ret) in rpcif_manual_xfer()
551 smenr = rpc->enable & in rpcif_manual_xfer()
557 * RPC-IF spoils the data for the commands without an address in rpcif_manual_xfer()
562 if (!(smenr & RPCIF_SMENR_ADE(0xF)) && rpc->dirmap) { in rpcif_manual_xfer()
565 regmap_update_bits(rpc->regmap, RPCIF_CMNCR, in rpcif_manual_xfer()
567 regmap_write(rpc->regmap, RPCIF_DRCR, in rpcif_manual_xfer()
569 regmap_write(rpc->regmap, RPCIF_DRCMR, rpc->command); in rpcif_manual_xfer()
570 regmap_write(rpc->regmap, RPCIF_DREAR, in rpcif_manual_xfer()
572 regmap_write(rpc->regmap, RPCIF_DROPR, rpc->option); in rpcif_manual_xfer()
573 regmap_write(rpc->regmap, RPCIF_DRENR, in rpcif_manual_xfer()
575 regmap_write(rpc->regmap, RPCIF_DRDMCR, rpc->dummy); in rpcif_manual_xfer()
576 regmap_write(rpc->regmap, RPCIF_DRDRENR, rpc->ddr); in rpcif_manual_xfer()
577 memcpy_fromio(rpc->buffer, rpc->dirmap, rpc->xferlen); in rpcif_manual_xfer()
578 regmap_write(rpc->regmap, RPCIF_DRCR, RPCIF_DRCR_RCF); in rpcif_manual_xfer()
580 regmap_read(rpc->regmap, RPCIF_DRCR, &dummy); in rpcif_manual_xfer()
583 while (pos < rpc->xferlen) { in rpcif_manual_xfer()
584 u32 bytes_left = rpc->xferlen - pos; in rpcif_manual_xfer()
590 regmap_write(rpc->regmap, RPCIF_SMADR, in rpcif_manual_xfer()
591 rpc->smadr + pos); in rpcif_manual_xfer()
593 smenr |= RPCIF_SMENR_SPIDE(rpcif_bits_set(rpc, nbytes)); in rpcif_manual_xfer()
594 regmap_write(rpc->regmap, RPCIF_SMENR, smenr); in rpcif_manual_xfer()
595 regmap_write(rpc->regmap, RPCIF_SMCR, in rpcif_manual_xfer()
596 rpc->smcr | RPCIF_SMCR_SPIE); in rpcif_manual_xfer()
597 rpc->xfer_size = nbytes; in rpcif_manual_xfer()
598 ret = wait_msg_xfer_end(rpc); in rpcif_manual_xfer()
599 if (ret) in rpcif_manual_xfer()
602 if (nbytes == 8) in rpcif_manual_xfer()
603 regmap_read(rpc->regmap, RPCIF_SMRDR1, p++); in rpcif_manual_xfer()
604 regmap_read(rpc->regmap, RPCIF_SMRDR0, p); in rpcif_manual_xfer()
605 memcpy(rpc->buffer + pos, data, nbytes); in rpcif_manual_xfer()
611 regmap_write(rpc->regmap, RPCIF_SMENR, rpc->enable); in rpcif_manual_xfer()
612 regmap_write(rpc->regmap, RPCIF_SMCR, in rpcif_manual_xfer()
613 rpc->smcr | RPCIF_SMCR_SPIE); in rpcif_manual_xfer()
614 ret = wait_msg_xfer_end(rpc); in rpcif_manual_xfer()
615 if (ret) in rpcif_manual_xfer()
624 if (reset_control_reset(rpc->rstc)) in rpcif_manual_xfer()
626 rpcif_hw_init(dev, rpc->bus_size == 2); in rpcif_manual_xfer()
638 if (count && ((unsigned long)from & 1)) { in memcpy_fromio_readw()
643 count--; in memcpy_fromio_readw()
649 count -= 2; in memcpy_fromio_readw()
659 count -= maxw; in memcpy_fromio_readw()
665 count -= 2; in memcpy_fromio_readw()
667 if (count) { in memcpy_fromio_readw()
675 struct rpcif_priv *rpc = dev_get_drvdata(dev); in rpcif_dirmap_read() local
676 loff_t from = offs & (rpc->size - 1); in rpcif_dirmap_read()
677 size_t size = rpc->size - from; in rpcif_dirmap_read()
680 if (len > size) in rpcif_dirmap_read()
684 if (ret < 0) in rpcif_dirmap_read()
687 regmap_update_bits(rpc->regmap, RPCIF_CMNCR, RPCIF_CMNCR_MD, 0); in rpcif_dirmap_read()
688 regmap_write(rpc->regmap, RPCIF_DRCR, 0); in rpcif_dirmap_read()
689 regmap_write(rpc->regmap, RPCIF_DRCMR, rpc->command); in rpcif_dirmap_read()
690 regmap_write(rpc->regmap, RPCIF_DREAR, in rpcif_dirmap_read()
692 regmap_write(rpc->regmap, RPCIF_DROPR, rpc->option); in rpcif_dirmap_read()
693 regmap_write(rpc->regmap, RPCIF_DRENR, in rpcif_dirmap_read()
694 rpc->enable & ~RPCIF_SMENR_SPIDE(0xF)); in rpcif_dirmap_read()
695 regmap_write(rpc->regmap, RPCIF_DRDMCR, rpc->dummy); in rpcif_dirmap_read()
696 regmap_write(rpc->regmap, RPCIF_DRDRENR, rpc->ddr); in rpcif_dirmap_read()
698 if (rpc->bus_size == 2) in rpcif_dirmap_read()
699 memcpy_fromio_readw(buf, rpc->dirmap + from, len); in rpcif_dirmap_read()
701 memcpy_fromio(buf, rpc->dirmap + from, len); in rpcif_dirmap_read()
711 struct device *dev = &pdev->dev; in rpcif_probe()
714 struct rpcif_priv *rpc; in rpcif_probe() local
719 flash = of_get_next_child(dev->of_node, NULL); in rpcif_probe()
720 if (!flash) { in rpcif_probe()
722 return -ENODEV; in rpcif_probe()
725 if (of_device_is_compatible(flash, "jedec,spi-nor")) { in rpcif_probe()
726 name = "rpc-if-spi"; in rpcif_probe()
727 } else if (of_device_is_compatible(flash, "cfi-flash")) { in rpcif_probe()
728 name = "rpc-if-hyperflash"; in rpcif_probe()
732 return -ENODEV; in rpcif_probe()
736 rpc = devm_kzalloc(dev, sizeof(*rpc), GFP_KERNEL); in rpcif_probe()
737 if (!rpc) in rpcif_probe()
738 return -ENOMEM; in rpcif_probe()
740 rpc->base = devm_platform_ioremap_resource_byname(pdev, "regs"); in rpcif_probe()
741 if (IS_ERR(rpc->base)) in rpcif_probe()
742 return PTR_ERR(rpc->base); in rpcif_probe()
744 rpc->regmap = devm_regmap_init(dev, NULL, rpc, &rpcif_regmap_config); in rpcif_probe()
745 if (IS_ERR(rpc->regmap)) { in rpcif_probe()
747 PTR_ERR(rpc->regmap)); in rpcif_probe()
748 return PTR_ERR(rpc->regmap); in rpcif_probe()
752 rpc->dirmap = devm_ioremap_resource(dev, res); in rpcif_probe()
753 if (IS_ERR(rpc->dirmap)) in rpcif_probe()
754 return PTR_ERR(rpc->dirmap); in rpcif_probe()
756 rpc->size = resource_size(res); in rpcif_probe()
757 rpc->info = of_device_get_match_data(dev); in rpcif_probe()
758 rpc->rstc = devm_reset_control_get_exclusive(dev, NULL); in rpcif_probe()
759 if (IS_ERR(rpc->rstc)) in rpcif_probe()
760 return PTR_ERR(rpc->rstc); in rpcif_probe()
762 vdev = platform_device_alloc(name, pdev->id); in rpcif_probe()
763 if (!vdev) in rpcif_probe()
764 return -ENOMEM; in rpcif_probe()
765 vdev->dev.parent = dev; in rpcif_probe()
767 rpc->dev = dev; in rpcif_probe()
768 rpc->vdev = vdev; in rpcif_probe()
769 platform_set_drvdata(pdev, rpc); in rpcif_probe()
772 if (ret) { in rpcif_probe()
782 struct rpcif_priv *rpc = platform_get_drvdata(pdev); in rpcif_remove() local
784 platform_device_unregister(rpc->vdev); in rpcif_remove()
788 { .compatible = "renesas,r8a7796-rpc-if", .data = &rpcif_info_r8a7796 },
789 { .compatible = "renesas,rcar-gen3-rpc-if", .data = &rpcif_info_gen3 },
790 { .compatible = "renesas,rcar-gen4-rpc-if", .data = &rpcif_info_gen4 },
791 { .compatible = "renesas,rzg2l-rpc-if", .data = &rpcif_info_rz_g2l },
800 .name = "rpc-if",
806 MODULE_DESCRIPTION("Renesas RPC-IF core driver");