Skip to contentSkip to conversation

Convert davinci_spi to DM

PATCH Superseded Vignesh R 5 participants 34 messages May 4, 2016 – Jun 16, 2016

Subsystems (2)

v3 of 6 Superseded Latest is v6 →

lore
Share & tools
lore

Vignesh R

author
#0 lore raw

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
author
#1 lore raw

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
index 1322991d6c7b..6b19b4b8c7a0 100644
@@ -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
index 8970fc015c7e..5253b5410d9a 100644
@@ -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
author
#3 lore raw

PATCH v4 1/1 dm: core: implement dev_map_phsymem()

In reply to 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() 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
index 1322991d6c7b..6b19b4b8c7a0 100644
@@ -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
index 8970fc015c7e..5253b5410d9a 100644
@@ -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
#4 lore raw

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() 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 +0 -0
index 1322991d6c7b..6b19b4b8c7a0 100644

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.
#5 lore raw

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() 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 +0 -0
index 1322991d6c7b..6b19b4b8c7a0 100644
@@ -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.

#6 lore raw

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() 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 +0 -0
index 1322991d6c7b..6b19b4b8c7a0 100644
@@ -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.
author
#7 lore raw

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() 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 +0 -0
index 1322991d6c7b..6b19b4b8c7a0 100644

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?

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
#8 lore raw

PATCH v3 1/12 dm: core: implement dev_map_phsymem()

In reply to Vignesh R

Hi,

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() with MAP_NOCACHE flag.

---

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
index 1322991d6c7b..6b19b4b8c7a0 100644
@@ -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
index 8970fc015c7e..5253b5410d9a 100644

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

author
#9 lore raw

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() with MAP_NOCACHE flag.

Quoted 7 lines
Quoted 5 lines

---

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
author
#10 lore raw

PATCH v5 1/1 dm: core: implement dev_map_physmem()

In reply to 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() 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
index 1322991d6c7b..0406fc82f8d1 100644
@@ -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
index 8970fc015c7e..9509c0b72ccb 100644
@@ -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
#11 lore raw

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() with MAP_NOCACHE flag.

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(+)
author
#12 lore raw

PATCH v3 2/12 spi: davinci_spi: Convert to driver to adapt to DM

In reply to Vignesh R

Convert 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
index 0bd4f88926f1..75c8681d4e93 100644
@@ -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
#13 lore raw

PATCH v3 2/12 spi: davinci_spi: Convert to driver to adapt to DM

Quoted 3 lines · Vignesh R

Convert davinci_spi driver so that it complies with SPI DM framework.

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>
author
#14 lore raw

PATCH v4 2/12 spi: davinci_spi: Convert to driver to adapt to DM

In reply to Vignesh R

Convert 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
index 0bd4f88926f1..39a3801df231 100644
@@ -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
#15 lore raw

PATCH v4 2/12 spi: davinci_spi: Convert to driver to adapt to DM

Quoted 8 lines · Vignesh R

Convert davinci_spi driver so that it complies with SPI DM framework.

---

v4: Check error returned by dev_map_physmem().

Quoted 7 lines

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(-)
author
#16 lore raw

PATCH v5 2/12 spi: davinci_spi: Convert to driver to adapt to DM

In reply to Vignesh R

Convert 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
index 0bd4f88926f1..22274c91a2f1 100644
@@ -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
#17 lore raw

PATCH v5 2/12 spi: davinci_spi: Convert to driver to adapt to DM

Hi Vignesh,

Quoted 11 lines · Vignesh R

Convert davinci_spi driver so that it complies with SPI DM framework.

---

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_slave members.
Use dev_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

author
#18 lore raw

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_spi driver so that it complies with SPI DM framework.

---

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_slave members.
Use dev_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 -ENODEV to 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
author
#19 lore raw

PATCH v6 2/12 spi: davinci_spi: Convert to driver to adapt to DM

In reply to Vignesh R

Convert 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
index 0bd4f88926f1..20aa99a451dc 100644
@@ -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
author
#20 lore raw

