Convert davinci_spi to DM
Subsystems (2)
v3 cover 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.
Rebased on top of v2016.05-rc3
Vignesh R (12):
dm: core: implement dev_map_phsymem()
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/core/device.c | 6 + drivers/spi/davinci_spi.c | 327 +++++++++++++++++++++++++---------- include/configs/ti_armv7_keystone2.h | 4 + include/dm/device.h | 9 + 14 files changed, 344 insertions(+), 93 deletions(-)
Signature · 1 line
2.8.2
PATCH v3 1/12 dm: core: implement dev_map_phsymem()
This API helps to map physical register addresss pace of device to virtual address space easily. Its just a wrapper around map_physmem() with MAP_NOCACHE flag.
---
v3: Explicitly include header file
v2: New patch
drivers/core/device.c | 6 ++++++ include/dm/device.h | 9 +++++++++ 2 files changed, 15 insertions(+)
drivers/core/device.c +6 -0
@@ -10,6 +10,7 @@*/ #include <common.h> +#include <asm/io.h> #include <fdtdec.h> #include <fdt_support.h> #include <malloc.h>
@@ -678,6 +679,11 @@ void *dev_get_addr_ptr(struct udevice *dev)return (void *)(uintptr_t )dev_get_addr_index (dev,0 ); } +void *dev_map_physmem (struct udevice *dev,unsigned long size) +{ +return map_physmem (dev_get_addr (dev), size,MAP_NOCACHE ); +} +bool device_has_children (struct udevice *dev) {return !list_empty (&dev->child_head);
include/dm/device.h +9 -0
@@ -463,6 +463,15 @@ fdt_addr_t dev_get_addr(struct udevice *dev);*/ void *dev_get_addr_ptr (struct udevice *dev); +/* * dev_map_physmem() - Map bus memory into CPU space +* +* @dev: Pointer to device +* @size: size of the memory to map +* +* @return addr +*/ +void *dev_map_physmem (struct udevice *dev,unsigned long size); +/** * dev_get_addr_index() - Get the indexed reg property of a device *
Signature · 1 line
2.8.2
PATCH v3 1/12 dm: core: implement dev_map_phsymem()
Quoted 6 lines · Vignesh R
This API helps to map physical register addresss pace of device to virtual address space easily. Its just a wrapper around
map_physmem()withMAP_NOCACHEflag.Signed-off-by Vignesh R <[email protected]>Suggested-by Simon Glass <[email protected]>
PATCH v4 1/1 dm: core: implement dev_map_phsymem()
In reply to Vignesh RThis API helps to map physical register addresss pace of device to virtual address space easily. Its just a wrapper around map_physmem() with MAP_NOCACHE flag.
---
v4: Reorder include files to avoid build warning on dra7xx.
drivers/core/device.c | 6 ++++++ include/dm/device.h | 9 +++++++++ 2 files changed, 15 insertions(+)
drivers/core/device.c +6 -0
@@ -10,6 +10,7 @@*/ #include <common.h> +#include <asm/io.h> #include <fdtdec.h> #include <fdt_support.h> #include <malloc.h>
@@ -678,6 +679,11 @@ void *dev_get_addr_ptr(struct udevice *dev)return (void *)(uintptr_t )dev_get_addr_index (dev,0 ); } +void *dev_map_physmem (struct udevice *dev,unsigned long size) +{ +return map_physmem (dev_get_addr (dev), size,MAP_NOCACHE ); +} +bool device_has_children (struct udevice *dev) {return !list_empty (&dev->child_head);
include/dm/device.h +9 -0
@@ -463,6 +463,15 @@ fdt_addr_t dev_get_addr(struct udevice *dev);*/ void *dev_get_addr_ptr (struct udevice *dev); +/* * dev_map_physmem() - Map bus memory into CPU space +* +* @dev: Pointer to device +* @size: size of the memory to map +* +* @return addr +*/ +void *dev_map_physmem (struct udevice *dev,unsigned long size); +/** * dev_get_addr_index() - Get the indexed reg property of a device *
Signature · 1 line
2.8.2
PATCH v4 1/1 dm: core: implement dev_map_phsymem()
Quoted 21 lines · Vignesh R
This API helps to map physical register addresss pace of device to virtual address space easily. Its just a wrapper around
map_physmem()withMAP_NOCACHEflag.Signed-off-by Vignesh R <[email protected]>Suggested-by Simon Glass <[email protected]>Reviewed-by Jagan Teki <[email protected]>---
v4: Reorder include files to avoid build warning on dra7xx.
drivers/core/device.c | 6 ++++++ include/dm/device.h | 9 +++++++++ 2 files changed, 15 insertions(+)drivers/core/device.c +0
-0
drivers/core/device.c line 13
Quoted 4 lines
drivers/core/device.c +1
-0@@ -10,6 +10,7 @@*/ #include <common.h> +#include <asm/io.h>
I think this look same as v3 [1] please check?
drivers/core/device.c line 16
Quoted 3 lines
drivers/core/device.c +0
-0#include <fdtdec.h> #include <fdt_support.h> #include <malloc.h>
[1] https://patchwork.ozlabs.org/patch/618361/
Signature · 1 line
Jagan.
R
PATCH v4 1/1 dm: core: implement dev_map_phsymem()
Quoted 24 lines · Jagan Teki
Quoted 23 lines · Vignesh R
This API helps to map physical register addresss pace of device to virtual address space easily. Its just a wrapper around
map_physmem()withMAP_NOCACHEflag.Signed-off-by Vignesh R <[email protected]>Suggested-by Simon Glass <[email protected]>Reviewed-by Jagan Teki <[email protected]>---
v4: Reorder include files to avoid build warning on dra7xx.
drivers/core/device.c | 6 ++++++ include/dm/device.h | 9 +++++++++ 2 files changed, 15 insertions(+)drivers/core/device.c +0
-0@@ -10,6 +10,7 @@*/
Quoted 4 lines
drivers/core/device.c line 13
Quoted 2 lines
drivers/core/device.c +1
-0#include <common.h> +#include <asm/io.h> I think this look same as v3 [1] please check?
Yeah, v3 has the include files in correct. Please ignore this patch. Sorry for the spam.
Regards
Vignesh.
PATCH v4 1/1 dm: core: implement dev_map_phsymem()
Quoted 27 lines · Vignesh
Quoted 24 lines · Jagan Teki
Quoted 23 lines · Vignesh R
This API helps to map physical register addresss pace of device to virtual address space easily. Its just a wrapper around
map_physmem()withMAP_NOCACHEflag.Signed-off-by Vignesh R <[email protected]>Suggested-by Simon Glass <[email protected]>Reviewed-by Jagan Teki <[email protected]>---
v4: Reorder include files to avoid build warning on dra7xx.
drivers/core/device.c | 6 ++++++ include/dm/device.h | 9 +++++++++ 2 files changed, 15 insertions(+)drivers/core/device.c +0
-0@@ -10,6 +10,7 @@*/
Quoted 7 lines
Quoted 4 lines
drivers/core/device.c line 13
Quoted 2 lines
drivers/core/device.c +1
-0#include <common.h> +#include <asm/io.h> I think this look same as v3 [1] please check?
Yeah, v3 has the include files in correct. Please ignore this patch. Sorry for the spam.
Did you test this series on top of master?
Signature · 1 line
Jagan.
PATCH v4 1/1 dm: core: implement dev_map_phsymem()
Quoted 33 lines · Jagan Teki
Quoted 32 lines · Vignesh
Quoted 28 lines · Jagan Teki
Quoted 21 lines · Vignesh R
This API helps to map physical register addresss pace of device to virtual address space easily. Its just a wrapper around
map_physmem()withMAP_NOCACHEflag.Signed-off-by Vignesh R <[email protected]>Suggested-by Simon Glass <[email protected]>Reviewed-by Jagan Teki <[email protected]>---
v4: Reorder include files to avoid build warning on dra7xx.
drivers/core/device.c | 6 ++++++ include/dm/device.h | 9 +++++++++ 2 files changed, 15 insertions(+)drivers/core/device.c +0
-0drivers/core/device.c line 13
Quoted 4 lines
drivers/core/device.c +1
-0@@ -10,6 +10,7 @@*/ #include <common.h> +#include <asm/io.h> I think this look same as v3 [1] please check?
Quoted 4 lines
Quoted 2 lines
Yeah, v3 has the include files in correct. Please ignore this patch. Sorry for the spam.
Did you test this series on top of master?
Yes, this is tested on top of 2016.05-rc3
Signature · 2 lines
Regards Vignesh
PATCH v3 1/12 dm: core: implement dev_map_phsymem()
In reply to Vignesh RHi,
Quoted 9 lines · Vignesh R
This API helps to map physical register addresss pace of device to virtual address space easily. Its just a wrapper around
map_physmem()withMAP_NOCACHEflag.Signed-off-by Vignesh R <[email protected]>Suggested-by Simon Glass <[email protected]>---
v3: Explicitly include header file
A few nits, sorry this review is late.
Please fix spelling of dev_map_phsymemin the commit subject.
Quoted 20 lines
v2: New patch
drivers/core/device.c | 6 ++++++ include/dm/device.h | 9 +++++++++ 2 files changed, 15 insertions(+)drivers/core/device.c +1
-0@@ -10,6 +10,7 @@*/ #include <common.h> +#include <asm/io.h> #include <fdtdec.h> #include <fdt_support.h> #include <malloc.h>
drivers/core/device.c void *dev_get_addr_ptr(struct udevice *dev) · line 684
Quoted 6 lines
drivers/core/device.c +3
-0@@ -678,6 +679,11 @@ void *dev_get_addr_ptr(struct udevice *dev)return (void *)(uintptr_t )dev_get_addr_index (dev,0 ); } +void *dev_map_physmem (struct udevice *dev,unsigned long size) +{ +return map_physmem (dev_get_addr (dev), size,MAP_NOCACHE );
What happens if dev_get_addr() returns 0. Does it work OK? If not, please add a check for it.
Quoted 10 lines
drivers/core/device.c +2
-0+} +bool device_has_children (struct udevice *dev) {return !list_empty (&dev->child_head);include/dm/device.h +0
-0
include/dm/device.h fdt_addr_t dev_get_addr(struct udevice *dev); · line 466
Quoted 4 lines
include/dm/device.h +1
-0@@ -463,6 +463,15 @@ fdt_addr_t dev_get_addr(struct udevice *dev);*/ void *dev_get_addr_ptr (struct udevice *dev); +/* * dev_map_physmem() - Map bus memory into CPU space
This is fine, but please add more detail on following lines. You need to mention that it reads the device address from the 'reg' property using dev_get_addr().
include/dm/device.h fdt_addr_t dev_get_addr(struct udevice *dev); · line 471
Quoted 5 lines
include/dm/device.h +5
-0+* +* @dev: Pointer to device +* @size: size of the memory to map +* +* @return addr
Something like:
@return mapped address, or 0 if the device does not have an address or the mapping failed
Quoted 9 lines
include/dm/device.h +3
-1+*/ +void *dev_map_physmem (struct udevice *dev,unsigned long size); +/** * dev_get_addr_index() - Get the indexed reg property of a device * -- 2.8.2
Regards,
Simon
PATCH v3 1/12 dm: core: implement dev_map_phsymem()
Quoted 7 lines · Simon Glass
Hi,
Quoted 4 lines · Vignesh R
This API helps to map physical register addresss pace of device to virtual address space easily. Its just a wrapper around
map_physmem()withMAP_NOCACHEflag.
Quoted 7 lines
Quoted 5 lines
Signed-off-by Vignesh R <[email protected]>Suggested-by Simon Glass <[email protected]>---
v3: Explicitly include header file
A few nits, sorry this review is late.
Posted a v5 in reply to this thread.
Signature · 2 lines
Regards Vignesh
PATCH v5 1/1 dm: core: implement dev_map_physmem()
In reply to Vignesh RThis API helps to map physical register addresss pace of device to virtual address space easily. Its just a wrapper around map_physmem() with MAP_NOCACHE flag.
---
v5: Fix comments by Simon Glass <[email protected]>
drivers/core/device.c | 11 +++++++++++ include/dm/device.h | 13 +++++++++++++ 2 files changed, 24 insertions(+)
drivers/core/device.c +11 -0
@@ -10,6 +10,7 @@*/ #include <common.h> +#include <asm/io.h> #include <fdtdec.h> #include <fdt_support.h> #include <malloc.h>
@@ -678,6 +679,16 @@ void *dev_get_addr_ptr(struct udevice *dev)return (void *)(uintptr_t )dev_get_addr_index (dev,0 ); } +void *dev_map_physmem (struct udevice *dev,unsigned long size) +{ +fdt_addr_t addr =dev_get_addr (dev); + +if (addr ==FDT_ADDR_T_NONE ) +return NULL ; + +return map_physmem (addr, size,MAP_NOCACHE ); +} +bool device_has_children (struct udevice *dev) {return !list_empty (&dev->child_head);
include/dm/device.h +13 -0
@@ -464,6 +464,19 @@ fdt_addr_t dev_get_addr(struct udevice *dev);void *dev_get_addr_ptr (struct udevice *dev);/** +* dev_map_physmem() - Read device address from reg property of the +* device node and map the address into CPU address +* space. +* +* @dev: Pointer to device +* @size: size of the memory to map +* +* @return mapped address, or NULL if the device does not have reg +* property. +*/ +void *dev_map_physmem (struct udevice *dev,unsigned long size); + +/** * dev_get_addr_index() - Get the indexed reg property of a device * * @dev: Pointer to a device
Signature · 1 line
2.8.2
PATCH v5 1/1 dm: core: implement dev_map_physmem()
Quoted 8 lines · Vignesh R
This API helps to map physical register addresss pace of device to virtual address space easily. Its just a wrapper around
map_physmem()withMAP_NOCACHEflag.Signed-off-by Vignesh R <[email protected]>Suggested-by Simon Glass <[email protected]>Reviewed-by Jagan Teki <[email protected]>
Quoted 7 lines
---
v5: Fix comments by Simon Glass <[email protected]>
drivers/core/device.c | 11 +++++++++++ include/dm/device.h | 13 +++++++++++++ 2 files changed, 24 insertions(+)
PATCH v3 2/12 spi: davinci_spi: Convert to driver to adapt to DM
In reply to Vignesh RConvert davinci_spi driver so that it complies with SPI DM framework.
---
v3: No changes
v2: Add comments to struct davinci_spi_slave members.
Use dev_map_physmem() added by previous patch.
drivers/spi/davinci_spi.c | 327 +++++++++++++++++++++++++++++++++------------- 1 file changed, 237 insertions(+), 90 deletions(-)
drivers/spi/davinci_spi.c +237 -90
@@ -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 freq;/* current SPI bus frequency */ +unsigned int mode;/* current SPI mode used */ +u8 num_cs;/* total no. of CS available */ +u8 cur_cs;/* CS of current slave */ +bool half_duplex;/* true, if master is half-duplex only */ }; -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,139 @@ 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 =dev_map_physmem (bus,sizeof (struct davinci_spi_regs )); + 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
Signature · 1 line
2.8.2
PATCH v3 2/12 spi: davinci_spi: Convert to driver to adapt to DM
Quoted 3 lines · Vignesh R
Convert
davinci_spidriver so that it complies with SPI DM framework.Signed-off-by Vignesh R <[email protected]>
Signature · 8 lines
Tom -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 819 bytes Desc: Digital signature URL: <http://lists.denx.de/pipermail/u-boot/attachments/20160506/c5f81985/attachment.sig>
PATCH v4 2/12 spi: davinci_spi: Convert to driver to adapt to DM
In reply to Vignesh RConvert davinci_spi driver so that it complies with SPI DM framework.
---
v4: Check error returned by dev_map_physmem().
v3: No changes
v2: Add comments to struct davinci_spi_slave members.
Use dev_map_physmem() added by previous patch.
drivers/spi/davinci_spi.c | 329 +++++++++++++++++++++++++++++++++------------- 1 file changed, 240 insertions(+), 89 deletions(-)
drivers/spi/davinci_spi.c +240 -89
@@ -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 freq;/* current SPI bus frequency */ +unsigned int mode;/* current SPI mode used */ +u8 num_cs;/* total no. of CS available */ +u8 cur_cs;/* CS of current slave */ +bool half_duplex;/* true, if master is half-duplex only */ }; -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,143 @@ 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 ; +} -out: -if (flags &SPI_XFER_END ) { -u8 dummy =0 ; -davinci_spi_write (slave,1 , &dummy, flags); +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 =dev_map_physmem (bus,sizeof (struct davinci_spi_regs )); +if (!ds->regs) { +printf ("%s: could not map device address\n" ); +return -ENODEV ; } + ds->num_cs =fdtdec_get_int (blob, node,"num-cs" ,4 ); +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
Signature · 1 line
2.8.2
PATCH v4 2/12 spi: davinci_spi: Convert to driver to adapt to DM
Quoted 8 lines · Vignesh R
Convert
davinci_spidriver so that it complies with SPI DM framework.Signed-off-by Vignesh R <[email protected]>Reviewed-by Tom Rini <[email protected]>---
v4: Check error returned by
dev_map_physmem().
Quoted 7 lines
v3: No changes
v2: Add comments to struct
davinci_spi_slavemembers.
Usedev_map_physmem()added by previous patch.drivers/spi/davinci_spi.c | 329 +++++++++++++++++++++++++++++++++------------- 1 file changed, 240 insertions(+), 89 deletions(-)
PATCH v5 2/12 spi: davinci_spi: Convert to driver to adapt to DM
In reply to Vignesh RConvert davinci_spi driver so that it complies with SPI DM framework.
---
v5: correct error message.
v4: Check error returned by dev_map_physmem().
v3: No changes
v2: Add comments to struct davinci_spi_slave members.
Use dev_map_physmem() added by previous patch.
drivers/spi/davinci_spi.c | 329 +++++++++++++++++++++++++++++++++------------- 1 file changed, 240 insertions(+), 89 deletions(-)
drivers/spi/davinci_spi.c +240 -89
@@ -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 freq;/* current SPI bus frequency */ +unsigned int mode;/* current SPI mode used */ +u8 num_cs;/* total no. of CS available */ +u8 cur_cs;/* CS of current slave */ +bool half_duplex;/* true, if master is half-duplex only */ }; -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,143 @@ 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 ; +} -out: -if (flags &SPI_XFER_END ) { -u8 dummy =0 ; -davinci_spi_write (slave,1 , &dummy, flags); +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 =dev_map_physmem (bus,sizeof (struct davinci_spi_regs )); +if (!ds->regs) { +printf ("%s: could not map device address\n" , __func__); +return -ENODEV ; } + ds->num_cs =fdtdec_get_int (blob, node,"num-cs" ,4 ); +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
Signature · 1 line
2.8.3
PATCH v5 2/12 spi: davinci_spi: Convert to driver to adapt to DM
Hi Vignesh,
Quoted 11 lines · Vignesh R
Convert
davinci_spidriver so that it complies with SPI DM framework.Signed-off-by Vignesh R <[email protected]>Reviewed-by Tom Rini <[email protected]>---
v5: correct error message.
v4: Check error returned by
dev_map_physmem().
Quoted 7 lines
v3: No changes
v2: Add comments to struct
davinci_spi_slavemembers.
Usedev_map_physmem()added by previous patch.drivers/spi/davinci_spi.c | 329 +++++++++++++++++++++++++++++++++------------- 1 file changed, 240 insertions(+), 89 deletions(-)
Sorry I missed something below.
[snip]
drivers/spi/davinci_spi.c void spi_free_slave(struct spi_slave *slave) · line 548
Quoted 10 lines
drivers/spi/davinci_spi.c +10
-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 =dev_map_physmem (bus,sizeof (struct davinci_spi_regs )); +if (!ds->regs) { +printf ("%s: could not map device address\n" , __func__); +return -ENODEV ;
-EINVAL
We use -ENODEV to say there is no device. Here, we have a device but the configuration is wrong.
Quoted 33 lines
}drivers/spi/davinci_spi.c +27
-1+ ds->num_cs =fdtdec_get_int (blob, node,"num-cs" ,4 ); + 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.3
PATCH v5 2/12 spi: davinci_spi: Convert to driver to adapt to DM
Quoted 38 lines · Simon Glass
Hi Vignesh,
Quoted 11 lines · Vignesh R
Convert
davinci_spidriver so that it complies with SPI DM framework.Signed-off-by Vignesh R <[email protected]>Reviewed-by Tom Rini <[email protected]>---
v5: correct error message.
v4: Check error returned by
dev_map_physmem().Quoted 7 lines
v3: No changes
v2: Add comments to struct
davinci_spi_slavemembers.
Usedev_map_physmem()added by previous patch.drivers/spi/davinci_spi.c | 329 +++++++++++++++++++++++++++++++++------------- 1 file changed, 240 insertions(+), 89 deletions(-)Sorry I missed something below.
[snip]drivers/spi/davinci_spi.c void spi_free_slave(struct spi_slave *slave) · line 548
Quoted 10 lines
drivers/spi/davinci_spi.c +10
-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 =dev_map_physmem (bus,sizeof (struct davinci_spi_regs )); +if (!ds->regs) { +printf ("%s: could not map device address\n" , __func__); +return -ENODEV ;
-EINVAL
Quoted 2 lines
We use
-ENODEVto say there is no device. Here, we have a device but the configuration is wrong.
Ok, I posted in v6 with above change.
Signature · 2 lines
Regards Vignesh
PATCH v6 2/12 spi: davinci_spi: Convert to driver to adapt to DM
In reply to Vignesh RConvert davinci_spi driver so that it complies with SPI DM framework.
---
v6: Fix retval on dev_map_physmem() failure.
drivers/spi/davinci_spi.c | 329 +++++++++++++++++++++++++++++++++------------- 1 file changed, 240 insertions(+), 89 deletions(-)
drivers/spi/davinci_spi.c +240 -89
@@ -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 freq;/* current SPI bus frequency */ +unsigned int mode;/* current SPI mode used */ +u8 num_cs;/* total no. of CS available */ +u8 cur_cs;/* CS of current slave */ +bool half_duplex;/* true, if master is half-duplex only */ }; -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,143 @@ 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 ; +} -out: -if (flags &SPI_XFER_END ) { -u8 dummy =0 ; -davinci_spi_write (slave,1 , &dummy, flags); +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 =dev_map_physmem (bus,sizeof (struct davinci_spi_regs )); +if (!ds->regs) { +printf ("%s: could not map device address\n" , __func__); +return -EINVAL ; } + ds->num_cs =fdtdec_get_int (blob, node,"num-cs" ,4 ); +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
Signature · 1 line
2.8.3
PATCH v6 2/12 spi: davinci_spi: Convert to driver to adapt to DM
Quoted 6 lines · Vignesh R
Convert
davinci_spidriver so that it complies with SPI DM framework.Signed-off-by Vignesh R <[email protected]>---
v6: Fix retval on
dev_map_physmem()failure.
Gentle ping....
Quoted 456 lines
drivers/spi/davinci_spi.c | 329 +++++++++++++++++++++++++++++++++------------- 1 file changed, 240 insertions(+), 89 deletions(-)drivers/spi/davinci_spi.c +240
-89@@ -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 freq;/* current SPI bus frequency */ +unsigned int mode;/* current SPI mode used */ +u8 num_cs;/* total no. of CS available */ +u8 cur_cs;/* CS of current slave */ +bool half_duplex;/* true, if master is half-duplex only */ }; -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,143 @@ 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 ; +} -out: -if (flags &SPI_XFER_END ) { -u8 dummy =0 ; -davinci_spi_write (slave,1 , &dummy, flags); +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 =dev_map_physmem (bus,sizeof (struct davinci_spi_regs )); +if (!ds->regs) { +printf ("%s: could not map device address\n" , __func__); +return -EINVAL ; } + ds->num_cs =fdtdec_get_int (blob, node,"num-cs" ,4 ); +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
Signature · 2 lines
Regards Vignesh
PATCH v6 2/12 spi: davinci_spi: Convert to driver to adapt to DM
In reply to Vignesh RHi Vignesh,
Quoted 9 lines · Vignesh R
Convert
davinci_spidriver so that it complies with SPI DM framework.Signed-off-by Vignesh R <[email protected]>---
v6: Fix retval on
dev_map_physmem()failure.drivers/spi/davinci_spi.c | 329 +++++++++++++++++++++++++++++++++------------- 1 file changed, 240 insertions(+), 89 deletions(-)
Who is picking this one up? I can pull it into dm if you like, but I assumed it would be a SPI patch.
Regards,
Simon
PATCH v3 3/12 keystone2: spi: do not define DM_SPI and DM_SPI_FLASH for SPL build
In reply to Vignesh RSince Keystone2 devices do not have support DM in SPL, do not define DM_SPI and DM_SPI_FLASH for SPL build.
--- include/configs/ti_armv7_keystone2.h | 4 ++++ 1 file changed, 4 insertions(+)
include/configs/ti_armv7_keystone2.h +4 -0
@@ -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
Signature · 1 line
2.8.2
PATCH v3 4/12 ARM: dts: keystone2: add SPI aliases for davinci SPI nodes
In reply to Vignesh RAdd aliases for SPI nodes in order for it to be probed by the DM framework.
--- arch/arm/dts/keystone.dtsi | 3 +++ 1 file changed, 3 insertions(+)
arch/arm/dts/keystone.dtsi +3 -0
@@ -19,6 +19,9 @@ aliases { serial0 = &uart0; + spi0 = &spi0; + spi1 = &spi1; + spi2 = &spi2; }; chosen {
Signature · 1 line
2.8.2
PATCH v3 5/12 ARM: dts: k2hk: Enable Davinci SPI controller
In reply to Vignesh RNow 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.
--- arch/arm/dts/k2hk-evm.dts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
arch/arm/dts/k2hk-evm.dts +2 -1
@@ -147,10 +147,11 @@ }; &spi0 { + status = "okay"; nor_flash: n25q128a11 at 0 { #address-cells = <1>; #size-cells = <1>; - compatible = "Micron,n25q128a11"; + compatible = "Micron,n25q128a11", "spi-flash"; spi-max-frequency = <54000000>; m25p,fast-read; reg = <0>;
Signature · 1 line
2.8.2
PATCH v3 6/12 defconfig: k2hk_evm_defconfig: enable SPI driver model
In reply to Vignesh REnable SPI and SPI Flash driver model as K2HK SPI controller driver supports driver model.
--- configs/k2hk_evm_defconfig | 2 ++ 1 file changed, 2 insertions(+)
configs/k2hk_evm_defconfig +2 -0
@@ -28,6 +28,8 @@ CONFIG_CMD_FS_GENERIC=y CONFIG_OF_CONTROL=y CONFIG_DM=y CONFIG_TI_AEMIF=y +CONFIG_DM_SPI=y +CONFIG_DM_SPI_FLASH=y CONFIG_SPI_FLASH=y CONFIG_SPI_FLASH_STMICRO=y CONFIG_DM_ETH=y
Signature · 1 line
2.8.2
PATCH v3 7/12 ARM: dts: k2e: Enable Davinci SPI controller
In reply to Vignesh RNow 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.
--- arch/arm/dts/k2e-evm.dts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
arch/arm/dts/k2e-evm.dts +2 -1
@@ -119,10 +119,11 @@ }; &spi0 { + status = "okay"; nor_flash: n25q128a11 at 0 { #address-cells = <1>; #size-cells = <1>; - compatible = "Micron,n25q128a11"; + compatible = "Micron,n25q128a11", "spi-flash"; spi-max-frequency = <54000000>; m25p,fast-read; reg = <0>;
Signature · 1 line
2.8.2
PATCH v3 8/12 defconfig: k2e_evm_defconfig: enable SPI driver model
In reply to Vignesh REnable SPI and SPI Flash driver model as K2E SPI controller driver supports driver model.
--- configs/k2e_evm_defconfig | 2 ++ 1 file changed, 2 insertions(+)
configs/k2e_evm_defconfig +2 -0
@@ -28,6 +28,8 @@ CONFIG_CMD_FS_GENERIC=y CONFIG_OF_CONTROL=y CONFIG_DM=y CONFIG_TI_AEMIF=y +CONFIG_DM_SPI=y +CONFIG_DM_SPI_FLASH=y CONFIG_SPI_FLASH=y CONFIG_SPI_FLASH_STMICRO=y CONFIG_DM_ETH=y
Signature · 1 line
2.8.2
PATCH v3 9/12 ARM: dts: k2l: Enable Davinci SPI controller
In reply to Vignesh RNow 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.
--- arch/arm/dts/k2l-evm.dts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
arch/arm/dts/k2l-evm.dts +2 -1
@@ -96,10 +96,11 @@ }; &spi0 { + status ="okay"; nor_flash: n25q128a11 at 0 { #address-cells = <1>; #size-cells = <1>; - compatible = "Micron,n25q128a11"; + compatible = "Micron,n25q128a11", "spi-flash"; spi-max-frequency = <54000000>; m25p,fast-read; reg = <0>;
Signature · 1 line
2.8.2
PATCH v3 10/12 defconfig: k2l_evm_defconfig: enable SPI driver model
In reply to Vignesh REnable SPI and SPI Flash driver model as K2L SPI controller driver supports driver model.
--- configs/k2l_evm_defconfig | 2 ++ 1 file changed, 2 insertions(+)
configs/k2l_evm_defconfig +2 -0
@@ -28,6 +28,8 @@ CONFIG_CMD_FS_GENERIC=y CONFIG_OF_CONTROL=y CONFIG_DM=y CONFIG_TI_AEMIF=y +CONFIG_DM_SPI=y +CONFIG_DM_SPI_FLASH=y CONFIG_SPI_FLASH=y CONFIG_SPI_FLASH_STMICRO=y CONFIG_DM_ETH=y
Signature · 1 line
2.8.2
PATCH v3 11/12 ARM: dts: k2g: add support for Davinci SPI controller
In reply to Vignesh RK2G SoC has 4 SPI instances that are compatible with davinci_spi controller(present on 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.
--- arch/arm/dts/k2g-evm.dts | 24 ++++++++++++++++++++++++ arch/arm/dts/k2g.dtsi | 47 +++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 71 insertions(+)
arch/arm/dts/k2g-evm.dts +24 -0
@@ -31,3 +31,27 @@ &gbe0 { phy-handle = <ðphy0>; }; + +&spi1 { + status = "okay"; + + spi_nor: flash at 0 { + #address-cells = <1>; + #size-cells = <1>; + compatible = "spi-flash"; + spi-max-frequency = <50000000>; + m25p,fast-read; + reg = <0>; + + partition at 0 { + label = "u-boot-spl"; + reg = <0x0 0x80000>; + read-only; + }; + + partition at 1 { + label = "misc"; + reg = <0x80000 0xf80000>; + }; + }; +};
arch/arm/dts/k2g.dtsi +47 -0
58 lines not on this page · raw message
Signature · 1 line
2.8.2
PATCH v3 12/12 defconfig: k2g_evm_defconfig: enable SPI driver model
In reply to Vignesh REnable SPI and SPI Flash driver model as K2G SPI controller driver supports driver model.
--- configs/k2g_evm_defconfig | 2 ++ 1 file changed, 2 insertions(+)
configs/k2g_evm_defconfig +2 -0
@@ -27,6 +27,8 @@ CONFIG_CMD_FAT=y CONFIG_CMD_FS_GENERIC=y 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
Signature · 1 line
2.8.2
v3 cover Convert davinci_spi to DM
In reply to Vignesh RQuoted 23 lines · Vignesh R
This series converts
davinci_spidriver to adapt to driver model framework. And enables the driver on k2l, k2e, k2hk evms. Also, added support fordavinci_spion k2g evm.Tested on k2l, k2e, k2hk and k2g evms.
Rebased on top of v2016.05-rc3
Vignesh R (12):
dm: core: implementdev_map_phsymem()
spi:davinci_spi: Convert to driver to adapt to DM
keystone2: spi: do not defineDM_SPIandDM_SPI_FLASHfor 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
Quoted 12 lines
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/core/device.c | 6 + drivers/spi/davinci_spi.c | 327 +++++++++++++++++++++++++--
Signature · 1 line
Jagan.
v3 cover Convert davinci_spi to DM
In reply to Vignesh RQuoted 9 lines · Vignesh R
This series converts
davinci_spidriver to adapt to driver model framework. And enables the driver on k2l, k2e, k2hk evms. Also, added support fordavinci_spion k2g evm.Tested on k2l, k2e, k2hk and k2g evms.
Rebased on top of v2016.05-rc3
Gentle ping on the series...
Quoted 30 lines
Vignesh R (12):
dm: core: implementdev_map_phsymem()
spi:davinci_spi: Convert to driver to adapt to DM
keystone2: spi: do not defineDM_SPIandDM_SPI_FLASHfor 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 modelarch/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/core/device.c | 6 + drivers/spi/davinci_spi.c | 327 +++++++++++++++++++++++++---------- include/configs/ti_armv7_keystone2.h | 4 + include/dm/device.h | 9 + 14 files changed, 344 insertions(+), 93 deletions(-)
Signature · 2 lines
Regards Vignesh