Re: [PATCH v3 1/2] spi: Add Renesas R-Car Gen3 RPC SPI controller driver
Hello! On 12/21/2018 04:30 AM, masonccy...@mxic.com.tw wrote: >> > diff --git a/drivers/spi/spi-renesas-rpc.c b/drivers/spi/spi-renesas-rpc.c >> > new file mode 100644 >> > index 000..cec5669 >> > --- /dev/null >> > +++ b/drivers/spi/spi-renesas-rpc.c >> > @@ -0,0 +1,776 @@ >> [...] >> > +static const struct soc_device_attribute r8a7795es1[] __initconst = { >> >>This __initconst shouldn't be there, it causes a build warning. >> >> > + { .soc_id = "r8a7795", .revision = "ES1.*" }, >> >>Wait, the driver doesn't really probe on R8A7795 yet! > > yup, this is for RPC_PHYCNT_STRTIM setting by Marek's comments. > > On H3 ES1.x, the value should be 0, while on others, the value should be 6. > > ES1.x is r8a7795. Why care if we don't support H3 yet? Add this when the R8A77950 support is added. >> > + { /* sentinel */ } >> > +}; >> > + >> > +static void rpc_spi_hw_init(struct rpc_spi *rpc) >> > +{ >> > + int strtim; >> > + /* >> > +* NOTE: The 0x260 are undocumented bits, but they must be set. >> > +* RPC_PHYCNT_STRTIM is strobe timing adjustment bit, >> > +* 0x0 : the delay is biggest, >> > +* 0x1 : the delay is 2nd biggest, >> > +* On H3 ES1.x, the value should be 0, while on others, >> > +* the value should be 6. >> > +*/ >> > + if (soc_device_match(r8a7795es1)) >> > + strtim = 0; >> > + else >> > + strtim = 6; >> [...] >> > +static const struct of_device_id rpc_spi_of_ids[] = { >> > + { .compatible = "renesas,r8a77995-rpc", }, >> >>We only support R8A77995 now. > > see above ! There's difference between R8A77995 and R8A77950, right? [...] > thanks & best regards, > Mason MBR, Sergei
Re: [PATCH v3 1/2] spi: Add Renesas R-Car Gen3 RPC SPI controller driver
On 12/17/2018 10:42 AM, masonccy...@mxic.com.tw wrote: >> > +static int rpc_spi_io_xfer(struct rpc_spi *rpc, >> > +const void *tx_buf, void *rx_buf) >> > +{ >> > + u32 smenr, smcr, data, pos = 0; >> > + int ret = 0; >> > + >> > + regmap_write(rpc->regmap, RPC_CMNCR, RPC_CMNCR_MD | RPC_CMNCR_SFDE | >> > + RPC_CMNCR_MOIIO_HIZ | RPC_CMNCR_IOFV_HIZ | >> > + RPC_CMNCR_BSZ(0)); >> > + regmap_write(rpc->regmap, RPC_SMDRENR, 0x0); >> > + regmap_write(rpc->regmap, RPC_SMCMR, rpc->cmd); >> > + regmap_write(rpc->regmap, RPC_SMDMCR, rpc->dummy); >> > + regmap_write(rpc->regmap, RPC_SMADR, rpc->addr); >> > + >> > + if (tx_buf) { >> > + smenr = rpc->smenr; >> > + >> > + while (pos < rpc->xferlen) { >> > + u32 nbytes = rpc->xferlen - pos; >> > + >> > + regmap_write(rpc->regmap, RPC_SMWDR0, >> > + get_unaligned((u32 *)(tx_buf + pos))); >> > + >> > + if (nbytes > 4) { >> > +nbytes = 4; >> > +smcr = rpc->smcr | >> > + RPC_SMCR_SPIE | RPC_SMCR_SSLKP; >> > + } else { >> > +smcr = rpc->smcr | RPC_SMCR_SPIE; >> > + } >> > + >> > + regmap_write(rpc->regmap, RPC_SMENR, smenr); >> > + regmap_write(rpc->regmap, RPC_SMCR, smcr); >> > + ret = wait_msg_xfer_end(rpc); >> > + if (ret) >> > +goto out; >> > + >> > + pos += nbytes; >> > + smenr = rpc->smenr & ~RPC_SMENR_CDE & >> > +~RPC_SMENR_ADE(0xf); >> > + } >> > + } else if (rx_buf) { >> > + while (pos < rpc->xferlen) { >> > + u32 nbytes = rpc->xferlen - pos; >> > + >> > + if (nbytes > 4) >> > +nbytes = 4; >> > + >> > + regmap_write(rpc->regmap, RPC_SMENR, rpc->smenr); >> > + regmap_write(rpc->regmap, RPC_SMCR, >> > + rpc->smcr | RPC_SMCR_SPIE); >> >>Hm... our flash chip (Spansion S25FS512S) doesn't get detected; it sends >> JEDEC ID bytes 0..3 repeatedly, unless I copy the SSLKP logic from the >> writing >> branch above... [...] > what follows is my booting log, FYI. > -- > [1.625053] m25p80 spi5.0: s25fl129p1 (16384 Kbytes) Looking at the spi_nor_ids[], this chip has 0x01 in both byte 0 and byte 4... > [1.634391] 12 fixed-partitions partitions found on MTD device spi5.0 > [1.642198] Creating 12 MTD partitions on "spi5.0": > [1.647598] 0x-0x0004 : "Bank 1 - Boot parameter" > [1.660893] 0x0004-0x0018 : "Bank 1 - Loader-BL2" > [1.671287] 0x0018-0x001c : "Bank 1 - Certification" > --- > >> >> > + ret = wait_msg_xfer_end(rpc); >> > + if (ret) >> > +goto out; >> > + >> > + regmap_read(rpc->regmap, RPC_SMRDR0, ); >> > + memcpy_fromio(rx_buf + pos, (void *), nbytes); >> > + pos += nbytes; >> >>... and it skips byte 4 unless I copy the code from the end of the writing >> branch, clearing CDE/ADE. But even then the byte 4 reads as 0x03 instead of >> 0. > > yup, I think this is some kind of RPC HW limitation, > in RPC manual I/O mode, it only could read 4 bytes data w/ one command. > > That is, one command + read 4 bytes data + read 4 bytes data + read 4 bytes > data + ... > will get the incorrect data. > > That's why RPC in manual I/O mode, driver only could do, > one command + read 4 bytes data; one command + read 4 bytes data and so on. Yes. But the problem is you can't work around by reading 4 bytes at most for the RDID command -- it has no address phase. Every time you "restart" reading, you get bytes 0..3 again, like me. It seems that this approach works for you only by chance... > thanks & best regards, > Mason MBR, Sergei
Re: [PATCH v3 1/2] spi: Add Renesas R-Car Gen3 RPC SPI controller driver
Hello! On 12/17/2018 10:42 AM, masonccy...@mxic.com.tw wrote: >> > +static int rpc_spi_io_xfer(struct rpc_spi *rpc, >> > +const void *tx_buf, void *rx_buf) >> > +{ >> > + u32 smenr, smcr, data, pos = 0; >> > + int ret = 0; >> > + >> > + regmap_write(rpc->regmap, RPC_CMNCR, RPC_CMNCR_MD | RPC_CMNCR_SFDE | >> > + RPC_CMNCR_MOIIO_HIZ | RPC_CMNCR_IOFV_HIZ | >> > + RPC_CMNCR_BSZ(0)); >> > + regmap_write(rpc->regmap, RPC_SMDRENR, 0x0); >> > + regmap_write(rpc->regmap, RPC_SMCMR, rpc->cmd); >> > + regmap_write(rpc->regmap, RPC_SMDMCR, rpc->dummy); >> > + regmap_write(rpc->regmap, RPC_SMADR, rpc->addr); >> > + >> > + if (tx_buf) { >> > + smenr = rpc->smenr; >> > + >> > + while (pos < rpc->xferlen) { >> > + u32 nbytes = rpc->xferlen - pos; >> > + >> > + regmap_write(rpc->regmap, RPC_SMWDR0, >> > + get_unaligned((u32 *)(tx_buf + pos))); >> > + >> > + if (nbytes > 4) { >> > +nbytes = 4; >> > +smcr = rpc->smcr | >> > + RPC_SMCR_SPIE | RPC_SMCR_SSLKP; >> > + } else { >> > +smcr = rpc->smcr | RPC_SMCR_SPIE; >> > + } >> > + >> > + regmap_write(rpc->regmap, RPC_SMENR, smenr); >> > + regmap_write(rpc->regmap, RPC_SMCR, smcr); >> > + ret = wait_msg_xfer_end(rpc); >> > + if (ret) >> > +goto out; >> > + >> > + pos += nbytes; >> > + smenr = rpc->smenr & ~RPC_SMENR_CDE & >> > +~RPC_SMENR_ADE(0xf); >> > + } >> > + } else if (rx_buf) { >> > + while (pos < rpc->xferlen) { >> > + u32 nbytes = rpc->xferlen - pos; >> > + >> > + if (nbytes > 4) >> > +nbytes = 4; >> > + >> > + regmap_write(rpc->regmap, RPC_SMENR, rpc->smenr); >> > + regmap_write(rpc->regmap, RPC_SMCR, >> > + rpc->smcr | RPC_SMCR_SPIE); >> >>Hm... our flash chip (Spansion S25FS512S) doesn't get detected; it sends >> JEDEC ID bytes 0..3 repeatedly, unless I copy the SSLKP logic from the >> writing >> branch above... > > Do you switch the SW1, SW2, SW3, SW13, SW31 and SW10 to on-board QSPI mode ? > Because R-Car D3 Draak board default is booting from HyperFlsah. I was testing your patch on the V3H-based Condor and Starter Kit boards -- it should have worked without much ado... It works with *our* driver, living under drivers/mtd/spi-nor/ (which makes it outdated, AFAIU) and I was going to push it upstream before I learned about your driver. :-) > what follows is my booting log, FYI. > -- > [1.625053] m25p80 spi5.0: s25fl129p1 (16384 Kbytes) So another Spansion flash? > [1.634391] 12 fixed-partitions partitions found on MTD device spi5.0 > [1.642198] Creating 12 MTD partitions on "spi5.0": > [1.647598] 0x-0x0004 : "Bank 1 - Boot parameter" > [1.660893] 0x0004-0x0018 : "Bank 1 - Loader-BL2" > [1.671287] 0x0018-0x001c : "Bank 1 - Certification" > --- > >> >> > + ret = wait_msg_xfer_end(rpc); >> > + if (ret) >> > +goto out; >> > + >> > + regmap_read(rpc->regmap, RPC_SMRDR0, ); >> > + memcpy_fromio(rx_buf + pos, (void *), nbytes); >> > + pos += nbytes; >> >>... and it skips byte 4 unless I copy the code from the end of the writing >> branch, clearing CDE/ADE. But even then the byte 4 reads as 0x03 instead of >> 0. > > yup, I think this is some kind of RPC HW limitation, > in RPC manual I/O mode, it only could read 4 bytes data w/ one command. Thank for the info -- seems worth a comment though... > That is, one command + read 4 bytes data + read 4 bytes data + read 4 bytes > data + ... > will get the incorrect data. What if we want to read less than 4 bytes (the ID read requests SPI_NOR_MAX_ID_LEN (6) bytes, i.e. 4 + 2)? You seem to always expect 4 bytes... > That's why RPC in manual I/O mode, driver only could do, > one command + read 4 bytes data; one command + read 4 bytes data and so on. The question is why it just duplicates the ID bytes 0..3 on the 2nd iteration in our case... > But RPC in external address space read mode(here we call it direct mapping > read mode) > is ok for one command + read 4 bytes data + read 4 bytes data + Sounds promising... if only we could make the probing work. :-) > thanks & best regards, > Mason MBR, Sergei
Re: [PATCH v3 1/2] spi: Add Renesas R-Car Gen3 RPC SPI controller driver
On 12/17/2018 08:42 AM, masonccy...@mxic.com.tw wrote: > Hi Sergei, > > >> > +static int rpc_spi_io_xfer(struct rpc_spi *rpc, >> > + const void *tx_buf, void *rx_buf) >> > +{ >> > + u32 smenr, smcr, data, pos = 0; >> > + int ret = 0; >> > + >> > + regmap_write(rpc->regmap, RPC_CMNCR, RPC_CMNCR_MD | RPC_CMNCR_SFDE | >> > + RPC_CMNCR_MOIIO_HIZ | RPC_CMNCR_IOFV_HIZ | >> > + RPC_CMNCR_BSZ(0)); >> > + regmap_write(rpc->regmap, RPC_SMDRENR, 0x0); >> > + regmap_write(rpc->regmap, RPC_SMCMR, rpc->cmd); >> > + regmap_write(rpc->regmap, RPC_SMDMCR, rpc->dummy); >> > + regmap_write(rpc->regmap, RPC_SMADR, rpc->addr); >> > + >> > + if (tx_buf) { >> > + smenr = rpc->smenr; >> > + >> > + while (pos < rpc->xferlen) { >> > + u32 nbytes = rpc->xferlen - pos; >> > + >> > + regmap_write(rpc->regmap, RPC_SMWDR0, >> > + get_unaligned((u32 *)(tx_buf + pos))); >> > + >> > + if (nbytes > 4) { >> > + nbytes = 4; >> > + smcr = rpc->smcr | >> > + RPC_SMCR_SPIE | RPC_SMCR_SSLKP; >> > + } else { >> > + smcr = rpc->smcr | RPC_SMCR_SPIE; >> > + } >> > + >> > + regmap_write(rpc->regmap, RPC_SMENR, smenr); >> > + regmap_write(rpc->regmap, RPC_SMCR, smcr); >> > + ret = wait_msg_xfer_end(rpc); >> > + if (ret) >> > + goto out; >> > + >> > + pos += nbytes; >> > + smenr = rpc->smenr & ~RPC_SMENR_CDE & >> > + ~RPC_SMENR_ADE(0xf); >> > + } >> > + } else if (rx_buf) { >> > + while (pos < rpc->xferlen) { >> > + u32 nbytes = rpc->xferlen - pos; >> > + >> > + if (nbytes > 4) >> > + nbytes = 4; >> > + >> > + regmap_write(rpc->regmap, RPC_SMENR, rpc->smenr); >> > + regmap_write(rpc->regmap, RPC_SMCR, >> > + rpc->smcr | RPC_SMCR_SPIE); >> >> Hm... our flash chip (Spansion S25FS512S) doesn't get detected; it > sends >> JEDEC ID bytes 0..3 repeatedly, unless I copy the SSLKP logic from the > writing >> branch above... > > Do you switch the SW1, SW2, SW3, SW13, SW31 and SW10 to on-board QSPI > mode ? > Because R-Car D3 Draak board default is booting from HyperFlsah. So this puts us back to the original discussion -- the driver should support HF mode as well IMO. > what follows is my booting log, FYI. > -- > [ 1.625053] m25p80 spi5.0: s25fl129p1 (16384 Kbytes) > [ 1.634391] 12 fixed-partitions partitions found on MTD device spi5.0 > [ 1.642198] Creating 12 MTD partitions on "spi5.0": > [ 1.647598] 0x-0x0004 : "Bank 1 - Boot parameter" > [ 1.660893] 0x0004-0x0018 : "Bank 1 - Loader-BL2" > [ 1.671287] 0x0018-0x001c : "Bank 1 - Certification" > --- > >> >> > + ret = wait_msg_xfer_end(rpc); >> > + if (ret) >> > + goto out; >> > + >> > + regmap_read(rpc->regmap, RPC_SMRDR0, ); >> > + memcpy_fromio(rx_buf + pos, (void *), nbytes); >> > + pos += nbytes; >> >> ... and it skips byte 4 unless I copy the code from the end of the > writing >> branch, clearing CDE/ADE. But even then the byte 4 reads as 0x03 > instead of 0. > > yup, I think this is some kind of RPC HW limitation, > in RPC manual I/O mode, it only could read 4 bytes data w/ one command. > > That is, one command + read 4 bytes data + read 4 bytes data + read 4 > bytes data + ... > will get the incorrect data. > > That's why RPC in manual I/O mode, driver only could do, > one command + read 4 bytes data; one command + read 4 bytes data and so on. > > But RPC in external address space read mode(here we call it direct > mapping read mode) > is ok for one command + read 4 bytes data + read 4 bytes data + I think the U-Boot driver solves those problems, since it works in both RPC and HF mode on all of Gen3 boards , not just D3 in non-standard SPI boot configuration. Please take a look. -- Best regards, Marek Vasut
Re: [PATCH v3 1/2] spi: Add Renesas R-Car Gen3 RPC SPI controller driver
On 12/07/2018 02:13 PM, Mason Yang wrote: > Add a driver for Renesas R-Car Gen3 RPC SPI controller. > > Signed-off-by: Mason Yang > --- > drivers/spi/Kconfig | 6 + > drivers/spi/Makefile | 1 + > drivers/spi/spi-renesas-rpc.c | 776 > ++ > 3 files changed, 783 insertions(+) > create mode 100644 drivers/spi/spi-renesas-rpc.c > > diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig > index 7d3a5c9..54b40f8 100644 > --- a/drivers/spi/Kconfig > +++ b/drivers/spi/Kconfig [...] > diff --git a/drivers/spi/spi-renesas-rpc.c b/drivers/spi/spi-renesas-rpc.c > new file mode 100644 > index 000..cec5669 > --- /dev/null > +++ b/drivers/spi/spi-renesas-rpc.c > @@ -0,0 +1,776 @@ [...] > +static int rpc_spi_do_reset(struct rpc_spi *rpc) > +{ > + int ret; > + > + ret = reset_control_reset(rpc->rstc); > + if (ret) > + return ret; > + > + return 0; This degrades to: { return reset_control_reset(rpc->rstc); } So, we hardly need this function now... [...] > +static int rpc_spi_io_xfer(struct rpc_spi *rpc, > +const void *tx_buf, void *rx_buf) > +{ > + u32 smenr, smcr, data, pos = 0; > + int ret = 0; > + > + regmap_write(rpc->regmap, RPC_CMNCR, RPC_CMNCR_MD | RPC_CMNCR_SFDE | > + RPC_CMNCR_MOIIO_HIZ | RPC_CMNCR_IOFV_HIZ | > + RPC_CMNCR_BSZ(0)); > + regmap_write(rpc->regmap, RPC_SMDRENR, 0x0); > + regmap_write(rpc->regmap, RPC_SMCMR, rpc->cmd); > + regmap_write(rpc->regmap, RPC_SMDMCR, rpc->dummy); > + regmap_write(rpc->regmap, RPC_SMADR, rpc->addr); > + > + if (tx_buf) { > + smenr = rpc->smenr; > + > + while (pos < rpc->xferlen) { > + u32 nbytes = rpc->xferlen - pos; > + > + regmap_write(rpc->regmap, RPC_SMWDR0, > + get_unaligned((u32 *)(tx_buf + pos))); > + > + if (nbytes > 4) { > + nbytes = 4; > + smcr = rpc->smcr | > +RPC_SMCR_SPIE | RPC_SMCR_SSLKP; > + } else { > + smcr = rpc->smcr | RPC_SMCR_SPIE; > + } > + > + regmap_write(rpc->regmap, RPC_SMENR, smenr); > + regmap_write(rpc->regmap, RPC_SMCR, smcr); > + ret = wait_msg_xfer_end(rpc); > + if (ret) > + goto out; > + > + pos += nbytes; > + smenr = rpc->smenr & ~RPC_SMENR_CDE & > + ~RPC_SMENR_ADE(0xf); > + } > + } else if (rx_buf) { > + while (pos < rpc->xferlen) { > + u32 nbytes = rpc->xferlen - pos; > + > + if (nbytes > 4) > + nbytes = 4; > + > + regmap_write(rpc->regmap, RPC_SMENR, rpc->smenr); > + regmap_write(rpc->regmap, RPC_SMCR, > + rpc->smcr | RPC_SMCR_SPIE); Hm... our flash chip (Spansion S25FS512S) doesn't get detected; it sends JEDEC ID bytes 0..3 repeatedly, unless I copy the SSLKP logic from the writing branch above... > + ret = wait_msg_xfer_end(rpc); > + if (ret) > + goto out; > + > + regmap_read(rpc->regmap, RPC_SMRDR0, ); > + memcpy_fromio(rx_buf + pos, (void *), nbytes); > + pos += nbytes; ... and it skips byte 4 unless I copy the code from the end of the writing branch, clearing CDE/ADE. But even then the byte 4 reads as 0x03 instead of 0. > + regmap_write(rpc->regmap, RPC_SMCMR, rpc->cmd); > + regmap_write(rpc->regmap, RPC_SMDMCR, rpc->dummy); > + regmap_write(rpc->regmap, RPC_SMADR, rpc->addr + pos); > + } > + } else { > + regmap_write(rpc->regmap, RPC_SMENR, rpc->smenr); > + regmap_write(rpc->regmap, RPC_SMCR, rpc->smcr | RPC_SMCR_SPIE); > + ret = wait_msg_xfer_end(rpc); > + if (ret) > + goto out; > + } > + > + return ret; > +out: > + return rpc_spi_do_reset(rpc); > +} [...] MBR, Sergei
Re: [PATCH v3 1/2] spi: Add Renesas R-Car Gen3 RPC SPI controller driver
On 12/07/2018 02:13 PM, Mason Yang wrote: > Add a driver for Renesas R-Car Gen3 RPC SPI controller. > > Signed-off-by: Mason Yang [...] > diff --git a/drivers/spi/spi-renesas-rpc.c b/drivers/spi/spi-renesas-rpc.c > new file mode 100644 > index 000..cec5669 > --- /dev/null > +++ b/drivers/spi/spi-renesas-rpc.c > @@ -0,0 +1,776 @@ [...] > +static const struct soc_device_attribute r8a7795es1[] __initconst = { This __initconst shouldn't be there, it causes a build warning. > + { .soc_id = "r8a7795", .revision = "ES1.*" }, Wait, the driver doesn't really probe on R8A7795 yet! > + { /* sentinel */ } > +}; > + > +static void rpc_spi_hw_init(struct rpc_spi *rpc) > +{ > + int strtim; > + /* > + * NOTE: The 0x260 are undocumented bits, but they must be set. > + * RPC_PHYCNT_STRTIM is strobe timing adjustment bit, > + * 0x0 : the delay is biggest, > + * 0x1 : the delay is 2nd biggest, > + * On H3 ES1.x, the value should be 0, while on others, > + * the value should be 6. > + */ > + if (soc_device_match(r8a7795es1)) > + strtim = 0; > + else > + strtim = 6; [...] > +static const struct of_device_id rpc_spi_of_ids[] = { > + { .compatible = "renesas,r8a77995-rpc", }, We only support R8A77995 now. > + { /* sentinel */ } > +}; > +MODULE_DEVICE_TABLE(of, rpc_spi_of_ids); [...] MBR, Sergei
Re: [PATCH v3 1/2] spi: Add Renesas R-Car Gen3 RPC SPI controller driver
Hi Mason, Thank you for the patch! Perhaps something to improve: [auto build test WARNING on spi/for-next] [also build test WARNING on next-20181207] [if your patch is applied to the wrong git tree, please drop us a note to help improve the system] url: https://github.com/0day-ci/linux/commits/Mason-Yang/spi-Add-Renesas-R-Car-Gen3-RPC-SPI-controller-driver/20181208-081244 base: https://git.kernel.org/pub/scm/linux/kernel/git/broonie/spi.git for-next config: i386-allmodconfig (attached as .config) compiler: gcc-7 (Debian 7.3.0-1) 7.3.0 reproduce: # save the attached .config to linux build tree make ARCH=i386 All warnings (new ones prefixed by >>): >> WARNING: drivers/spi/spi-renesas-rpc.o(.text+0xabd): Section mismatch in >> reference from the function rpc_spi_probe() to the variable >> .init.rodata:r8a7795es1 The function rpc_spi_probe() references the variable __initconst r8a7795es1. This is often because rpc_spi_probe lacks a __initconst annotation or the annotation of r8a7795es1 is wrong. --- 0-DAY kernel test infrastructureOpen Source Technology Center https://lists.01.org/pipermail/kbuild-all Intel Corporation .config.gz Description: application/gzip
[PATCH v3 1/2] spi: Add Renesas R-Car Gen3 RPC SPI controller driver
Add a driver for Renesas R-Car Gen3 RPC SPI controller. Signed-off-by: Mason Yang --- drivers/spi/Kconfig | 6 + drivers/spi/Makefile | 1 + drivers/spi/spi-renesas-rpc.c | 776 ++ 3 files changed, 783 insertions(+) create mode 100644 drivers/spi/spi-renesas-rpc.c diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig index 7d3a5c9..54b40f8 100644 --- a/drivers/spi/Kconfig +++ b/drivers/spi/Kconfig @@ -528,6 +528,12 @@ config SPI_RSPI help SPI driver for Renesas RSPI and QSPI blocks. +config SPI_RENESAS_RPC + tristate "Renesas R-Car Gen3 RPC SPI controller" + depends on ARCH_RENESAS || COMPILE_TEST + help + SPI driver for Renesas R-Car Gen3 RPC. + config SPI_QCOM_QSPI tristate "QTI QSPI controller" depends on ARCH_QCOM diff --git a/drivers/spi/Makefile b/drivers/spi/Makefile index 3575205..5d5c523 100644 --- a/drivers/spi/Makefile +++ b/drivers/spi/Makefile @@ -81,6 +81,7 @@ obj-$(CONFIG_SPI_QUP) += spi-qup.o obj-$(CONFIG_SPI_ROCKCHIP) += spi-rockchip.o obj-$(CONFIG_SPI_RB4XX)+= spi-rb4xx.o obj-$(CONFIG_SPI_RSPI) += spi-rspi.o +obj-$(CONFIG_SPI_RENESAS_RPC) += spi-renesas-rpc.o obj-$(CONFIG_SPI_S3C24XX) += spi-s3c24xx-hw.o spi-s3c24xx-hw-y := spi-s3c24xx.o spi-s3c24xx-hw-$(CONFIG_SPI_S3C24XX_FIQ) += spi-s3c24xx-fiq.o diff --git a/drivers/spi/spi-renesas-rpc.c b/drivers/spi/spi-renesas-rpc.c new file mode 100644 index 000..cec5669 --- /dev/null +++ b/drivers/spi/spi-renesas-rpc.c @@ -0,0 +1,776 @@ +// SPDX-License-Identifier: GPL-2.0 +// +// Copyright (C) 2018 ~ 2019 Renesas Solutions Corp. +// Copyright (C) 2018 Macronix International Co., Ltd. +// +// R-Car Gen3 RPC SPI/QSPI/Octa driver +// +// Authors: +// Mason Yang +// + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#define RPC_CMNCR 0x /* R/W */ +#define RPC_CMNCR_MD BIT(31) +#define RPC_CMNCR_SFDE BIT(24) +#define RPC_CMNCR_MOIIO3(val) (((val) & 0x3) << 22) +#define RPC_CMNCR_MOIIO2(val) (((val) & 0x3) << 20) +#define RPC_CMNCR_MOIIO1(val) (((val) & 0x3) << 18) +#define RPC_CMNCR_MOIIO0(val) (((val) & 0x3) << 16) +#define RPC_CMNCR_MOIIO_HIZ(RPC_CMNCR_MOIIO0(3) | RPC_CMNCR_MOIIO1(3) | \ +RPC_CMNCR_MOIIO2(3) | RPC_CMNCR_MOIIO3(3)) +#define RPC_CMNCR_IO3FV(val) (((val) & 0x3) << 14) +#define RPC_CMNCR_IO2FV(val) (((val) & 0x3) << 12) +#define RPC_CMNCR_IO0FV(val) (((val) & 0x3) << 8) +#define RPC_CMNCR_IOFV_HIZ (RPC_CMNCR_IO0FV(3) | RPC_CMNCR_IO2FV(3) | \ +RPC_CMNCR_IO3FV(3)) +#define RPC_CMNCR_CPHATBIT(6) +#define RPC_CMNCR_CPHARBIT(5) +#define RPC_CMNCR_SSLP BIT(4) +#define RPC_CMNCR_CPOL BIT(3) +#define RPC_CMNCR_BSZ(val) (((val) & 0x3) << 0) + +#define RPC_SSLDR 0x0004 /* R/W */ +#define RPC_SSLDR_SPNDL(d) (((d) & 0x7) << 16) +#define RPC_SSLDR_SLNDL(d) (((d) & 0x7) << 8) +#define RPC_SSLDR_SCKDL(d) (((d) & 0x7) << 0) + +#define RPC_DRCR 0x000C /* R/W */ +#define RPC_DRCR_SSLN BIT(24) +#define RPC_DRCR_RBURST(v) (((v) & 0x1F) << 16) +#define RPC_DRCR_RCF BIT(9) +#define RPC_DRCR_RBE BIT(8) +#define RPC_DRCR_SSLE BIT(0) + +#define RPC_DRCMR 0x0010 /* R/W */ +#define RPC_DRCMR_CMD(c) (((c) & 0xFF) << 16) +#define RPC_DRCMR_OCMD(c) (((c) & 0xFF) << 0) + +#define RPC_DREAR 0x0014 /* R/W */ +#define RPC_DREAR_EAC BIT(0) + +#define RPC_DROPR 0x0018 /* R/W */ + +#define RPC_DRENR 0x001C /* R/W */ +#define RPC_DRENR_CDB(o) (u32)o) & 0x3) << 30)) +#define RPC_DRENR_OCDB(o) (((o) & 0x3) << 28) +#define RPC_DRENR_ADB(o) (((o) & 0x3) << 24) +#define RPC_DRENR_OPDB(o) (((o) & 0x3) << 20) +#define RPC_DRENR_SPIDB(o) (((o) & 0x3) << 16) +#define RPC_DRENR_DME BIT(15) +#define RPC_DRENR_CDE BIT(14) +#define RPC_DRENR_OCDE BIT(12) +#define RPC_DRENR_ADE(v) (((v) & 0xF) << 8) +#define RPC_DRENR_OPDE(v) (((v) & 0xF) << 4) + +#define RPC_SMCR 0x0020 /* R/W */ +#define RPC_SMCR_SSLKP BIT(8) +#define RPC_SMCR_SPIRE BIT(2) +#define RPC_SMCR_SPIWE BIT(1) +#define RPC_SMCR_SPIE BIT(0) + +#define RPC_SMCMR 0x0024 /* R/W */ +#define RPC_SMCMR_CMD(c) (((c) & 0xFF) << 16) +#define RPC_SMCMR_OCMD(c) (((c) & 0xFF) << 0) + +#define RPC_SMADR 0x0028 /* R/W */ +#define RPC_SMOPR 0x002C /* R/W */ +#define RPC_SMOPR_OPD0(o) (((o) & 0xFF) << 0) +#define RPC_SMOPR_OPD1(o) (((o) & 0xFF) << 8) +#define RPC_SMOPR_OPD2(o) (((o) &