// SPDX-License-Identifier: GPL-2.0 /* * SH QSPI (Quad SPI) driver * * Copyright (C) 2013 Renesas Electronics Corporation * Copyright (C) 2013 Nobuhiro Iwamatsu */ #include #include #include #include #include #include #include /* SH QSPI register bit masks _ */ #define SPCR_MSTR 0x08 #define SPCR_SPE 0x40 #define SPSR_SPRFF 0x80 #define SPSR_SPTEF 0x20 #define SPPCR_IO3FV 0x04 #define SPPCR_IO2FV 0x02 #define SPPCR_IO1FV 0x01 #define SPBDCR_RXBC0 BIT(0) #define SPCMD_SCKDEN BIT(15) #define SPCMD_SLNDEN BIT(14) #define SPCMD_SPNDEN BIT(13) #define SPCMD_SSLKP BIT(7) #define SPCMD_BRDV0 BIT(2) #define SPCMD_INIT1 SPCMD_SCKDEN | SPCMD_SLNDEN | \ SPCMD_SPNDEN | SPCMD_SSLKP | \ SPCMD_BRDV0 #define SPCMD_INIT2 SPCMD_SPNDEN | SPCMD_SSLKP | \ SPCMD_BRDV0 #define SPBFCR_TXRST BIT(7) #define SPBFCR_RXRST BIT(6) #define SPBFCR_TXTRG 0x30 #define SPBFCR_RXTRG 0x07 /* SH QSPI register set */ struct sh_qspi_regs { u8 spcr; u8 sslp; u8 sppcr; u8 spsr; u32 spdr; u8 spscr; u8 spssr; u8 spbr; u8 spdcr; u8 spckd; u8 sslnd; u8 spnd; u8 dummy0; u16 spcmd0; u16 spcmd1; u16 spcmd2; u16 spcmd3; u8 spbfcr; u8 dummy1; u16 spbdcr; u32 spbmul0; u32 spbmul1; u32 spbmul2; u32 spbmul3; }; struct sh_qspi_slave { #ifndef CONFIG_DM_SPI struct spi_slave slave; #endif struct sh_qspi_regs *regs; }; static void sh_qspi_init(struct sh_qspi_slave *ss) { /* QSPI initialize */ /* Set master mode only */ writeb(SPCR_MSTR, &ss->regs->spcr); /* Set SSL signal level */ writeb(0x00, &ss->regs->sslp); /* Set MOSI signal value when transfer is in idle state */ writeb(SPPCR_IO3FV|SPPCR_IO2FV, &ss->regs->sppcr); /* Set bit rate. See 58.3.8 Quad Serial Peripheral Interface */ writeb(0x01, &ss->regs->spbr); /* Disable Dummy Data Transmission */ writeb(0x00, &ss->regs->spdcr); /* Set clock delay value */ writeb(0x00, &ss->regs->spckd); /* Set SSL negation delay value */ writeb(0x00, &ss->regs->sslnd); /* Set next-access delay value */ writeb(0x00, &ss->regs->spnd); /* Set equence command */ writew(SPCMD_INIT2, &ss->regs->spcmd0); /* Reset transfer and receive Buffer */ setbits_8(&ss->regs->spbfcr, SPBFCR_TXRST|SPBFCR_RXRST); /* Clear transfer and receive Buffer control bit */ clrbits_8(&ss->regs->spbfcr, SPBFCR_TXRST|SPBFCR_RXRST); /* Set equence control method. Use equence0 only */ writeb(0x00, &ss->regs->spscr); /* Enable SPI function */ setbits_8(&ss->regs->spcr, SPCR_SPE); } static void sh_qspi_cs_activate(struct sh_qspi_slave *ss) { /* Set master mode only */ writeb(SPCR_MSTR, &ss->regs->spcr); /* Set command */ writew(SPCMD_INIT1, &ss->regs->spcmd0); /* Reset transfer and receive Buffer */ setbits_8(&ss->regs->spbfcr, SPBFCR_TXRST|SPBFCR_RXRST); /* Clear transfer and receive Buffer control bit */ clrbits_8(&ss->regs->spbfcr, SPBFCR_TXRST|SPBFCR_RXRST); /* Set equence control method. Use equence0 only */ writeb(0x00, &ss->regs->spscr); /* Enable SPI function */ setbits_8(&ss->regs->spcr, SPCR_SPE); } static void sh_qspi_cs_deactivate(struct sh_qspi_slave *ss) { /* Disable SPI Function */ clrbits_8(&ss->regs->spcr, SPCR_SPE); } static int sh_qspi_xfer_common(struct sh_qspi_slave *ss, unsigned int bitlen, const void *dout, void *din, unsigned long flags) { u32 nbyte, chunk; int i, ret = 0; u8 dtdata = 0, drdata; u8 *tdata = &dtdata, *rdata = &drdata; u32 *spbmul0 = &ss->regs->spbmul0; if (dout == NULL && din == NULL) { if (flags & SPI_XFER_END) sh_qspi_cs_deactivate(ss); return 0; } if (bitlen % 8) { printf("%s: bitlen is not 8bit alined %d", __func__, bitlen); return 1; } nbyte = bitlen / 8; if (flags & SPI_XFER_BEGIN) { sh_qspi_cs_activate(ss); /* Set 1048576 byte */ writel(0x100000, spbmul0); } if (flags & SPI_XFER_END) writel(nbyte, spbmul0); if (dout != NULL) tdata = (u8 *)dout; if (din != NULL) rdata = din; while (nbyte > 0) { /* * Check if there is 32 Byte chunk and if there is, transfer * it in one burst, otherwise transfer on byte-by-byte basis. */ chunk = (nbyte >= 32) ? 32 : 1; clrsetbits_8(&ss->regs->spbfcr, SPBFCR_TXTRG | SPBFCR_RXTRG, chunk == 32 ? SPBFCR_TXTRG | SPBFCR_RXTRG : 0); ret = wait_for_bit_8(&ss->regs->spsr, SPSR_SPTEF, true, 1000, true); if (ret) return ret; for (i = 0; i < chunk; i++) { writeb(*tdata, &ss->regs->spdr); if (dout != NULL) tdata++; } ret = wait_for_bit_8(&ss->regs->spsr, SPSR_SPRFF, true, 1000, true); if (ret) return ret; for (i = 0; i < chunk; i++) { *rdata = readb(&ss->regs->spdr); if (din != NULL) rdata++; } nbyte -= chunk; } if (flags & SPI_XFER_END) sh_qspi_cs_deactivate(ss); return ret; } #ifndef CONFIG_DM_SPI static inline struct sh_qspi_slave *to_sh_qspi(struct spi_slave *slave) { return container_of(slave, struct sh_qspi_slave, slave); } int spi_cs_is_valid(unsigned int bus, unsigned int cs) { return 1; } void spi_cs_activate(struct spi_slave *slave) { struct sh_qspi_slave *ss = to_sh_qspi(slave); sh_qspi_cs_activate(ss); } void spi_cs_deactivate(struct spi_slave *slave) { struct sh_qspi_slave *ss = to_sh_qspi(slave); sh_qspi_cs_deactivate(ss); } void spi_init(void) { /* nothing to do */ } struct spi_slave *spi_setup_slave(unsigned int bus, unsigned int cs, unsigned int max_hz, unsigned int mode) { struct sh_qspi_slave *ss; if (!spi_cs_is_valid(bus, cs)) return NULL; ss = spi_alloc_slave(struct sh_qspi_slave, bus, cs); if (!ss) { printf("SPI_error: Fail to allocate sh_qspi_slave\n"); return NULL; } ss->regs = (struct sh_qspi_regs *)SH_QSPI_BASE; /* Init SH QSPI */ sh_qspi_init(ss); return &ss->slave; } void spi_free_slave(struct spi_slave *slave) { struct sh_qspi_slave *spi = to_sh_qspi(slave); free(spi); } int spi_claim_bus(struct spi_slave *slave) { return 0; } void spi_release_bus(struct spi_slave *slave) { } int spi_xfer(struct spi_slave *slave, unsigned int bitlen, const void *dout, void *din, unsigned long flags) { struct sh_qspi_slave *ss = to_sh_qspi(slave); return sh_qspi_xfer_common(ss, bitlen, dout, din, flags); } #else #include static int sh_qspi_xfer(struct udevice *dev, unsigned int bitlen, const void *dout, void *din, unsigned long flags) { struct udevice *bus = dev->parent; struct sh_qspi_slave *ss = dev_get_platdata(bus); return sh_qspi_xfer_common(ss, bitlen, dout, din, flags); } static int sh_qspi_set_speed(struct udevice *dev, uint speed) { /* This is a SPI NOR controller, do nothing. */ return 0; } static int sh_qspi_set_mode(struct udevice *dev, uint mode) { /* This is a SPI NOR controller, do nothing. */ return 0; } static int sh_qspi_probe(struct udevice *dev) { struct sh_qspi_slave *ss = dev_get_platdata(dev); sh_qspi_init(ss); return 0; } static int sh_qspi_ofdata_to_platdata(struct udevice *dev) { struct sh_qspi_slave *plat = dev_get_platdata(dev); plat->regs = (struct sh_qspi_regs *)dev_read_addr(dev); return 0; } static const struct dm_spi_ops sh_qspi_ops = { .xfer = sh_qspi_xfer, .set_speed = sh_qspi_set_speed, .set_mode = sh_qspi_set_mode, }; static const struct udevice_id sh_qspi_ids[] = { { .compatible = "renesas,qspi" }, { } }; U_BOOT_DRIVER(sh_qspi) = { .name = "sh_qspi", .id = UCLASS_SPI, .of_match = sh_qspi_ids, .ops = &sh_qspi_ops, .ofdata_to_platdata = sh_qspi_ofdata_to_platdata, .platdata_auto_alloc_size = sizeof(struct sh_qspi_slave), .probe = sh_qspi_probe, }; #endif