[U-Boot] [PATCH 00/11] ARM: Keystone2: Convert davinci_spi to DM

This series converts davinci_spi driver to adapt to driver model framework. And enables the driver on k2l, k2e, k2hk evms. Also, added support for davinci_spi on k2g evm.
Tested on k2l, k2e, k2hk and k2g evms.
Vignesh R (11): spi: davinci_spi: Convert to driver to adapt to DM keystone2: spi: do not define DM_SPI and DM_SPI_FLASH for SPL build ARM: dts: keystone2: add SPI aliases for davinci SPI nodes ARM: dts: k2hk: Enable Davinci SPI controller defconfig: k2hk_evm_defconfig: enable SPI driver model ARM: dts: k2e: Enable Davinci SPI controller defconfig: k2e_evm_defconfig: enable SPI driver model ARM: dts: k2l: Enable Davinci SPI controller defconfig: k2l_evm_defconfig: enable SPI driver model ARM: dts: k2g: add support for Davinci SPI controller defconfig: k2g_evm_defconfig: enable SPI driver model
arch/arm/dts/k2e-evm.dts | 3 +- arch/arm/dts/k2g-evm.dts | 24 +++ arch/arm/dts/k2g.dtsi | 47 +++++ arch/arm/dts/k2hk-evm.dts | 3 +- arch/arm/dts/k2l-evm.dts | 3 +- arch/arm/dts/keystone.dtsi | 3 + configs/k2e_evm_defconfig | 2 + configs/k2g_evm_defconfig | 2 + configs/k2hk_evm_defconfig | 2 + configs/k2l_evm_defconfig | 2 + drivers/spi/davinci_spi.c | 326 +++++++++++++++++++++++++---------- include/configs/ti_armv7_keystone2.h | 4 + 12 files changed, 329 insertions(+), 92 deletions(-)

