[U-Boot] [PATCH v1 1/1] spi: lpc32xx_ssp: DM conversion

Akash Gajjar gajjar04akash at gmail.com
Wed May 9 07:07:10 UTC 2018


From: Akash Gajjar <gajjar04akash at gmail.com>

This patch adds support for DM to the LPC32xx SSP SPI driver.

Some TODOs are left over for later, These would be enhancements to the
original functionality, and can come later. The legacy functionality is
removed in this version.

Signed-off-by: Akash Gajjar <akash at openedev.com>
---
 drivers/spi/Kconfig                        |  10 +-
 drivers/spi/lpc32xx_ssp.c                  | 145 +++++++++++++++--------------
 include/dm/platform_data/spi_lpc32xx_ssp.h |  15 +++
 3 files changed, 93 insertions(+), 77 deletions(-)
 create mode 100644 include/dm/platform_data/spi_lpc32xx_ssp.h

diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig
index ec92b84..2297d4a 100644
--- a/drivers/spi/Kconfig
+++ b/drivers/spi/Kconfig
@@ -99,6 +99,11 @@ config ICH_SPI
 	  access the SPI NOR flash on platforms embedding this Intel
 	  ICH IP core.
 
+config LPC32XX_SSP
+	bool "LPC32XX SPI Driver"
+	help
+	  Enable support for SPI on LPC32xx
+
 config MVEBU_A3700_SPI
 	bool "Marvell Armada 3700 SPI driver"
 	help
@@ -277,11 +282,6 @@ config KIRKWOOD_SPI
 	  Enable support for SPI on various Marvell SoCs, such as
 	  Kirkwood and Armada 375.
 
-config LPC32XX_SSP
-	bool "LPC32XX SPI Driver"
-	help
-	  Enable support for SPI on LPC32xx
-
 config MPC8XX_SPI
 	bool "MPC8XX SPI Driver"
 	depends on MPC8xx
diff --git a/drivers/spi/lpc32xx_ssp.c b/drivers/spi/lpc32xx_ssp.c
index e2a593b..ae41b57 100644
--- a/drivers/spi/lpc32xx_ssp.c
+++ b/drivers/spi/lpc32xx_ssp.c
@@ -4,6 +4,9 @@
  * (C) Copyright 2014  DENX Software Engineering GmbH
  * Written-by: Albert ARIBAUD <albert.aribaud at 3adev.fr>
  *
+ * Support for device model:
+ * Copyright (C) 2018 Akash Gajjar <akash at openedev.com>
+ *
  * SPDX-License-Identifier:     GPL-2.0+
  */
 
@@ -13,6 +16,8 @@
 #include <malloc.h>
 #include <spi.h>
 #include <asm/arch/clk.h>