PATCH v6 2/12 spi: davinci_spi: Convert to driver to adapt to DM

Quoted 6 lines · Vignesh R

Convert davinci_spi driver so that it complies with SPI DM framework.

---

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
index 0bd4f88926f1..20aa99a451dc 100644
@@ -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
#21 lore raw

PATCH v6 2/12 spi: davinci_spi: Convert to driver to adapt to DM

In reply to Vignesh R

Hi Vignesh,

Quoted 9 lines · Vignesh R

Convert 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(-)

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

author
#22 lore raw

PATCH v3 3/12 keystone2: spi: do not define DM_SPI and DM_SPI_FLASH for SPL build

In reply to Vignesh R

Since 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
index 2c9028c73558..985dd0625ab0 100644
@@ -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
author
#23 lore raw

PATCH v3 4/12 ARM: dts: keystone2: add SPI aliases for davinci SPI nodes

In reply to Vignesh R

Add 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
index f39b969f8d43..be97f3f21f92 100644
@@ -19,6 +19,9 @@
 
 	aliases {
 		serial0	= &uart0;
+		spi0 = &spi0;
+		spi1 = &spi1;
+		spi2 = &spi2;
 	};
 
 	chosen {
Signature · 1 line
2.8.2
author
#24 lore raw

PATCH v3 5/12 ARM: dts: k2hk: Enable Davinci SPI controller

In reply to Vignesh R

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.

---
 arch/arm/dts/k2hk-evm.dts | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)
arch/arm/dts/k2hk-evm.dts +2 -1
index 660ebf58d547..c5cad2c9da80 100644
@@ -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
author
#25 lore raw

PATCH v3 6/12 defconfig: k2hk_evm_defconfig: enable SPI driver model

In reply to Vignesh R

Enable 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
index 3975e804e534..21b8e1d2d383 100644
@@ -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
author
#26 lore raw

PATCH v3 7/12 ARM: dts: k2e: Enable Davinci SPI controller

In reply to Vignesh R

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.

---
 arch/arm/dts/k2e-evm.dts | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)
arch/arm/dts/k2e-evm.dts +2 -1
index 50c83c21d911..e2c3fb49102a 100644
@@ -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
author
#27 lore raw

PATCH v3 8/12 defconfig: k2e_evm_defconfig: enable SPI driver model

In reply to Vignesh R

Enable 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
index 044a9bf5b6e3..1e5003e8d23c 100644
@@ -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
author
#28 lore raw

PATCH v3 9/12 ARM: dts: k2l: Enable Davinci SPI controller

In reply to Vignesh R

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.

---
 arch/arm/dts/k2l-evm.dts | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)
arch/arm/dts/k2l-evm.dts +2 -1
index 9a69a6b55374..da0661ba3e8a 100644
@@ -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
author
#29 lore raw

PATCH v3 10/12 defconfig: k2l_evm_defconfig: enable SPI driver model

In reply to Vignesh R

Enable 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
index 844dd57163f5..1ba7d23e9c78 100644
@@ -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
author
#30 lore raw

PATCH v3 11/12 ARM: dts: k2g: add support for Davinci SPI controller

In reply to Vignesh R

K2G 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
index 0ca36ef39ad3..38ca7ae1b6b9 100644
@@ -31,3 +31,27 @@
 &gbe0 {
 	phy-handle = <&ethphy0>;
 };
+
+&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
author
#31 lore raw

PATCH v3 12/12 defconfig: k2g_evm_defconfig: enable SPI driver model

In reply to Vignesh R

Enable 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
index d0b45ce3f8a5..33722ce9c421 100644
@@ -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
#32 lore raw

v3 cover Convert davinci_spi to DM

In reply to Vignesh R
Quoted 23 lines · Vignesh R

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

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.
author
#33 lore raw

v3 cover Convert davinci_spi to DM

In reply to Vignesh R
Quoted 9 lines · Vignesh R

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

Gentle ping on the series...

Quoted 30 lines

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 · 2 lines
Regards
Vignesh