Convert davinci_spi driver to comply with SPI DM framework.
Signed-off-by: Vignesh R vigneshr@ti.com --- drivers/spi/davinci_spi.c | 326 +++++++++++++++++++++++++++++++++------------- 1 file changed, 237 insertions(+), 89 deletions(-)
diff --git a/drivers/spi/davinci_spi.c b/drivers/spi/davinci_spi.c index 0bd4f88926f1..838f9fb7fb27 100644 --- a/drivers/spi/davinci_spi.c +++ b/drivers/spi/davinci_spi.c @@ -14,6 +14,7 @@ #include <malloc.h> #include <asm/io.h> #include <asm/arch/hardware.h> +#include <dm.h>
/* SPIGCR0 */ #define SPIGCR0_SPIENA_MASK 0x1 @@ -51,6 +52,7 @@ /* SPIDEF */ #define SPIDEF_CSDEF0_MASK BIT(0)
+#ifndef CONFIG_DM_SPI #define SPI0_BUS 0 #define SPI0_BASE CONFIG_SYS_SPI_BASE /* @@ -83,6 +85,9 @@ #define SPI2_NUM_CS CONFIG_SYS_SPI2_NUM_CS #define SPI2_BASE CONFIG_SYS_SPI2_BASE #endif +#endif + +DECLARE_GLOBAL_DATA_PTR;
/* davinci spi register set */ struct davinci_spi_regs { @@ -114,16 +119,17 @@ struct davinci_spi_regs {
/* davinci spi slave */ struct davinci_spi_slave { +#ifndef CONFIG_DM_SPI struct spi_slave slave; +#endif struct davinci_spi_regs *regs; unsigned int freq; + unsigned int mode; + u8 num_cs; + u8 cur_cs; + bool half_duplex; };
-static inline struct davinci_spi_slave *to_davinci_spi(struct spi_slave *slave) -{ - return container_of(slave, struct davinci_spi_slave, slave); -} - /* * This functions needs to act like a macro to avoid pipeline reloads in the * loops below. Use always_inline. This gains us about 160KiB/s and the bloat @@ -144,15 +150,14 @@ static inline u32 davinci_spi_xfer_data(struct davinci_spi_slave *ds, u32 data) return buf_reg_val; }
-static int davinci_spi_read(struct spi_slave *slave, unsigned int len, +static int davinci_spi_read(struct davinci_spi_slave *ds, unsigned int len, u8 *rxp, unsigned long flags) { - struct davinci_spi_slave *ds = to_davinci_spi(slave); unsigned int data1_reg_val;
/* enable CS hold, CS[n] and clear the data bits */ data1_reg_val = ((1 << SPIDAT1_CSHOLD_SHIFT) | - (slave->cs << SPIDAT1_CSNR_SHIFT)); + (ds->cur_cs << SPIDAT1_CSNR_SHIFT));
/* wait till TXFULL is deasserted */ while (readl(&ds->regs->buf) & SPIBUF_TXFULL_MASK) @@ -175,15 +180,14 @@ static int davinci_spi_read(struct spi_slave *slave, unsigned int len, return 0; }
-static int davinci_spi_write(struct spi_slave *slave, unsigned int len, +static int davinci_spi_write(struct davinci_spi_slave *ds, unsigned int len, const u8 *txp, unsigned long flags) { - struct davinci_spi_slave *ds = to_davinci_spi(slave); unsigned int data1_reg_val;
/* enable CS hold and clear the data bits */ data1_reg_val = ((1 << SPIDAT1_CSHOLD_SHIFT) | - (slave->cs << SPIDAT1_CSNR_SHIFT)); + (ds->cur_cs << SPIDAT1_CSNR_SHIFT));
/* wait till TXFULL is deasserted */ while (readl(&ds->regs->buf) & SPIBUF_TXFULL_MASK) @@ -209,16 +213,15 @@ static int davinci_spi_write(struct spi_slave *slave, unsigned int len, return 0; }
-#ifndef CONFIG_SPI_HALF_DUPLEX -static int davinci_spi_read_write(struct spi_slave *slave, unsigned int len, - u8 *rxp, const u8 *txp, unsigned long flags) +static int davinci_spi_read_write(struct davinci_spi_slave *ds, unsigned + int len, u8 *rxp, const u8 *txp, + unsigned long flags) { - struct davinci_spi_slave *ds = to_davinci_spi(slave); unsigned int data1_reg_val;
/* enable CS hold and clear the data bits */ data1_reg_val = ((1 << SPIDAT1_CSHOLD_SHIFT) | - (slave->cs << SPIDAT1_CSNR_SHIFT)); + (ds->cur_cs << SPIDAT1_CSNR_SHIFT));
/* wait till TXFULL is deasserted */ while (readl(&ds->regs->buf) & SPIBUF_TXFULL_MASK) @@ -237,7 +240,115 @@ static int davinci_spi_read_write(struct spi_slave *slave, unsigned int len,
return 0; } -#endif + + +static int __davinci_spi_claim_bus(struct davinci_spi_slave *ds, int cs) +{ + unsigned int mode = 0, scalar; + + /* Enable the SPI hardware */ + writel(SPIGCR0_SPIRST_MASK, &ds->regs->gcr0); + udelay(1000); + writel(SPIGCR0_SPIENA_MASK, &ds->regs->gcr0); + + /* Set master mode, powered up and not activated */ + writel(SPIGCR1_MASTER_MASK | SPIGCR1_CLKMOD_MASK, &ds->regs->gcr1); + + /* CS, CLK, SIMO and SOMI are functional pins */ + writel(((1 << cs) | SPIPC0_CLKFUN_MASK | + SPIPC0_DOFUN_MASK | SPIPC0_DIFUN_MASK), &ds->regs->pc0); + + /* setup format */ + scalar = ((CONFIG_SYS_SPI_CLK / ds->freq) - 1) & 0xFF; + + /* + * Use following format: + * character length = 8, + * MSB shifted out first + */ + if (ds->mode & SPI_CPOL) + mode |= SPI_CPOL; + if (!(ds->mode & SPI_CPHA)) + mode |= SPI_CPHA; + writel(8 | (scalar << SPIFMT_PRESCALE_SHIFT) | + (mode << SPIFMT_PHASE_SHIFT), &ds->regs->fmt0); + + /* + * Including a minor delay. No science here. Should be good even with + * no delay + */ + writel((50 << SPI_C2TDELAY_SHIFT) | + (50 << SPI_T2CDELAY_SHIFT), &ds->regs->delay); + + /* default chip select register */ + writel(SPIDEF_CSDEF0_MASK, &ds->regs->def); + + /* no interrupts */ + writel(0, &ds->regs->int0); + writel(0, &ds->regs->lvl); + + /* enable SPI */ + writel((readl(&ds->regs->gcr1) | SPIGCR1_SPIENA_MASK), &ds->regs->gcr1); + + return 0; +} + +static int __davinci_spi_release_bus(struct davinci_spi_slave *ds) +{ + /* Disable the SPI hardware */ + writel(SPIGCR0_SPIRST_MASK, &ds->regs->gcr0); + + return 0; +} + +static int __davinci_spi_xfer(struct davinci_spi_slave *ds, + unsigned int bitlen, const void *dout, void *din, + unsigned long flags) +{ + unsigned int len; + + if (bitlen == 0) + /* Finish any previously submitted transfers */ + goto out; + + /* + * It's not clear how non-8-bit-aligned transfers are supposed to be + * represented as a stream of bytes...this is a limitation of + * the current SPI interface - here we terminate on receiving such a + * transfer request. + */ + if (bitlen % 8) { + /* Errors always terminate an ongoing transfer */ + flags |= SPI_XFER_END; + goto out; + } + + len = bitlen / 8; + + if (!dout) + return davinci_spi_read(ds, len, din, flags); + if (!din) + return davinci_spi_write(ds, len, dout, flags); + if (!ds->half_duplex) + return davinci_spi_read_write(ds, len, din, dout, flags); + + printf("SPI full duplex not supported\n"); + flags |= SPI_XFER_END; + +out: + if (flags & SPI_XFER_END) { + u8 dummy = 0; + davinci_spi_write(ds, 1, &dummy, flags); + } + return 0; +} + +#ifndef CONFIG_DM_SPI + +static inline struct davinci_spi_slave *to_davinci_spi(struct spi_slave *slave) +{ + return container_of(slave, struct davinci_spi_slave, slave); +}
int spi_cs_is_valid(unsigned int bus, unsigned int cs) { @@ -313,6 +424,7 @@ struct spi_slave *spi_setup_slave(unsigned int bus, unsigned int cs, }
ds->freq = max_hz; + ds->mode = mode;
return &ds->slave; } @@ -324,104 +436,140 @@ void spi_free_slave(struct spi_slave *slave) free(ds); }
+int spi_xfer(struct spi_slave *slave, unsigned int bitlen, + const void *dout, void *din, unsigned long flags) +{ + struct davinci_spi_slave *ds = to_davinci_spi(slave); + + ds->cur_cs = slave->cs; + + return __davinci_spi_xfer(ds, bitlen, dout, din, flags); +} + int spi_claim_bus(struct spi_slave *slave) { struct davinci_spi_slave *ds = to_davinci_spi(slave); - unsigned int scalar;
- /* Enable the SPI hardware */ - writel(SPIGCR0_SPIRST_MASK, &ds->regs->gcr0); - udelay(1000); - writel(SPIGCR0_SPIENA_MASK, &ds->regs->gcr0); +#ifdef CONFIG_SPI_HALF_DUPLEX + ds->half_duplex = true; +#else + ds->half_duplex = false; +#endif + return __davinci_spi_claim_bus(ds, ds->slave.cs); +}
- /* Set master mode, powered up and not activated */ - writel(SPIGCR1_MASTER_MASK | SPIGCR1_CLKMOD_MASK, &ds->regs->gcr1); +void spi_release_bus(struct spi_slave *slave) +{ + struct davinci_spi_slave *ds = to_davinci_spi(slave);
- /* CS, CLK, SIMO and SOMI are functional pins */ - writel(((1 << slave->cs) | SPIPC0_CLKFUN_MASK | - SPIPC0_DOFUN_MASK | SPIPC0_DIFUN_MASK), &ds->regs->pc0); + __davinci_spi_release_bus(ds); +}
- /* setup format */ - scalar = ((CONFIG_SYS_SPI_CLK / ds->freq) - 1) & 0xFF; +#else +static int davinci_spi_set_speed(struct udevice *bus, uint max_hz) +{ + struct davinci_spi_slave *ds = dev_get_priv(bus);
- /* - * Use following format: - * character length = 8, - * clock signal delayed by half clk cycle, - * clock low in idle state - Mode 0, - * MSB shifted out first - */ - writel(8 | (scalar << SPIFMT_PRESCALE_SHIFT) | - (1 << SPIFMT_PHASE_SHIFT), &ds->regs->fmt0); + debug("%s speed %u\n", __func__, max_hz); + if (max_hz > CONFIG_SYS_SPI_CLK / 2) + return -EINVAL;
- /* - * Including a minor delay. No science here. Should be good even with - * no delay - */ - writel((50 << SPI_C2TDELAY_SHIFT) | - (50 << SPI_T2CDELAY_SHIFT), &ds->regs->delay); + ds->freq = max_hz;
- /* default chip select register */ - writel(SPIDEF_CSDEF0_MASK, &ds->regs->def); + return 0; +}
- /* no interrupts */ - writel(0, &ds->regs->int0); - writel(0, &ds->regs->lvl); +static int davinci_spi_set_mode(struct udevice *bus, uint mode) +{ + struct davinci_spi_slave *ds = dev_get_priv(bus);
- /* enable SPI */ - writel((readl(&ds->regs->gcr1) | SPIGCR1_SPIENA_MASK), &ds->regs->gcr1); + debug("%s mode %u\n", __func__, mode); + ds->mode = mode;
return 0; }
-void spi_release_bus(struct spi_slave *slave) +static int davinci_spi_claim_bus(struct udevice *dev) { - struct davinci_spi_slave *ds = to_davinci_spi(slave); + struct dm_spi_slave_platdata *slave_plat = + dev_get_parent_platdata(dev); + struct udevice *bus = dev->parent; + struct davinci_spi_slave *ds = dev_get_priv(bus); + + if (slave_plat->cs >= ds->num_cs) { + printf("Invalid SPI chipselect\n"); + return -EINVAL; + } + ds->half_duplex = slave_plat->mode & SPI_PREAMBLE;
- /* Disable the SPI hardware */ - writel(SPIGCR0_SPIRST_MASK, &ds->regs->gcr0); + return __davinci_spi_claim_bus(ds, slave_plat->cs); }
-int spi_xfer(struct spi_slave *slave, unsigned int bitlen, - const void *dout, void *din, unsigned long flags) +static int davinci_spi_release_bus(struct udevice *dev) { - unsigned int len; + struct davinci_spi_slave *ds = dev_get_priv(dev->parent);
- if (bitlen == 0) - /* Finish any previously submitted transfers */ - goto out; + return __davinci_spi_release_bus(ds); +}
- /* - * It's not clear how non-8-bit-aligned transfers are supposed to be - * represented as a stream of bytes...this is a limitation of - * the current SPI interface - here we terminate on receiving such a - * transfer request. - */ - if (bitlen % 8) { - /* Errors always terminate an ongoing transfer */ - flags |= SPI_XFER_END; - goto out; +static int davinci_spi_xfer(struct udevice *dev, unsigned int bitlen, + const void *dout, void *din, + unsigned long flags) +{ + struct dm_spi_slave_platdata *slave = + dev_get_parent_platdata(dev); + struct udevice *bus = dev->parent; + struct davinci_spi_slave *ds = dev_get_priv(bus); + + if (slave->cs >= ds->num_cs) { + printf("Invalid SPI chipselect\n"); + return -EINVAL; } + ds->cur_cs = slave->cs;
- len = bitlen / 8; + return __davinci_spi_xfer(ds, bitlen, dout, din, flags); +}
- if (!dout) - return davinci_spi_read(slave, len, din, flags); - else if (!din) - return davinci_spi_write(slave, len, dout, flags); -#ifndef CONFIG_SPI_HALF_DUPLEX - else - return davinci_spi_read_write(slave, len, din, dout, flags); -#else - printf("SPI full duplex transaction requested with " - "CONFIG_SPI_HALF_DUPLEX defined.\n"); - flags |= SPI_XFER_END; -#endif +static int davinci_spi_probe(struct udevice *bus) +{ + /* Nothing to do */ + return 0; +} + +static int davinci_ofdata_to_platadata(struct udevice *bus) +{ + struct davinci_spi_slave *ds = dev_get_priv(bus); + const void *blob = gd->fdt_blob; + int node = bus->of_offset; + + ds->regs = map_physmem(dev_get_addr(bus), + sizeof(struct davinci_spi_regs), MAP_NOCACHE); + ds->num_cs = fdtdec_get_int(blob, node, "num-cs", 4);
-out: - if (flags & SPI_XFER_END) { - u8 dummy = 0; - davinci_spi_write(slave, 1, &dummy, flags); - } return 0; } + +static const struct dm_spi_ops davinci_spi_ops = { + .claim_bus = davinci_spi_claim_bus, + .release_bus = davinci_spi_release_bus, + .xfer = davinci_spi_xfer, + .set_speed = davinci_spi_set_speed, + .set_mode = davinci_spi_set_mode, +}; + +static const struct udevice_id davinci_spi_ids[] = { + { .compatible = "ti,keystone-spi" }, + { .compatible = "ti,dm6441-spi" }, + { } +}; + +U_BOOT_DRIVER(davinci_spi) = { + .name = "davinci_spi", + .id = UCLASS_SPI, + .of_match = davinci_spi_ids, + .ops = &davinci_spi_ops, + .ofdata_to_platdata = davinci_ofdata_to_platadata, + .priv_auto_alloc_size = sizeof(struct davinci_spi_slave), + .probe = davinci_spi_probe, +}; +#endif

On Tue, Apr 12, 2016 at 05:03:17PM +0530, Vignesh R wrote:
Convert davinci_spi driver to comply with SPI DM framework.
Signed-off-by: Vignesh R vigneshr@ti.com
Reviewed-by: Tom Rini trini@konsulko.com

On 12 April 2016 at 05:33, Vignesh R vigneshr@ti.com wrote:
Convert davinci_spi driver to comply with SPI DM framework.
Signed-off-by: Vignesh R vigneshr@ti.com
drivers/spi/davinci_spi.c | 326 +++++++++++++++++++++++++++++++++------------- 1 file changed, 237 insertions(+), 89 deletions(-)
diff --git a/drivers/spi/davinci_spi.c b/drivers/spi/davinci_spi.c index 0bd4f88926f1..838f9fb7fb27 100644 --- a/drivers/spi/davinci_spi.c +++ b/drivers/spi/davinci_spi.c @@ -14,6 +14,7 @@ #include <malloc.h> #include <asm/io.h> #include <asm/arch/hardware.h> +#include <dm.h>
/* SPIGCR0 */ #define SPIGCR0_SPIENA_MASK 0x1 @@ -51,6 +52,7 @@ /* SPIDEF */ #define SPIDEF_CSDEF0_MASK BIT(0)
+#ifndef CONFIG_DM_SPI #define SPI0_BUS 0 #define SPI0_BASE CONFIG_SYS_SPI_BASE /* @@ -83,6 +85,9 @@ #define SPI2_NUM_CS CONFIG_SYS_SPI2_NUM_CS #define SPI2_BASE CONFIG_SYS_SPI2_BASE #endif +#endif
+DECLARE_GLOBAL_DATA_PTR;
/* davinci spi register set */ struct davinci_spi_regs { @@ -114,16 +119,17 @@ struct davinci_spi_regs {
/* davinci spi slave */ struct davinci_spi_slave { +#ifndef CONFIG_DM_SPI struct spi_slave slave; +#endif struct davinci_spi_regs *regs; unsigned int freq;
unsigned int mode;
u8 num_cs;
u8 cur_cs;
bool half_duplex;
Comments on these?
};
-static inline struct davinci_spi_slave *to_davinci_spi(struct spi_slave *slave) -{
return container_of(slave, struct davinci_spi_slave, slave);
-}
/*
- This functions needs to act like a macro to avoid pipeline reloads in the
- loops below. Use always_inline. This gains us about 160KiB/s and the bloat
@@ -144,15 +150,14 @@ static inline u32 davinci_spi_xfer_data(struct davinci_spi_slave *ds, u32 data) return buf_reg_val; }
-static int davinci_spi_read(struct spi_slave *slave, unsigned int len, +static int davinci_spi_read(struct davinci_spi_slave *ds, unsigned int len, u8 *rxp, unsigned long flags) {
struct davinci_spi_slave *ds = to_davinci_spi(slave); unsigned int data1_reg_val; /* enable CS hold, CS[n] and clear the data bits */ data1_reg_val = ((1 << SPIDAT1_CSHOLD_SHIFT) |
(slave->cs << SPIDAT1_CSNR_SHIFT));
(ds->cur_cs << SPIDAT1_CSNR_SHIFT)); /* wait till TXFULL is deasserted */ while (readl(&ds->regs->buf) & SPIBUF_TXFULL_MASK)
@@ -175,15 +180,14 @@ static int davinci_spi_read(struct spi_slave *slave, unsigned int len, return 0; }
-static int davinci_spi_write(struct spi_slave *slave, unsigned int len, +static int davinci_spi_write(struct davinci_spi_slave *ds, unsigned int len, const u8 *txp, unsigned long flags) {
struct davinci_spi_slave *ds = to_davinci_spi(slave); unsigned int data1_reg_val; /* enable CS hold and clear the data bits */ data1_reg_val = ((1 << SPIDAT1_CSHOLD_SHIFT) |
(slave->cs << SPIDAT1_CSNR_SHIFT));
(ds->cur_cs << SPIDAT1_CSNR_SHIFT)); /* wait till TXFULL is deasserted */ while (readl(&ds->regs->buf) & SPIBUF_TXFULL_MASK)
@@ -209,16 +213,15 @@ static int davinci_spi_write(struct spi_slave *slave, unsigned int len, return 0; }
-#ifndef CONFIG_SPI_HALF_DUPLEX -static int davinci_spi_read_write(struct spi_slave *slave, unsigned int len,
u8 *rxp, const u8 *txp, unsigned long flags)
+static int davinci_spi_read_write(struct davinci_spi_slave *ds, unsigned
int len, u8 *rxp, const u8 *txp,
unsigned long flags)
{
struct davinci_spi_slave *ds = to_davinci_spi(slave); unsigned int data1_reg_val; /* enable CS hold and clear the data bits */ data1_reg_val = ((1 << SPIDAT1_CSHOLD_SHIFT) |
(slave->cs << SPIDAT1_CSNR_SHIFT));
(ds->cur_cs << SPIDAT1_CSNR_SHIFT)); /* wait till TXFULL is deasserted */ while (readl(&ds->regs->buf) & SPIBUF_TXFULL_MASK)
@@ -237,7 +240,115 @@ static int davinci_spi_read_write(struct spi_slave *slave, unsigned int len,
return 0;
} -#endif
+static int __davinci_spi_claim_bus(struct davinci_spi_slave *ds, int cs) +{
unsigned int mode = 0, scalar;
/* Enable the SPI hardware */
writel(SPIGCR0_SPIRST_MASK, &ds->regs->gcr0);
udelay(1000);
writel(SPIGCR0_SPIENA_MASK, &ds->regs->gcr0);
/* Set master mode, powered up and not activated */
writel(SPIGCR1_MASTER_MASK | SPIGCR1_CLKMOD_MASK, &ds->regs->gcr1);
/* CS, CLK, SIMO and SOMI are functional pins */
writel(((1 << cs) | SPIPC0_CLKFUN_MASK |
SPIPC0_DOFUN_MASK | SPIPC0_DIFUN_MASK), &ds->regs->pc0);
/* setup format */
scalar = ((CONFIG_SYS_SPI_CLK / ds->freq) - 1) & 0xFF;
/*
* Use following format:
* character length = 8,
* MSB shifted out first
*/
if (ds->mode & SPI_CPOL)
mode |= SPI_CPOL;
if (!(ds->mode & SPI_CPHA))
mode |= SPI_CPHA;
writel(8 | (scalar << SPIFMT_PRESCALE_SHIFT) |
(mode << SPIFMT_PHASE_SHIFT), &ds->regs->fmt0);
/*
* Including a minor delay. No science here. Should be good even with
* no delay
*/
writel((50 << SPI_C2TDELAY_SHIFT) |
(50 << SPI_T2CDELAY_SHIFT), &ds->regs->delay);
/* default chip select register */
writel(SPIDEF_CSDEF0_MASK, &ds->regs->def);
/* no interrupts */
writel(0, &ds->regs->int0);
writel(0, &ds->regs->lvl);
/* enable SPI */
writel((readl(&ds->regs->gcr1) | SPIGCR1_SPIENA_MASK), &ds->regs->gcr1);
return 0;
+}
+static int __davinci_spi_release_bus(struct davinci_spi_slave *ds) +{
/* Disable the SPI hardware */
writel(SPIGCR0_SPIRST_MASK, &ds->regs->gcr0);
return 0;
+}
+static int __davinci_spi_xfer(struct davinci_spi_slave *ds,
unsigned int bitlen, const void *dout, void *din,
unsigned long flags)
+{
unsigned int len;
if (bitlen == 0)
/* Finish any previously submitted transfers */
goto out;
/*
* It's not clear how non-8-bit-aligned transfers are supposed to be
* represented as a stream of bytes...this is a limitation of
* the current SPI interface - here we terminate on receiving such a
* transfer request.
*/
if (bitlen % 8) {
/* Errors always terminate an ongoing transfer */
flags |= SPI_XFER_END;
goto out;
}
len = bitlen / 8;
if (!dout)
return davinci_spi_read(ds, len, din, flags);
if (!din)
return davinci_spi_write(ds, len, dout, flags);
if (!ds->half_duplex)
return davinci_spi_read_write(ds, len, din, dout, flags);
printf("SPI full duplex not supported\n");
flags |= SPI_XFER_END;
+out:
if (flags & SPI_XFER_END) {
u8 dummy = 0;
davinci_spi_write(ds, 1, &dummy, flags);
}
return 0;
+}
+#ifndef CONFIG_DM_SPI
+static inline struct davinci_spi_slave *to_davinci_spi(struct spi_slave *slave) +{
return container_of(slave, struct davinci_spi_slave, slave);
+}
int spi_cs_is_valid(unsigned int bus, unsigned int cs) { @@ -313,6 +424,7 @@ struct spi_slave *spi_setup_slave(unsigned int bus, unsigned int cs, }
ds->freq = max_hz;
ds->mode = mode; return &ds->slave;
} @@ -324,104 +436,140 @@ void spi_free_slave(struct spi_slave *slave) free(ds); }
+int spi_xfer(struct spi_slave *slave, unsigned int bitlen,
const void *dout, void *din, unsigned long flags)
+{
struct davinci_spi_slave *ds = to_davinci_spi(slave);
ds->cur_cs = slave->cs;
return __davinci_spi_xfer(ds, bitlen, dout, din, flags);
+}
int spi_claim_bus(struct spi_slave *slave) { struct davinci_spi_slave *ds = to_davinci_spi(slave);
unsigned int scalar;
/* Enable the SPI hardware */
writel(SPIGCR0_SPIRST_MASK, &ds->regs->gcr0);
udelay(1000);
writel(SPIGCR0_SPIENA_MASK, &ds->regs->gcr0);
+#ifdef CONFIG_SPI_HALF_DUPLEX
ds->half_duplex = true;
+#else
ds->half_duplex = false;
+#endif
return __davinci_spi_claim_bus(ds, ds->slave.cs);
+}
/* Set master mode, powered up and not activated */
writel(SPIGCR1_MASTER_MASK | SPIGCR1_CLKMOD_MASK, &ds->regs->gcr1);
+void spi_release_bus(struct spi_slave *slave) +{
struct davinci_spi_slave *ds = to_davinci_spi(slave);
/* CS, CLK, SIMO and SOMI are functional pins */
writel(((1 << slave->cs) | SPIPC0_CLKFUN_MASK |
SPIPC0_DOFUN_MASK | SPIPC0_DIFUN_MASK), &ds->regs->pc0);
__davinci_spi_release_bus(ds);
+}
/* setup format */
scalar = ((CONFIG_SYS_SPI_CLK / ds->freq) - 1) & 0xFF;
+#else +static int davinci_spi_set_speed(struct udevice *bus, uint max_hz) +{
struct davinci_spi_slave *ds = dev_get_priv(bus);
/*
* Use following format:
* character length = 8,
* clock signal delayed by half clk cycle,
* clock low in idle state - Mode 0,
* MSB shifted out first
*/
writel(8 | (scalar << SPIFMT_PRESCALE_SHIFT) |
(1 << SPIFMT_PHASE_SHIFT), &ds->regs->fmt0);
debug("%s speed %u\n", __func__, max_hz);
if (max_hz > CONFIG_SYS_SPI_CLK / 2)
return -EINVAL;
/*
* Including a minor delay. No science here. Should be good even with
* no delay
*/
writel((50 << SPI_C2TDELAY_SHIFT) |
(50 << SPI_T2CDELAY_SHIFT), &ds->regs->delay);
ds->freq = max_hz;
/* default chip select register */
writel(SPIDEF_CSDEF0_MASK, &ds->regs->def);
return 0;
+}
/* no interrupts */
writel(0, &ds->regs->int0);
writel(0, &ds->regs->lvl);
+static int davinci_spi_set_mode(struct udevice *bus, uint mode) +{
struct davinci_spi_slave *ds = dev_get_priv(bus);
/* enable SPI */
writel((readl(&ds->regs->gcr1) | SPIGCR1_SPIENA_MASK), &ds->regs->gcr1);
debug("%s mode %u\n", __func__, mode);
ds->mode = mode; return 0;
}
-void spi_release_bus(struct spi_slave *slave) +static int davinci_spi_claim_bus(struct udevice *dev) {
struct davinci_spi_slave *ds = to_davinci_spi(slave);
struct dm_spi_slave_platdata *slave_plat =
dev_get_parent_platdata(dev);
struct udevice *bus = dev->parent;
struct davinci_spi_slave *ds = dev_get_priv(bus);
if (slave_plat->cs >= ds->num_cs) {
What is going on here? Why would these be different?
printf("Invalid SPI chipselect\n");
return -EINVAL;
}
ds->half_duplex = slave_plat->mode & SPI_PREAMBLE;
/* Disable the SPI hardware */
writel(SPIGCR0_SPIRST_MASK, &ds->regs->gcr0);
return __davinci_spi_claim_bus(ds, slave_plat->cs);
}
-int spi_xfer(struct spi_slave *slave, unsigned int bitlen,
const void *dout, void *din, unsigned long flags)
+static int davinci_spi_release_bus(struct udevice *dev) {
unsigned int len;
struct davinci_spi_slave *ds = dev_get_priv(dev->parent);
if (bitlen == 0)
/* Finish any previously submitted transfers */
goto out;
return __davinci_spi_release_bus(ds);
+}
/*
* It's not clear how non-8-bit-aligned transfers are supposed to be
* represented as a stream of bytes...this is a limitation of
* the current SPI interface - here we terminate on receiving such a
* transfer request.
*/
if (bitlen % 8) {
/* Errors always terminate an ongoing transfer */
flags |= SPI_XFER_END;
goto out;
+static int davinci_spi_xfer(struct udevice *dev, unsigned int bitlen,
const void *dout, void *din,
unsigned long flags)
+{
struct dm_spi_slave_platdata *slave =
dev_get_parent_platdata(dev);
struct udevice *bus = dev->parent;
struct davinci_spi_slave *ds = dev_get_priv(bus);
if (slave->cs >= ds->num_cs) {
printf("Invalid SPI chipselect\n");
return -EINVAL; }
ds->cur_cs = slave->cs;
len = bitlen / 8;
return __davinci_spi_xfer(ds, bitlen, dout, din, flags);
+}
if (!dout)
return davinci_spi_read(slave, len, din, flags);
else if (!din)
return davinci_spi_write(slave, len, dout, flags);
-#ifndef CONFIG_SPI_HALF_DUPLEX
else
return davinci_spi_read_write(slave, len, din, dout, flags);
-#else
printf("SPI full duplex transaction requested with "
"CONFIG_SPI_HALF_DUPLEX defined.\n");
flags |= SPI_XFER_END;
-#endif +static int davinci_spi_probe(struct udevice *bus) +{
/* Nothing to do */
return 0;
+}
+static int davinci_ofdata_to_platadata(struct udevice *bus) +{
struct davinci_spi_slave *ds = dev_get_priv(bus);
const void *blob = gd->fdt_blob;
int node = bus->of_offset;
ds->regs = map_physmem(dev_get_addr(bus),
sizeof(struct davinci_spi_regs), MAP_NOCACHE);
Can you add a dev_map_physmem() to do this in one step?
ds->num_cs = fdtdec_get_int(blob, node, "num-cs", 4);
-out:
if (flags & SPI_XFER_END) {
u8 dummy = 0;
davinci_spi_write(slave, 1, &dummy, flags);
} return 0;
}
+static const struct dm_spi_ops davinci_spi_ops = {
.claim_bus = davinci_spi_claim_bus,
.release_bus = davinci_spi_release_bus,
.xfer = davinci_spi_xfer,
.set_speed = davinci_spi_set_speed,
.set_mode = davinci_spi_set_mode,
+};
+static const struct udevice_id davinci_spi_ids[] = {
{ .compatible = "ti,keystone-spi" },
{ .compatible = "ti,dm6441-spi" },
{ }
+};
+U_BOOT_DRIVER(davinci_spi) = {
.name = "davinci_spi",
.id = UCLASS_SPI,
.of_match = davinci_spi_ids,
.ops = &davinci_spi_ops,
.ofdata_to_platdata = davinci_ofdata_to_platadata,
.priv_auto_alloc_size = sizeof(struct davinci_spi_slave),
.probe = davinci_spi_probe,
+};
+#endif
2.8.1
Regards, Simon