+#include <dm.h>
+#include <dm/platform_data/spi_lpc32xx_ssp.h>
 
 /* SSP chip registers */
 struct ssp_regs {
@@ -36,90 +41,36 @@ struct ssp_regs {
 /* SSP status RX FIFO not empty bit */
 #define SSP_SR_RNE 0x0004
 
-/* lpc32xx spi slave */
-struct lpc32xx_spi_slave {
-	struct spi_slave slave;
+struct lpc32xx_ssp_spi_priv {
 	struct ssp_regs *regs;
 };
 
-static inline struct lpc32xx_spi_slave *to_lpc32xx_spi_slave(
-	struct spi_slave *slave)
+static int lpc32xx_ssp_spi_claim_bus(struct udevice *dev)
 {
-	return container_of(slave, struct lpc32xx_spi_slave, slave);
-}
-
-/* spi_init is called during boot when CONFIG_CMD_SPI is defined */
-void spi_init(void)
-{
-	/*
-	 *  nothing to do: clocking was enabled in lpc32xx_ssp_enable()
-	 * and configuration will be done in spi_setup_slave()
-	*/
+	return 0;
 }
 
-/* the following is called in sequence by do_spi_xfer() */
-
-struct spi_slave *spi_setup_slave(uint bus, uint cs, uint max_hz, uint mode)
+static int lpc32xx_ssp_spi_release_bus(struct udevice *dev)
 {
-	struct lpc32xx_spi_slave *lslave;
-
-	/* we only set up SSP0 for now, so ignore bus */
-
-	if (mode & SPI_3WIRE) {
-		pr_err("3-wire mode not supported");
-		return NULL;
-	}
-
-	if (mode & SPI_SLAVE) {
-		pr_err("slave mode not supported\n");
-		return NULL;
-	}
-
-	if (mode & SPI_PREAMBLE) {
-		pr_err("preamble byte skipping not supported\n");
-		return NULL;
-	}
-
-	lslave = spi_alloc_slave(struct lpc32xx_spi_slave, bus, cs);
-	if (!lslave) {
-		printf("SPI_error: Fail to allocate lpc32xx_spi_slave\n");
-		return NULL;
-	}
-
-	lslave->regs = (struct ssp_regs *)SSP0_BASE;
-
-	/*
-	 * 8 bit frame, SPI fmt, 500kbps -> clock divider is 26.
-	 * Set SCR to 0 and CPSDVSR to 26.
-	 */
-
-	writel(0x7, &lslave->regs->cr0); /* 8-bit chunks, SPI, 1 clk/bit */
-	writel(26, &lslave->regs->cpsr); /* SSP clock = HCLK/26 = 500kbps */
-	writel(0, &lslave->regs->imsc); /* do not raise any interrupts */
-	writel(0, &lslave->regs->icr); /* clear any pending interrupt */
-	writel(0, &lslave->regs->dmacr); /* do not do DMAs */
-	writel(SSP_CR1_SSP_ENABLE, &lslave->regs->cr1); /* enable SSP0 */
-	return &lslave->slave;
+	return 0;
 }
 
-void spi_free_slave(struct spi_slave *slave)
+static int lpc32xx_ssp_spi_set_speed(struct udevice *bus, uint hz)
 {
-	struct lpc32xx_spi_slave *lslave = to_lpc32xx_spi_slave(slave);
-
-	debug("(lpc32xx) spi_free_slave: 0x%08x\n", (u32)lslave);
-	free(lslave);
+	return 0;
 }
 
-int spi_claim_bus(struct spi_slave *slave)
+static int lpc32xx_ssp_spi_set_mode(struct udevice *bus, uint mode)
 {
-	/* only one bus and slave so far, always available */
 	return 0;
 }
 
-int spi_xfer(struct spi_slave *slave, unsigned int bitlen,
-	const void *dout, void *din, unsigned long flags)
+static int lpc32xx_ssp_spi_xfer(struct udevice *dev, uint bitlen,
+				const void *dout, void *din, ulong flags)
 {
-	struct lpc32xx_spi_slave *lslave = to_lpc32xx_spi_slave(slave);
+	struct udevice *bus = dev->parent;
+	struct lpc32xx_ssp_priv *priv = dev_get_priv(bus);
+	struct ssp_regs *regs = priv->regs;
 	int bytelen = bitlen >> 3;
 	int idx_out = 0;
 	int idx_in = 0;
@@ -127,18 +78,68 @@ int spi_xfer(struct spi_slave *slave, unsigned int bitlen,
 
 	start_time = get_timer(0);
 	while ((idx_out < bytelen) || (idx_in < bytelen)) {
-		int status = readl(&lslave->regs->sr);
+		int status = readl(&regs->sr);
 		if ((idx_out < bytelen) && (status & SSP_SR_TNF))
-			writel(((u8 *)dout)[idx_out++], &lslave->regs->data);
+			writel(((u8 *)dout)[idx_out++], &regs->data);
 		if ((idx_in < bytelen) && (status & status & SSP_SR_RNE))
-			((u8 *)din)[idx_in++] = readl(&lslave->regs->data);
+			((u8 *)din)[idx_in++] = readl(&regs->data);
 		if (get_timer(start_time) >= CONFIG_LPC32XX_SSP_TIMEOUT)
 			return -1;
 	}
+
+	return 0;
+}
+
+static int lpc32xx_ssp_spi_probe(struct udevice *bus)
+{
+	struct lpc32xx_ssp_spi_platdata *plat = bus->platdata;
+	struct lpc32xx_ssp_spi_priv = dev_get_priv(bus);
+
+	priv->regs = plat->regs;
+
 	return 0;
 }
 
-void spi_release_bus(struct spi_slave *slave)
+static const struct dm_spi_ops lpc32xx_ssp_spi_ops = {
+	.claim_bus	= lpc32xx_ssp_spi_claim_bus,
+	.release_bus	= lpc32xx_ssp_spi_release_bus,
+	.xfer		= lpc32xx_ssp_spi_xfer,
+	.set_speed	= lpc32xx_ssp_spi_set_speed,
+	.set_mode	= lpc32xx_ssp_spi_set_mode,
+};
+
+#if CONFIG_IS_ENABLED(OF_CONTROL)
+static int lpc32xx_ssp_spi_ofdata_to_platadata(struct udevice *bus)
 {
-	/* do nothing */
+	struct lpc32xx_ssp_spi_platdata *plat = bus->platdata;
+	fdt_addr_t addr;
+
+	addr = devfdt_get_addr(bus);
+	if (addr == FDT_ADDR_T_NONE)
+		return -EINVAL;
+
+	plat->regs = (struct struct ssp_regs *)addr;
+
+	return 0;
 }
+
+/* TODO: update compatibel device tree */
+static const struct udevice_id lpc32xx_ssp_spi_ids[] = {
+	{ .compatible = "" },
+	{}
+};
+#endif
+
+U_BOOT_DRIVER(lpc32xx_ssp_spi) = {
+	.name = "lpc32xx_ssp_spi",
+	.id = UCLASS_SPI,
+#if CONFIG_IS_ENABLED(OF_CONTROL)
+	.of_match = lpc32xx_ssp_spi_ids,
+	.ofdata_to_platdata = lpc32xx_ssp_spi_ofdata_to_platadata,
+	.platdata_auto_alloc_size = sizeof(struct lpc32xx_ssp_spi_platdata),
+#endif
+	.ops = &lpc32xx_ssp_spi_ops,
+	.priv_auto_alloc_size = sizeof(struct lpc32xx_ssp_spi_priv),
+	.probe = lpc32xx_ssp_spi_probe,
+};
+#endif
diff --git a/include/dm/platform_data/spi_lpc32xx_ssp.h b/include/dm/platform_data/spi_lpc32xx_ssp.h
new file mode 100644
index 0000000..ea5cccf
--- /dev/null
+++ b/include/dm/platform_data/spi_lpc32xx_ssp.h
@@ -0,0 +1,15 @@
+/*
+ * Copyright (c) 2018  Akash Gajjar <akash at openedev.com>
+ *
+ * SPDX-License-Identifier:     GPL-2.0+
+ */
+
+#ifndef __lpc32xx_ssp_h
+#define __lpc32xx_ssp_h
+
+struct lpc32xx_ssp_spi_platdata {
+	struct ssp_regs *regs;
+};
+
+#endif /* __lpc32xx_ssp_h */
+
-- 
2.7.4



More information about the U-Boot mailing list