Hi,
On 04/20/2016 08:10 PM, Simon Glass wrote:
On 12 April 2016 at 05:33, Vignesh R vigneshr@ti.com wrote:
Convert davinci_spi driver to comply with SPI DM framework.
Signed-off-by: Vignesh R vigneshr@ti.com
drivers/spi/davinci_spi.c | 326 +++++++++++++++++++++++++++++++++------------- 1 file changed, 237 insertions(+), 89 deletions(-)
diff --git a/drivers/spi/davinci_spi.c b/drivers/spi/davinci_spi.c index 0bd4f88926f1..838f9fb7fb27 100644 --- a/drivers/spi/davinci_spi.c +++ b/drivers/spi/davinci_spi.c @@ -14,6 +14,7 @@ #include <malloc.h> #include <asm/io.h> #include <asm/arch/hardware.h> +#include <dm.h>
/* SPIGCR0 */ #define SPIGCR0_SPIENA_MASK 0x1 @@ -51,6 +52,7 @@ /* SPIDEF */ #define SPIDEF_CSDEF0_MASK BIT(0)
+#ifndef CONFIG_DM_SPI #define SPI0_BUS 0 #define SPI0_BASE CONFIG_SYS_SPI_BASE /* @@ -83,6 +85,9 @@ #define SPI2_NUM_CS CONFIG_SYS_SPI2_NUM_CS #define SPI2_BASE CONFIG_SYS_SPI2_BASE #endif +#endif
+DECLARE_GLOBAL_DATA_PTR;
/* davinci spi register set */ struct davinci_spi_regs { @@ -114,16 +119,17 @@ struct davinci_spi_regs {
/* davinci spi slave */ struct davinci_spi_slave { +#ifndef CONFIG_DM_SPI struct spi_slave slave; +#endif struct davinci_spi_regs *regs; unsigned int freq;
unsigned int mode;
u8 num_cs;
u8 cur_cs;
bool half_duplex;
Comments on these?
mode - current SPI mode used by SPI controller num_cs - total no of chip-select for this controller cur_cs - chipselect currently used to communicate with slave half_duplex - true if controller/slave supports only half duplex mode of communication
I will add inline comments in v2.
};
-static inline struct davinci_spi_slave *to_davinci_spi(struct spi_slave *slave) -{
return container_of(slave, struct davinci_spi_slave, slave);
-}
/*
- This functions needs to act like a macro to avoid pipeline reloads in the
- loops below. Use always_inline. This gains us about 160KiB/s and the bloat
@@ -144,15 +150,14 @@ static inline u32 davinci_spi_xfer_data(struct davinci_spi_slave *ds, u32 data) return buf_reg_val; }
-static int davinci_spi_read(struct spi_slave *slave, unsigned int len, +static int davinci_spi_read(struct davinci_spi_slave *ds, unsigned int len, u8 *rxp, unsigned long flags) {
struct davinci_spi_slave *ds = to_davinci_spi(slave); unsigned int data1_reg_val; /* enable CS hold, CS[n] and clear the data bits */ data1_reg_val = ((1 << SPIDAT1_CSHOLD_SHIFT) |
(slave->cs << SPIDAT1_CSNR_SHIFT));
(ds->cur_cs << SPIDAT1_CSNR_SHIFT)); /* wait till TXFULL is deasserted */ while (readl(&ds->regs->buf) & SPIBUF_TXFULL_MASK)
@@ -175,15 +180,14 @@ static int davinci_spi_read(struct spi_slave *slave, unsigned int len, return 0; }
-static int davinci_spi_write(struct spi_slave *slave, unsigned int len, +static int davinci_spi_write(struct davinci_spi_slave *ds, unsigned int len, const u8 *txp, unsigned long flags) {
struct davinci_spi_slave *ds = to_davinci_spi(slave); unsigned int data1_reg_val; /* enable CS hold and clear the data bits */ data1_reg_val = ((1 << SPIDAT1_CSHOLD_SHIFT) |
(slave->cs << SPIDAT1_CSNR_SHIFT));
(ds->cur_cs << SPIDAT1_CSNR_SHIFT)); /* wait till TXFULL is deasserted */ while (readl(&ds->regs->buf) & SPIBUF_TXFULL_MASK)
@@ -209,16 +213,15 @@ static int davinci_spi_write(struct spi_slave *slave, unsigned int len, return 0; }
-#ifndef CONFIG_SPI_HALF_DUPLEX -static int davinci_spi_read_write(struct spi_slave *slave, unsigned int len,
u8 *rxp, const u8 *txp, unsigned long flags)
+static int davinci_spi_read_write(struct davinci_spi_slave *ds, unsigned
int len, u8 *rxp, const u8 *txp,
unsigned long flags)
{
struct davinci_spi_slave *ds = to_davinci_spi(slave); unsigned int data1_reg_val; /* enable CS hold and clear the data bits */ data1_reg_val = ((1 << SPIDAT1_CSHOLD_SHIFT) |
(slave->cs << SPIDAT1_CSNR_SHIFT));
(ds->cur_cs << SPIDAT1_CSNR_SHIFT)); /* wait till TXFULL is deasserted */ while (readl(&ds->regs->buf) & SPIBUF_TXFULL_MASK)
@@ -237,7 +240,115 @@ static int davinci_spi_read_write(struct spi_slave *slave, unsigned int len,
return 0;
} -#endif
+static int __davinci_spi_claim_bus(struct davinci_spi_slave *ds, int cs) +{
unsigned int mode = 0, scalar;
/* Enable the SPI hardware */
writel(SPIGCR0_SPIRST_MASK, &ds->regs->gcr0);
udelay(1000);
writel(SPIGCR0_SPIENA_MASK, &ds->regs->gcr0);
/* Set master mode, powered up and not activated */
writel(SPIGCR1_MASTER_MASK | SPIGCR1_CLKMOD_MASK, &ds->regs->gcr1);
/* CS, CLK, SIMO and SOMI are functional pins */
writel(((1 << cs) | SPIPC0_CLKFUN_MASK |
SPIPC0_DOFUN_MASK | SPIPC0_DIFUN_MASK), &ds->regs->pc0);
/* setup format */
scalar = ((CONFIG_SYS_SPI_CLK / ds->freq) - 1) & 0xFF;
/*
* Use following format:
* character length = 8,
* MSB shifted out first
*/
if (ds->mode & SPI_CPOL)
mode |= SPI_CPOL;
if (!(ds->mode & SPI_CPHA))
mode |= SPI_CPHA;
writel(8 | (scalar << SPIFMT_PRESCALE_SHIFT) |
(mode << SPIFMT_PHASE_SHIFT), &ds->regs->fmt0);
/*
* Including a minor delay. No science here. Should be good even with
* no delay
*/
writel((50 << SPI_C2TDELAY_SHIFT) |
(50 << SPI_T2CDELAY_SHIFT), &ds->regs->delay);
/* default chip select register */
writel(SPIDEF_CSDEF0_MASK, &ds->regs->def);
/* no interrupts */
writel(0, &ds->regs->int0);
writel(0, &ds->regs->lvl);
/* enable SPI */
writel((readl(&ds->regs->gcr1) | SPIGCR1_SPIENA_MASK), &ds->regs->gcr1);
return 0;
+}
+static int __davinci_spi_release_bus(struct davinci_spi_slave *ds) +{
/* Disable the SPI hardware */
writel(SPIGCR0_SPIRST_MASK, &ds->regs->gcr0);
return 0;
+}
+static int __davinci_spi_xfer(struct davinci_spi_slave *ds,
unsigned int bitlen, const void *dout, void *din,
unsigned long flags)
+{
unsigned int len;
if (bitlen == 0)
/* Finish any previously submitted transfers */
goto out;
/*
* It's not clear how non-8-bit-aligned transfers are supposed to be
* represented as a stream of bytes...this is a limitation of
* the current SPI interface - here we terminate on receiving such a
* transfer request.
*/
if (bitlen % 8) {
/* Errors always terminate an ongoing transfer */
flags |= SPI_XFER_END;
goto out;
}
len = bitlen / 8;
if (!dout)
return davinci_spi_read(ds, len, din, flags);
if (!din)
return davinci_spi_write(ds, len, dout, flags);
if (!ds->half_duplex)
return davinci_spi_read_write(ds, len, din, dout, flags);
printf("SPI full duplex not supported\n");
flags |= SPI_XFER_END;
+out:
if (flags & SPI_XFER_END) {
u8 dummy = 0;
davinci_spi_write(ds, 1, &dummy, flags);
}
return 0;
+}
+#ifndef CONFIG_DM_SPI
+static inline struct davinci_spi_slave *to_davinci_spi(struct spi_slave *slave) +{
return container_of(slave, struct davinci_spi_slave, slave);
+}
int spi_cs_is_valid(unsigned int bus, unsigned int cs) { @@ -313,6 +424,7 @@ struct spi_slave *spi_setup_slave(unsigned int bus, unsigned int cs, }
ds->freq = max_hz;
ds->mode = mode; return &ds->slave;
} @@ -324,104 +436,140 @@ void spi_free_slave(struct spi_slave *slave) free(ds); }
+int spi_xfer(struct spi_slave *slave, unsigned int bitlen,
const void *dout, void *din, unsigned long flags)
+{
struct davinci_spi_slave *ds = to_davinci_spi(slave);
ds->cur_cs = slave->cs;
return __davinci_spi_xfer(ds, bitlen, dout, din, flags);
+}
int spi_claim_bus(struct spi_slave *slave) { struct davinci_spi_slave *ds = to_davinci_spi(slave);
unsigned int scalar;
/* Enable the SPI hardware */
writel(SPIGCR0_SPIRST_MASK, &ds->regs->gcr0);
udelay(1000);
writel(SPIGCR0_SPIENA_MASK, &ds->regs->gcr0);
+#ifdef CONFIG_SPI_HALF_DUPLEX
ds->half_duplex = true;
+#else
ds->half_duplex = false;
+#endif
return __davinci_spi_claim_bus(ds, ds->slave.cs);
+}
/* Set master mode, powered up and not activated */
writel(SPIGCR1_MASTER_MASK | SPIGCR1_CLKMOD_MASK, &ds->regs->gcr1);
+void spi_release_bus(struct spi_slave *slave) +{
struct davinci_spi_slave *ds = to_davinci_spi(slave);
/* CS, CLK, SIMO and SOMI are functional pins */
writel(((1 << slave->cs) | SPIPC0_CLKFUN_MASK |
SPIPC0_DOFUN_MASK | SPIPC0_DIFUN_MASK), &ds->regs->pc0);
__davinci_spi_release_bus(ds);
+}
/* setup format */
scalar = ((CONFIG_SYS_SPI_CLK / ds->freq) - 1) & 0xFF;
+#else +static int davinci_spi_set_speed(struct udevice *bus, uint max_hz) +{
struct davinci_spi_slave *ds = dev_get_priv(bus);
/*
* Use following format:
* character length = 8,
* clock signal delayed by half clk cycle,
* clock low in idle state - Mode 0,
* MSB shifted out first
*/
writel(8 | (scalar << SPIFMT_PRESCALE_SHIFT) |
(1 << SPIFMT_PHASE_SHIFT), &ds->regs->fmt0);
debug("%s speed %u\n", __func__, max_hz);
if (max_hz > CONFIG_SYS_SPI_CLK / 2)
return -EINVAL;
/*
* Including a minor delay. No science here. Should be good even with
* no delay
*/
writel((50 << SPI_C2TDELAY_SHIFT) |
(50 << SPI_T2CDELAY_SHIFT), &ds->regs->delay);
ds->freq = max_hz;
/* default chip select register */
writel(SPIDEF_CSDEF0_MASK, &ds->regs->def);
return 0;
+}
/* no interrupts */
writel(0, &ds->regs->int0);
writel(0, &ds->regs->lvl);
+static int davinci_spi_set_mode(struct udevice *bus, uint mode) +{
struct davinci_spi_slave *ds = dev_get_priv(bus);
/* enable SPI */
writel((readl(&ds->regs->gcr1) | SPIGCR1_SPIENA_MASK), &ds->regs->gcr1);
debug("%s mode %u\n", __func__, mode);
ds->mode = mode; return 0;
}
-void spi_release_bus(struct spi_slave *slave) +static int davinci_spi_claim_bus(struct udevice *dev) {
struct davinci_spi_slave *ds = to_davinci_spi(slave);
struct dm_spi_slave_platdata *slave_plat =
dev_get_parent_platdata(dev);
struct udevice *bus = dev->parent;
struct davinci_spi_slave *ds = dev_get_priv(bus);
if (slave_plat->cs >= ds->num_cs) {
What is going on here? Why would these be different?
Its just a check to see if probe is called for a non-existing chip-select. ds->num_cs is max no. if chipselect for this controller. slave_plat->cs is the current chipselect being probed. Say if controller has only 4 chip-select line(num-cs = <4> in DT) and sf probe is called as sf probe 1:6 then slave_plat->cs will be 6 whereas ds->num_cs = 4, hence a check to ensure probe fails.
printf("Invalid SPI chipselect\n");
return -EINVAL;
}
ds->half_duplex = slave_plat->mode & SPI_PREAMBLE;
/* Disable the SPI hardware */
writel(SPIGCR0_SPIRST_MASK, &ds->regs->gcr0);
return __davinci_spi_claim_bus(ds, slave_plat->cs);
}
-int spi_xfer(struct spi_slave *slave, unsigned int bitlen,
const void *dout, void *din, unsigned long flags)
+static int davinci_spi_release_bus(struct udevice *dev) {
unsigned int len;
struct davinci_spi_slave *ds = dev_get_priv(dev->parent);
if (bitlen == 0)
/* Finish any previously submitted transfers */
goto out;
return __davinci_spi_release_bus(ds);
+}
/*
* It's not clear how non-8-bit-aligned transfers are supposed to be
* represented as a stream of bytes...this is a limitation of
* the current SPI interface - here we terminate on receiving such a
* transfer request.
*/
if (bitlen % 8) {
/* Errors always terminate an ongoing transfer */
flags |= SPI_XFER_END;
goto out;
+static int davinci_spi_xfer(struct udevice *dev, unsigned int bitlen,
const void *dout, void *din,
unsigned long flags)
+{
struct dm_spi_slave_platdata *slave =
dev_get_parent_platdata(dev);
struct udevice *bus = dev->parent;
struct davinci_spi_slave *ds = dev_get_priv(bus);
if (slave->cs >= ds->num_cs) {
printf("Invalid SPI chipselect\n");
return -EINVAL; }
ds->cur_cs = slave->cs;
len = bitlen / 8;
return __davinci_spi_xfer(ds, bitlen, dout, din, flags);
+}
if (!dout)
return davinci_spi_read(slave, len, din, flags);
else if (!din)
return davinci_spi_write(slave, len, dout, flags);
-#ifndef CONFIG_SPI_HALF_DUPLEX
else
return davinci_spi_read_write(slave, len, din, dout, flags);
-#else
printf("SPI full duplex transaction requested with "
"CONFIG_SPI_HALF_DUPLEX defined.\n");
flags |= SPI_XFER_END;
-#endif +static int davinci_spi_probe(struct udevice *bus) +{
/* Nothing to do */
return 0;
+}
+static int davinci_ofdata_to_platadata(struct udevice *bus) +{
struct davinci_spi_slave *ds = dev_get_priv(bus);
const void *blob = gd->fdt_blob;
int node = bus->of_offset;
ds->regs = map_physmem(dev_get_addr(bus),
sizeof(struct davinci_spi_regs), MAP_NOCACHE);
Can you add a dev_map_physmem() to do this in one step?
Sure, where would you like dev_map_physmem() to reside? In drivers/core/device.c?

i Vignesh,
On 21 April 2016 at 02:42, Vignesh R vigneshr@ti.com wrote:
Hi,
On 04/20/2016 08:10 PM, Simon Glass wrote:
On 12 April 2016 at 05:33, Vignesh R vigneshr@ti.com wrote:
Convert davinci_spi driver to comply with SPI DM framework.
Signed-off-by: Vignesh R vigneshr@ti.com
drivers/spi/davinci_spi.c | 326 +++++++++++++++++++++++++++++++++------------- 1 file changed, 237 insertions(+), 89 deletions(-)
diff --git a/drivers/spi/davinci_spi.c b/drivers/spi/davinci_spi.c index 0bd4f88926f1..838f9fb7fb27 100644 --- a/drivers/spi/davinci_spi.c +++ b/drivers/spi/davinci_spi.c @@ -14,6 +14,7 @@ #include <malloc.h> #include <asm/io.h> #include <asm/arch/hardware.h> +#include <dm.h>
/* SPIGCR0 */ #define SPIGCR0_SPIENA_MASK 0x1 @@ -51,6 +52,7 @@ /* SPIDEF */ #define SPIDEF_CSDEF0_MASK BIT(0)
+#ifndef CONFIG_DM_SPI #define SPI0_BUS 0 #define SPI0_BASE CONFIG_SYS_SPI_BASE /* @@ -83,6 +85,9 @@ #define SPI2_NUM_CS CONFIG_SYS_SPI2_NUM_CS #define SPI2_BASE CONFIG_SYS_SPI2_BASE #endif +#endif
+DECLARE_GLOBAL_DATA_PTR;
/* davinci spi register set */ struct davinci_spi_regs { @@ -114,16 +119,17 @@ struct davinci_spi_regs {
/* davinci spi slave */ struct davinci_spi_slave { +#ifndef CONFIG_DM_SPI struct spi_slave slave; +#endif struct davinci_spi_regs *regs; unsigned int freq;
unsigned int mode;
u8 num_cs;
u8 cur_cs;
bool half_duplex;
Comments on these?
mode - current SPI mode used by SPI controller num_cs - total no of chip-select for this controller cur_cs - chipselect currently used to communicate with slave half_duplex - true if controller/slave supports only half duplex mode of communication
I will add inline comments in v2.
};
-static inline struct davinci_spi_slave *to_davinci_spi(struct spi_slave *slave) -{
return container_of(slave, struct davinci_spi_slave, slave);
-}
/*
- This functions needs to act like a macro to avoid pipeline reloads in the
- loops below. Use always_inline. This gains us about 160KiB/s and the bloat
@@ -144,15 +150,14 @@ static inline u32 davinci_spi_xfer_data(struct davinci_spi_slave *ds, u32 data) return buf_reg_val; }
-static int davinci_spi_read(struct spi_slave *slave, unsigned int len, +static int davinci_spi_read(struct davinci_spi_slave *ds, unsigned int len, u8 *rxp, unsigned long flags) {
struct davinci_spi_slave *ds = to_davinci_spi(slave); unsigned int data1_reg_val; /* enable CS hold, CS[n] and clear the data bits */ data1_reg_val = ((1 << SPIDAT1_CSHOLD_SHIFT) |
(slave->cs << SPIDAT1_CSNR_SHIFT));
(ds->cur_cs << SPIDAT1_CSNR_SHIFT)); /* wait till TXFULL is deasserted */ while (readl(&ds->regs->buf) & SPIBUF_TXFULL_MASK)
@@ -175,15 +180,14 @@ static int davinci_spi_read(struct spi_slave *slave, unsigned int len, return 0; }
-static int davinci_spi_write(struct spi_slave *slave, unsigned int len, +static int davinci_spi_write(struct davinci_spi_slave *ds, unsigned int len, const u8 *txp, unsigned long flags) {
struct davinci_spi_slave *ds = to_davinci_spi(slave); unsigned int data1_reg_val; /* enable CS hold and clear the data bits */ data1_reg_val = ((1 << SPIDAT1_CSHOLD_SHIFT) |
(slave->cs << SPIDAT1_CSNR_SHIFT));
(ds->cur_cs << SPIDAT1_CSNR_SHIFT)); /* wait till TXFULL is deasserted */ while (readl(&ds->regs->buf) & SPIBUF_TXFULL_MASK)
@@ -209,16 +213,15 @@ static int davinci_spi_write(struct spi_slave *slave, unsigned int len, return 0; }
-#ifndef CONFIG_SPI_HALF_DUPLEX -static int davinci_spi_read_write(struct spi_slave *slave, unsigned int len,
u8 *rxp, const u8 *txp, unsigned long flags)
+static int davinci_spi_read_write(struct davinci_spi_slave *ds, unsigned
int len, u8 *rxp, const u8 *txp,
unsigned long flags)
{
struct davinci_spi_slave *ds = to_davinci_spi(slave); unsigned int data1_reg_val; /* enable CS hold and clear the data bits */ data1_reg_val = ((1 << SPIDAT1_CSHOLD_SHIFT) |
(slave->cs << SPIDAT1_CSNR_SHIFT));
(ds->cur_cs << SPIDAT1_CSNR_SHIFT)); /* wait till TXFULL is deasserted */ while (readl(&ds->regs->buf) & SPIBUF_TXFULL_MASK)
@@ -237,7 +240,115 @@ static int davinci_spi_read_write(struct spi_slave *slave, unsigned int len,
return 0;
} -#endif
+static int __davinci_spi_claim_bus(struct davinci_spi_slave *ds, int cs) +{
unsigned int mode = 0, scalar;
/* Enable the SPI hardware */
writel(SPIGCR0_SPIRST_MASK, &ds->regs->gcr0);
udelay(1000);
writel(SPIGCR0_SPIENA_MASK, &ds->regs->gcr0);
/* Set master mode, powered up and not activated */
writel(SPIGCR1_MASTER_MASK | SPIGCR1_CLKMOD_MASK, &ds->regs->gcr1);
/* CS, CLK, SIMO and SOMI are functional pins */
writel(((1 << cs) | SPIPC0_CLKFUN_MASK |
SPIPC0_DOFUN_MASK | SPIPC0_DIFUN_MASK), &ds->regs->pc0);
/* setup format */
scalar = ((CONFIG_SYS_SPI_CLK / ds->freq) - 1) & 0xFF;
/*
* Use following format:
* character length = 8,
* MSB shifted out first
*/
if (ds->mode & SPI_CPOL)
mode |= SPI_CPOL;
if (!(ds->mode & SPI_CPHA))
mode |= SPI_CPHA;
writel(8 | (scalar << SPIFMT_PRESCALE_SHIFT) |
(mode << SPIFMT_PHASE_SHIFT), &ds->regs->fmt0);
/*
* Including a minor delay. No science here. Should be good even with
* no delay
*/
writel((50 << SPI_C2TDELAY_SHIFT) |
(50 << SPI_T2CDELAY_SHIFT), &ds->regs->delay);
/* default chip select register */
writel(SPIDEF_CSDEF0_MASK, &ds->regs->def);
/* no interrupts */
writel(0, &ds->regs->int0);
writel(0, &ds->regs->lvl);
/* enable SPI */
writel((readl(&ds->regs->gcr1) | SPIGCR1_SPIENA_MASK), &ds->regs->gcr1);
return 0;
+}
+static int __davinci_spi_release_bus(struct davinci_spi_slave *ds) +{
/* Disable the SPI hardware */
writel(SPIGCR0_SPIRST_MASK, &ds->regs->gcr0);
return 0;
+}
+static int __davinci_spi_xfer(struct davinci_spi_slave *ds,
unsigned int bitlen, const void *dout, void *din,
unsigned long flags)
+{
unsigned int len;
if (bitlen == 0)
/* Finish any previously submitted transfers */
goto out;
/*
* It's not clear how non-8-bit-aligned transfers are supposed to be
* represented as a stream of bytes...this is a limitation of
* the current SPI interface - here we terminate on receiving such a
* transfer request.
*/
if (bitlen % 8) {
/* Errors always terminate an ongoing transfer */
flags |= SPI_XFER_END;
goto out;
}
len = bitlen / 8;
if (!dout)
return davinci_spi_read(ds, len, din, flags);
if (!din)
return davinci_spi_write(ds, len, dout, flags);
if (!ds->half_duplex)
return davinci_spi_read_write(ds, len, din, dout, flags);
printf("SPI full duplex not supported\n");
flags |= SPI_XFER_END;
+out:
if (flags & SPI_XFER_END) {
u8 dummy = 0;
davinci_spi_write(ds, 1, &dummy, flags);
}
return 0;
+}
+#ifndef CONFIG_DM_SPI
+static inline struct davinci_spi_slave *to_davinci_spi(struct spi_slave *slave) +{
return container_of(slave, struct davinci_spi_slave, slave);
+}
int spi_cs_is_valid(unsigned int bus, unsigned int cs) { @@ -313,6 +424,7 @@ struct spi_slave *spi_setup_slave(unsigned int bus, unsigned int cs, }
ds->freq = max_hz;
ds->mode = mode; return &ds->slave;
} @@ -324,104 +436,140 @@ void spi_free_slave(struct spi_slave *slave) free(ds); }
+int spi_xfer(struct spi_slave *slave, unsigned int bitlen,
const void *dout, void *din, unsigned long flags)
+{
struct davinci_spi_slave *ds = to_davinci_spi(slave);
ds->cur_cs = slave->cs;
return __davinci_spi_xfer(ds, bitlen, dout, din, flags);
+}
int spi_claim_bus(struct spi_slave *slave) { struct davinci_spi_slave *ds = to_davinci_spi(slave);
unsigned int scalar;
/* Enable the SPI hardware */
writel(SPIGCR0_SPIRST_MASK, &ds->regs->gcr0);
udelay(1000);
writel(SPIGCR0_SPIENA_MASK, &ds->regs->gcr0);
+#ifdef CONFIG_SPI_HALF_DUPLEX
ds->half_duplex = true;
+#else
ds->half_duplex = false;
+#endif
return __davinci_spi_claim_bus(ds, ds->slave.cs);
+}
/* Set master mode, powered up and not activated */
writel(SPIGCR1_MASTER_MASK | SPIGCR1_CLKMOD_MASK, &ds->regs->gcr1);
+void spi_release_bus(struct spi_slave *slave) +{
struct davinci_spi_slave *ds = to_davinci_spi(slave);
/* CS, CLK, SIMO and SOMI are functional pins */
writel(((1 << slave->cs) | SPIPC0_CLKFUN_MASK |
SPIPC0_DOFUN_MASK | SPIPC0_DIFUN_MASK), &ds->regs->pc0);
__davinci_spi_release_bus(ds);
+}
/* setup format */
scalar = ((CONFIG_SYS_SPI_CLK / ds->freq) - 1) & 0xFF;
+#else +static int davinci_spi_set_speed(struct udevice *bus, uint max_hz) +{
struct davinci_spi_slave *ds = dev_get_priv(bus);
/*
* Use following format:
* character length = 8,
* clock signal delayed by half clk cycle,
* clock low in idle state - Mode 0,
* MSB shifted out first
*/
writel(8 | (scalar << SPIFMT_PRESCALE_SHIFT) |
(1 << SPIFMT_PHASE_SHIFT), &ds->regs->fmt0);
debug("%s speed %u\n", __func__, max_hz);
if (max_hz > CONFIG_SYS_SPI_CLK / 2)
return -EINVAL;
/*
* Including a minor delay. No science here. Should be good even with
* no delay
*/
writel((50 << SPI_C2TDELAY_SHIFT) |
(50 << SPI_T2CDELAY_SHIFT), &ds->regs->delay);
ds->freq = max_hz;
/* default chip select register */
writel(SPIDEF_CSDEF0_MASK, &ds->regs->def);
return 0;
+}
/* no interrupts */
writel(0, &ds->regs->int0);
writel(0, &ds->regs->lvl);
+static int davinci_spi_set_mode(struct udevice *bus, uint mode) +{
struct davinci_spi_slave *ds = dev_get_priv(bus);
/* enable SPI */
writel((readl(&ds->regs->gcr1) | SPIGCR1_SPIENA_MASK), &ds->regs->gcr1);
debug("%s mode %u\n", __func__, mode);
ds->mode = mode; return 0;
}
-void spi_release_bus(struct spi_slave *slave) +static int davinci_spi_claim_bus(struct udevice *dev) {
struct davinci_spi_slave *ds = to_davinci_spi(slave);
struct dm_spi_slave_platdata *slave_plat =
dev_get_parent_platdata(dev);
struct udevice *bus = dev->parent;
struct davinci_spi_slave *ds = dev_get_priv(bus);
if (slave_plat->cs >= ds->num_cs) {
What is going on here? Why would these be different?
Its just a check to see if probe is called for a non-existing chip-select. ds->num_cs is max no. if chipselect for this controller. slave_plat->cs is the current chipselect being probed. Say if controller has only 4 chip-select line(num-cs = <4> in DT) and sf probe is called as sf probe 1:6 then slave_plat->cs will be 6 whereas ds->num_cs = 4, hence a check to ensure probe fails.
printf("Invalid SPI chipselect\n");
return -EINVAL;
}
ds->half_duplex = slave_plat->mode & SPI_PREAMBLE;
/* Disable the SPI hardware */
writel(SPIGCR0_SPIRST_MASK, &ds->regs->gcr0);
return __davinci_spi_claim_bus(ds, slave_plat->cs);
}
-int spi_xfer(struct spi_slave *slave, unsigned int bitlen,
const void *dout, void *din, unsigned long flags)
+static int davinci_spi_release_bus(struct udevice *dev) {
unsigned int len;
struct davinci_spi_slave *ds = dev_get_priv(dev->parent);
if (bitlen == 0)
/* Finish any previously submitted transfers */
goto out;
return __davinci_spi_release_bus(ds);
+}
/*
* It's not clear how non-8-bit-aligned transfers are supposed to be
* represented as a stream of bytes...this is a limitation of
* the current SPI interface - here we terminate on receiving such a
* transfer request.
*/
if (bitlen % 8) {
/* Errors always terminate an ongoing transfer */
flags |= SPI_XFER_END;
goto out;
+static int davinci_spi_xfer(struct udevice *dev, unsigned int bitlen,
const void *dout, void *din,
unsigned long flags)
+{
struct dm_spi_slave_platdata *slave =
dev_get_parent_platdata(dev);
struct udevice *bus = dev->parent;
struct davinci_spi_slave *ds = dev_get_priv(bus);
if (slave->cs >= ds->num_cs) {
printf("Invalid SPI chipselect\n");
return -EINVAL; }
ds->cur_cs = slave->cs;
len = bitlen / 8;
return __davinci_spi_xfer(ds, bitlen, dout, din, flags);
+}
if (!dout)
return davinci_spi_read(slave, len, din, flags);
else if (!din)
return davinci_spi_write(slave, len, dout, flags);
-#ifndef CONFIG_SPI_HALF_DUPLEX
else
return davinci_spi_read_write(slave, len, din, dout, flags);
-#else
printf("SPI full duplex transaction requested with "
"CONFIG_SPI_HALF_DUPLEX defined.\n");
flags |= SPI_XFER_END;
-#endif +static int davinci_spi_probe(struct udevice *bus) +{
/* Nothing to do */
return 0;
+}
+static int davinci_ofdata_to_platadata(struct udevice *bus) +{
struct davinci_spi_slave *ds = dev_get_priv(bus);
const void *blob = gd->fdt_blob;
int node = bus->of_offset;
ds->regs = map_physmem(dev_get_addr(bus),
sizeof(struct davinci_spi_regs), MAP_NOCACHE);
Can you add a dev_map_physmem() to do this in one step?
Sure, where would you like dev_map_physmem() to reside? In drivers/core/device.c?
Yes please.
Regards, Simon

Hi,
On 05/02/2016 12:25 AM, Simon Glass wrote:
i Vignesh,
On 21 April 2016 at 02:42, Vignesh R vigneshr@ti.com wrote:
[...]
+static int davinci_ofdata_to_platadata(struct udevice *bus) +{
struct davinci_spi_slave *ds = dev_get_priv(bus);
const void *blob = gd->fdt_blob;
int node = bus->of_offset;
ds->regs = map_physmem(dev_get_addr(bus),
sizeof(struct davinci_spi_regs), MAP_NOCACHE);
Can you add a dev_map_physmem() to do this in one step?
Sure, where would you like dev_map_physmem() to reside? In drivers/core/device.c?
Yes please.
I already posted v2 with this change: https://www.mail-archive.com/u-boot@lists.denx.de/msg210771.html

Since Keystone2 devices do not have support DM in SPL, do not define DM_SPI and DM_SPI_FLASH for SPL build.
Signed-off-by: Vignesh R vigneshr@ti.com --- include/configs/ti_armv7_keystone2.h | 4 ++++ 1 file changed, 4 insertions(+)
diff --git a/include/configs/ti_armv7_keystone2.h b/include/configs/ti_armv7_keystone2.h index 41185a159786..51d5c46f088e 100644 --- a/include/configs/ti_armv7_keystone2.h +++ b/include/configs/ti_armv7_keystone2.h @@ -89,6 +89,10 @@ #define CONFIG_SYS_SPI2 #define CONFIG_SYS_SPI2_BASE KS2_SPI2_BASE #define CONFIG_SYS_SPI2_NUM_CS 4 +#ifdef CONFIG_SPL_BUILD +#undef CONFIG_DM_SPI +#undef CONFIG_DM_SPI_FLASH +#endif
/* Network Configuration */ #define CONFIG_PHYLIB

On Tue, Apr 12, 2016 at 05:03:18PM +0530, Vignesh R wrote:
Since Keystone2 devices do not have support DM in SPL, do not define DM_SPI and DM_SPI_FLASH for SPL build.
Signed-off-by: Vignesh R vigneshr@ti.com
Reviewed-by: Tom Rini trini@konsulko.com

Add aliases for SPI nodes in order for it to be probed by the DM framework.
Signed-off-by: Vignesh R vigneshr@ti.com --- arch/arm/dts/keystone.dtsi | 3 +++ 1 file changed, 3 insertions(+)
diff --git a/arch/arm/dts/keystone.dtsi b/arch/arm/dts/keystone.dtsi index f39b969f8d43..be97f3f21f92 100644 --- a/arch/arm/dts/keystone.dtsi +++ b/arch/arm/dts/keystone.dtsi @@ -19,6 +19,9 @@
aliases { serial0 = &uart0; + spi0 = &spi0; + spi1 = &spi1; + spi2 = &spi2; };
chosen {

On Tue, Apr 12, 2016 at 05:03:19PM +0530, Vignesh R wrote:
Add aliases for SPI nodes in order for it to be probed by the DM framework.
Signed-off-by: Vignesh R vigneshr@ti.com
Reviewed-by: Tom Rini trini@konsulko.com
... but this is going up to the kernel too, yes?

On 04/12/2016 10:54 PM, Tom Rini wrote:
On Tue, Apr 12, 2016 at 05:03:19PM +0530, Vignesh R wrote:
Add aliases for SPI nodes in order for it to be probed by the DM framework.
Signed-off-by: Vignesh R vigneshr@ti.com
Reviewed-by: Tom Rini trini@konsulko.com
... but this is going up to the kernel too, yes?
Patch posted: https://patchwork.kernel.org/patch/8820581/

Now that davinci_spi driver has been converted to DM framework, enable the same in DT. Also add "spi-flash" as compatible property to n25q128a11 node as it is required for flash device to be probed in U-Boot.
Signed-off-by: Vignesh R vigneshr@ti.com --- arch/arm/dts/k2hk-evm.dts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/arch/arm/dts/k2hk-evm.dts b/arch/arm/dts/k2hk-evm.dts index 660ebf58d547..c5cad2c9da80 100644 --- a/arch/arm/dts/k2hk-evm.dts +++ b/arch/arm/dts/k2hk-evm.dts @@ -147,10 +147,11 @@ };
&spi0 { + status = "okay"; nor_flash: n25q128a11@0 { #address-cells = <1>; #size-cells = <1>; - compatible = "Micron,n25q128a11"; + compatible = "Micron,n25q128a11", "spi-flash"; spi-max-frequency = <54000000>; m25p,fast-read; reg = <0>;

On Tue, Apr 12, 2016 at 05:03:20PM +0530, Vignesh R wrote:
Now that davinci_spi driver has been converted to DM framework, enable the same in DT. Also add "spi-flash" as compatible property to n25q128a11 node as it is required for flash device to be probed in U-Boot.
Signed-off-by: Vignesh R vigneshr@ti.com
Reviewed-by: Tom Rini trini@konsulko.com

Enable SPI and SPI Flash driver model as K2HK SPI controller driver supports driver model.
Signed-off-by: Vignesh R vigneshr@ti.com --- configs/k2hk_evm_defconfig | 2 ++ 1 file changed, 2 insertions(+)
diff --git a/configs/k2hk_evm_defconfig b/configs/k2hk_evm_defconfig index 83efcbba0fbb..4c36aadaa9eb 100644 --- a/configs/k2hk_evm_defconfig +++ b/configs/k2hk_evm_defconfig @@ -11,6 +11,8 @@ CONFIG_SYS_PROMPT="K2HK EVM # " # CONFIG_CMD_SETEXPR is not set CONFIG_OF_CONTROL=y CONFIG_DM=y +CONFIG_DM_SPI=y +CONFIG_DM_SPI_FLASH=y CONFIG_SPI_FLASH=y CONFIG_SPI_FLASH_STMICRO=y CONFIG_DM_ETH=y

On Tue, Apr 12, 2016 at 05:03:21PM +0530, Vignesh R wrote:
Enable SPI and SPI Flash driver model as K2HK SPI controller driver supports driver model.
Signed-off-by: Vignesh R vigneshr@ti.com
Reviewed-by: Tom Rini trini@konsulko.com

Now that davinci_spi driver has been converted to DM framework, enable the same in DT. Also add "spi-flash" as compatible property to n25q128a11 node as it is required for flash device to be probed in U-Boot.
Signed-off-by: Vignesh R vigneshr@ti.com --- arch/arm/dts/k2e-evm.dts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/arch/arm/dts/k2e-evm.dts b/arch/arm/dts/k2e-evm.dts index 50c83c21d911..e2c3fb49102a 100644 --- a/arch/arm/dts/k2e-evm.dts +++ b/arch/arm/dts/k2e-evm.dts @@ -119,10 +119,11 @@ };
&spi0 { + status = "okay"; nor_flash: n25q128a11@0 { #address-cells = <1>; #size-cells = <1>; - compatible = "Micron,n25q128a11"; + compatible = "Micron,n25q128a11", "spi-flash"; spi-max-frequency = <54000000>; m25p,fast-read; reg = <0>;

On Tue, Apr 12, 2016 at 05:03:22PM +0530, Vignesh R wrote:
Now that davinci_spi driver has been converted to DM framework, enable the same in DT. Also add "spi-flash" as compatible property to n25q128a11 node as it is required for flash device to be probed in U-Boot.
Signed-off-by: Vignesh R vigneshr@ti.com
Reviewed-by: Tom Rini trini@konsulko.com

Enable SPI and SPI Flash driver model as K2E SPI controller driver supports driver model.
Signed-off-by: Vignesh R vigneshr@ti.com --- configs/k2e_evm_defconfig | 2 ++ 1 file changed, 2 insertions(+)
diff --git a/configs/k2e_evm_defconfig b/configs/k2e_evm_defconfig index a3fa758ac3f1..958e53d3a3d6 100644 --- a/configs/k2e_evm_defconfig +++ b/configs/k2e_evm_defconfig @@ -11,6 +11,8 @@ CONFIG_SYS_PROMPT="K2E EVM # " # CONFIG_CMD_SETEXPR is not set CONFIG_OF_CONTROL=y CONFIG_DM=y +CONFIG_DM_SPI=y +CONFIG_DM_SPI_FLASH=y CONFIG_SPI_FLASH=y CONFIG_SPI_FLASH_STMICRO=y CONFIG_DM_ETH=y

On Tue, Apr 12, 2016 at 05:03:23PM +0530, Vignesh R wrote:
Enable SPI and SPI Flash driver model as K2E SPI controller driver supports driver model.
Signed-off-by: Vignesh R vigneshr@ti.com
Reviewed-by: Tom Rini trini@konsulko.com

Now that davinci_spi driver has been converted to DM framework, enable the same in DT. Also add "spi-flash" as compatible property to n25q128a11 node as it is required for flash device to be probed in U-Boot.
Signed-off-by: Vignesh R vigneshr@ti.com --- arch/arm/dts/k2l-evm.dts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/arch/arm/dts/k2l-evm.dts b/arch/arm/dts/k2l-evm.dts index 9a69a6b55374..da0661ba3e8a 100644 --- a/arch/arm/dts/k2l-evm.dts +++ b/arch/arm/dts/k2l-evm.dts @@ -96,10 +96,11 @@ };
&spi0 { + status ="okay"; nor_flash: n25q128a11@0 { #address-cells = <1>; #size-cells = <1>; - compatible = "Micron,n25q128a11"; + compatible = "Micron,n25q128a11", "spi-flash"; spi-max-frequency = <54000000>; m25p,fast-read; reg = <0>;

On Tue, Apr 12, 2016 at 05:03:24PM +0530, Vignesh R wrote:
Now that davinci_spi driver has been converted to DM framework, enable the same in DT. Also add "spi-flash" as compatible property to n25q128a11 node as it is required for flash device to be probed in U-Boot.
Signed-off-by: Vignesh R vigneshr@ti.com
Reviewed-by: Tom Rini trini@konsulko.com

Enable SPI and SPI Flash driver model as K2L SPI controller driver supports driver model.
Signed-off-by: Vignesh R vigneshr@ti.com --- configs/k2l_evm_defconfig | 2 ++ 1 file changed, 2 insertions(+)
diff --git a/configs/k2l_evm_defconfig b/configs/k2l_evm_defconfig index d2ebb1d466cd..a9779dfb9c26 100644 --- a/configs/k2l_evm_defconfig +++ b/configs/k2l_evm_defconfig @@ -11,6 +11,8 @@ CONFIG_SYS_PROMPT="K2L EVM # " # CONFIG_CMD_SETEXPR is not set CONFIG_OF_CONTROL=y CONFIG_DM=y +CONFIG_DM_SPI=y +CONFIG_DM_SPI_FLASH=y CONFIG_SPI_FLASH=y CONFIG_SPI_FLASH_STMICRO=y CONFIG_DM_ETH=y

On Tue, Apr 12, 2016 at 05:03:25PM +0530, Vignesh R wrote:
Enable SPI and SPI Flash driver model as K2L SPI controller driver supports driver model.
Signed-off-by: Vignesh R vigneshr@ti.com
Reviewed-by: Tom Rini trini@konsulko.com

K2G SoC has 4 SPI instances that are compatible with davinci_spi controller(same as previous generation of Keystone2 devices). Add DT nodes for the same. K2G EVM has a N25Q128A13 SPI NOR flash connected on SPI-1. Add DT bindings for the same.
Signed-off-by: Vignesh R vigneshr@ti.com --- arch/arm/dts/k2g-evm.dts | 24 ++++++++++++++++++++++++ arch/arm/dts/k2g.dtsi | 47 +++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 71 insertions(+)
diff --git a/arch/arm/dts/k2g-evm.dts b/arch/arm/dts/k2g-evm.dts index 0ca36ef39ad3..38ca7ae1b6b9 100644 --- a/arch/arm/dts/k2g-evm.dts +++ b/arch/arm/dts/k2g-evm.dts @@ -31,3 +31,27 @@ &gbe0 { phy-handle = <ðphy0>; }; + +&spi1 { + status = "okay"; + + spi_nor: flash@0 { + #address-cells = <1>; + #size-cells = <1>; + compatible = "spi-flash"; + spi-max-frequency = <50000000>; + m25p,fast-read; + reg = <0>; + + partition@0 { + label = "u-boot-spl"; + reg = <0x0 0x80000>; + read-only; + }; + + partition@1 { + label = "misc"; + reg = <0x80000 0xf80000>; + }; + }; +}; diff --git a/arch/arm/dts/k2g.dtsi b/arch/arm/dts/k2g.dtsi index a3ed444d3c31..88b1a8e998ac 100644 --- a/arch/arm/dts/k2g.dtsi +++ b/arch/arm/dts/k2g.dtsi @@ -19,6 +19,10 @@
aliases { serial0 = &uart0; + spi0 = &spi0; + spi1 = &spi1; + spi2 = &spi2; + spi3 = &spi3; };
memory { @@ -88,5 +92,48 @@ ti,lpsc_module = <1>; };
+ spi0: spi@21805400 { + compatible = "ti,keystone-spi", "ti,dm6441-spi"; + reg = <0x21805400 0x200>; + num-cs = <4>; + ti,davinci-spi-intr-line = <0>; + interrupts = <GIC_SPI 64 IRQ_TYPE_EDGE_RISING>; + #address-cells = <1>; + #size-cells = <0>; + status = "disabled"; + }; + + spi1: spi@21805800 { + compatible = "ti,keystone-spi", "ti,dm6441-spi"; + reg = <0x21805800 0x200>; + num-cs = <4>; + ti,davinci-spi-intr-line = <0>; + interrupts = <GIC_SPI 66 IRQ_TYPE_EDGE_RISING>; + #address-cells = <1>; + #size-cells = <0>; + status = "disabled"; + }; + + spi2: spi@21805c00 { + compatible = "ti,keystone-spi", "ti,dm6441-spi"; + reg = <0x21805C00 0x200>; + num-cs = <4>; + ti,davinci-spi-intr-line = <0>; + interrupts = <GIC_SPI 68 IRQ_TYPE_EDGE_RISING>; + #address-cells = <1>; + #size-cells = <0>; + status = "disabled"; + }; + + spi3: spi@21806000 { + compatible = "ti,keystone-spi", "ti,dm6441-spi"; + reg = <0x21806000 0x200>; + num-cs = <4>; + ti,davinci-spi-intr-line = <0>; + interrupts = <GIC_SPI 70 IRQ_TYPE_EDGE_RISING>; + #address-cells = <1>; + #size-cells = <0>; + status = "disabled"; + }; }; };

On Tue, Apr 12, 2016 at 05:03:26PM +0530, Vignesh R wrote:
K2G SoC has 4 SPI instances that are compatible with davinci_spi controller(same as previous generation of Keystone2 devices). Add DT nodes for the same. K2G EVM has a N25Q128A13 SPI NOR flash connected on SPI-1. Add DT bindings for the same.
Signed-off-by: Vignesh R vigneshr@ti.com
Reviewed-by: Tom Rini trini@konsulko.com

Enable SPI and SPI Flash driver model as K2G SPI controller driver supports driver model.
Signed-off-by: Vignesh R vigneshr@ti.com --- configs/k2g_evm_defconfig | 2 ++ 1 file changed, 2 insertions(+)
diff --git a/configs/k2g_evm_defconfig b/configs/k2g_evm_defconfig index 054581297801..c39e3cedf685 100644 --- a/configs/k2g_evm_defconfig +++ b/configs/k2g_evm_defconfig @@ -11,6 +11,8 @@ CONFIG_CMD_REMOTEPROC=y # CONFIG_CMD_SETEXPR is not set CONFIG_OF_CONTROL=y CONFIG_DM=y +CONFIG_DM_SPI=y +CONFIG_DM_SPI_FLASH=y CONFIG_SPI_FLASH=y CONFIG_SPI_FLASH_STMICRO=y CONFIG_DM_ETH=y

On Tue, Apr 12, 2016 at 05:03:27PM +0530, Vignesh R wrote:
Enable SPI and SPI Flash driver model as K2G SPI controller driver supports driver model.
Signed-off-by: Vignesh R vigneshr@ti.com
Reviewed-by: Tom Rini trini@konsulko.com
participants (3)
-
Simon Glass
-
Tom Rini
-
Vignesh R