All the mail mirrored from lore.kernel.org
 help / color / mirror / Atom feed
From: Jagan Teki <jteki@openedev.com>
To: u-boot@lists.denx.de
Subject: [U-Boot] [U-Boot PATCH v2 09/17] dm: spi: zynq_spi: Convert to driver model
Date: Sun, 10 May 2015 20:45:49 +0530	[thread overview]
Message-ID: <1431270957-6901-10-git-send-email-jteki@openedev.com> (raw)
In-Reply-To: <1431270957-6901-1-git-send-email-jteki@openedev.com>

This converts the zynq spi driver to use the driver model.

Minimal functional changes like using meaningful name on
structure members wrt mainlined dm spi drivers.
- input_hz -> frequency
- req_hz -> freq
- base -> regs

Signed-off-by: Jagan Teki <jteki@openedev.com>
Acked-by: Simon Glass <sjg@chromium.org>
Cc: Michal Simek <michal.simek@xilinx.com>
Cc: Siva Durga Prasad Paladugu <sivadur@xilinx.com>
---
 drivers/spi/zynq_spi.c | 305 +++++++++++++++++++++++++++++--------------------
 1 file changed, 181 insertions(+), 124 deletions(-)

diff --git a/drivers/spi/zynq_spi.c b/drivers/spi/zynq_spi.c
index e9129da..6cc6db9 100644
--- a/drivers/spi/zynq_spi.c
+++ b/drivers/spi/zynq_spi.c
@@ -1,5 +1,6 @@
 /*
  * (C) Copyright 2013 Inc.
+ * (C) Copyright 2015 Jagan Teki <jteki@openedev.com>
  *
  * Xilinx Zynq PS SPI controller driver (master mode only)
  *
@@ -8,6 +9,8 @@
 
 #include <config.h>
 #include <common.h>
+#include <dm.h>
+#include <errno.h>
 #include <malloc.h>
 #include <spi.h>
 #include <asm/io.h>
@@ -44,180 +47,142 @@ struct zynq_spi_regs {
 	u32 rxdr;	/* 0x20 */
 };
 
-/* zynq spi slave */
-struct zynq_spi_slave {
-	struct spi_slave slave;
-	struct zynq_spi_regs *base;
-	u8 mode;
-	u8 fifo_depth;
+
+/* zynq spi platform data */
+struct zynq_spi_platdata {
+	struct zynq_spi_regs *regs;
+	u32 frequency;		/* input frequency */
 	u32 speed_hz;
-	u32 input_hz;
-	u32 req_hz;
 };
 
-static inline struct zynq_spi_slave *to_zynq_spi_slave(struct spi_slave *slave)
-{
-	return container_of(slave, struct zynq_spi_slave, slave);
-}
+/* zynq spi priv */
+struct zynq_spi_priv {
+	struct zynq_spi_regs *regs;
+	u8 cs;
+	u8 mode;
+	u8 fifo_depth;
+	u32 freq;		/* required frequency */
+};
 
-static inline struct zynq_spi_regs *get_zynq_spi_base(int dev)
+static inline struct zynq_spi_regs *get_zynq_spi_regs(struct udevice *bus)
 {
-	if (dev)
+	if (bus->seq)
 		return (struct zynq_spi_regs *)ZYNQ_SPI_BASEADDR1;
 	else
 		return (struct zynq_spi_regs *)ZYNQ_SPI_BASEADDR0;
 }
 
-static void zynq_spi_init_hw(struct zynq_spi_slave *zslave)
+static int zynq_spi_ofdata_to_platdata(struct udevice *bus)
+{
+	struct zynq_spi_platdata *plat = bus->platdata;
+
+	plat->regs = get_zynq_spi_regs(bus);
+	plat->frequency = 166666700;
+	plat->speed_hz = plat->frequency / 2;
+
+	return 0;
+}
+
+static void zynq_spi_init_hw(struct zynq_spi_priv *priv)
 {
+	struct zynq_spi_regs *regs = priv->regs;
 	u32 confr;
 
 	/* Disable SPI */
-	writel(~ZYNQ_SPI_ENR_SPI_EN_MASK, &zslave->base->enr);
+	writel(~ZYNQ_SPI_ENR_SPI_EN_MASK, &regs->enr);
 
 	/* Disable Interrupts */
-	writel(ZYNQ_SPI_IXR_ALL_MASK, &zslave->base->idr);
+	writel(ZYNQ_SPI_IXR_ALL_MASK, &regs->idr);
 
 	/* Clear RX FIFO */
-	while (readl(&zslave->base->isr) &
+	while (readl(&regs->isr) &
 			ZYNQ_SPI_IXR_RXNEMPTY_MASK)
-		readl(&zslave->base->rxdr);
+		readl(&regs->rxdr);
 
 	/* Clear Interrupts */
-	writel(ZYNQ_SPI_IXR_ALL_MASK, &zslave->base->isr);
+	writel(ZYNQ_SPI_IXR_ALL_MASK, &regs->isr);
 
 	/* Manual slave select and Auto start */
 	confr = ZYNQ_SPI_CR_MCS_MASK | ZYNQ_SPI_CR_CS_MASK |
 		ZYNQ_SPI_CR_MSTREN_MASK;
 	confr &= ~ZYNQ_SPI_CR_MSA_MASK;
-	writel(confr, &zslave->base->cr);
+	writel(confr, &regs->cr);
 
 	/* Enable SPI */
-	writel(ZYNQ_SPI_ENR_SPI_EN_MASK, &zslave->base->enr);
+	writel(ZYNQ_SPI_ENR_SPI_EN_MASK, &regs->enr);
 }
 
-int spi_cs_is_valid(unsigned int bus, unsigned int cs)
+static int zynq_spi_probe(struct udevice *bus)
 {
-	/* 2 bus with 3 chipselect */
-	return bus < 2 && cs < 3;
+	struct zynq_spi_platdata *plat = dev_get_platdata(bus);
+	struct zynq_spi_priv *priv = dev_get_priv(bus);
+
+	priv->regs = plat->regs;
+	priv->cs = spi_chip_select(bus);
+	priv->fifo_depth = ZYNQ_SPI_FIFO_DEPTH;
+
+	/* init the zynq spi hw */
+	zynq_spi_init_hw(priv);
+
+	return 0;
 }
 
-void spi_cs_activate(struct spi_slave *slave)
+static void spi_cs_activate(struct udevice *dev)
 {
-	struct zynq_spi_slave *zslave = to_zynq_spi_slave(slave);
+	struct udevice *bus = dev->parent;
+	struct zynq_spi_priv *priv = dev_get_priv(bus);
+	struct zynq_spi_regs *regs = priv->regs;
 	u32 cr;
 
-	debug("spi_cs_activate: 0x%08x\n", (u32)slave);
-
-	clrbits_le32(&zslave->base->cr, ZYNQ_SPI_CR_CS_MASK);
-	cr = readl(&zslave->base->cr);
+	clrbits_le32(&regs->cr, ZYNQ_SPI_CR_CS_MASK);
+	cr = readl(&regs->cr);
 	/*
 	 * CS cal logic: CS[13:10]
 	 * xxx0	- cs0
 	 * xx01	- cs1
 	 * x011 - cs2
 	 */
-	cr |= (~(0x1 << slave->cs) << 10) & ZYNQ_SPI_CR_CS_MASK;
-	writel(cr, &zslave->base->cr);
+	cr |= (~(0x1 << priv->cs) << 10) & ZYNQ_SPI_CR_CS_MASK;
+	writel(cr, &regs->cr);
 }
 
-void spi_cs_deactivate(struct spi_slave *slave)
+static void spi_cs_deactivate(struct udevice *dev)
 {
-	struct zynq_spi_slave *zslave = to_zynq_spi_slave(slave);
-
-	debug("spi_cs_deactivate: 0x%08x\n", (u32)slave);
-
-	setbits_le32(&zslave->base->cr, ZYNQ_SPI_CR_CS_MASK);
-}
+	struct udevice *bus = dev->parent;
+	struct zynq_spi_priv *priv = dev_get_priv(bus);
+	struct zynq_spi_regs *regs = priv->regs;
 
-void spi_init()
-{
-	/* nothing to do */
+	setbits_le32(&regs->cr, ZYNQ_SPI_CR_CS_MASK);
 }
 
-struct spi_slave *spi_setup_slave(unsigned int bus, unsigned int cs,
-		unsigned int max_hz, unsigned int mode)
+static int zynq_spi_claim_bus(struct udevice *dev)
 {
-	struct zynq_spi_slave *zslave;
-
-	if (!spi_cs_is_valid(bus, cs))
-		return NULL;
-
-	zslave = spi_alloc_slave(struct zynq_spi_slave, bus, cs);
-	if (!zslave) {
-		printf("SPI_error: Fail to allocate zynq_spi_slave\n");
-		return NULL;
-	}
-
-	zslave->base = get_zynq_spi_base(bus);
-	zslave->mode = mode;
-	zslave->fifo_depth = ZYNQ_SPI_FIFO_DEPTH;
-	zslave->input_hz = 166666700;
-	zslave->speed_hz = zslave->input_hz / 2;
-	zslave->req_hz = max_hz;
-
-	/* init the zynq spi hw */
-	zynq_spi_init_hw(zslave);
-
-	return &zslave->slave;
-}
+	struct udevice *bus = dev->parent;
+	struct zynq_spi_priv *priv = dev_get_priv(bus);
+	struct zynq_spi_regs *regs = priv->regs;
 
-void spi_free_slave(struct spi_slave *slave)
-{
-	struct zynq_spi_slave *zslave = to_zynq_spi_slave(slave);
+	writel(ZYNQ_SPI_ENR_SPI_EN_MASK, &regs->enr);
 
-	debug("spi_free_slave: 0x%08x\n", (u32)slave);
-	free(zslave);
+	return 0;
 }
 
-int spi_claim_bus(struct spi_slave *slave)
+static int zynq_spi_release_bus(struct udevice *dev)
 {
-	struct zynq_spi_slave *zslave = to_zynq_spi_slave(slave);
-	u32 confr = 0;
-	u8 baud_rate_val = 0;
+	struct udevice *bus = dev->parent;
+	struct zynq_spi_priv *priv = dev_get_priv(bus);
+	struct zynq_spi_regs *regs = priv->regs;
 
-	writel(~ZYNQ_SPI_ENR_SPI_EN_MASK, &zslave->base->enr);
-
-	/* Set the SPI Clock phase and polarities */
-	confr = readl(&zslave->base->cr);
-	confr &= ~(ZYNQ_SPI_CR_CPHA_MASK | ZYNQ_SPI_CR_CPOL_MASK);
-	if (zslave->mode & SPI_CPHA)
-		confr |= ZYNQ_SPI_CR_CPHA_MASK;
-	if (zslave->mode & SPI_CPOL)
-		confr |= ZYNQ_SPI_CR_CPOL_MASK;
-
-	/* Set the clock frequency */
-	if (zslave->req_hz == 0) {
-		/* Set baudrate x8, if the req_hz is 0 */
-		baud_rate_val = 0x2;
-	} else if (zslave->speed_hz != zslave->req_hz) {
-		while ((baud_rate_val < 8) &&
-				((zslave->input_hz /
-				(2 << baud_rate_val)) > zslave->req_hz))
-			baud_rate_val++;
-		zslave->speed_hz = zslave->req_hz / (2 << baud_rate_val);
-	}
-	confr &= ~ZYNQ_SPI_CR_BRD_MASK;
-	confr |= (baud_rate_val << 3);
-	writel(confr, &zslave->base->cr);
-
-	writel(ZYNQ_SPI_ENR_SPI_EN_MASK, &zslave->base->enr);
+	writel(~ZYNQ_SPI_ENR_SPI_EN_MASK, &regs->enr);
 
 	return 0;
 }
 
-void spi_release_bus(struct spi_slave *slave)
-{
-	struct zynq_spi_slave *zslave = to_zynq_spi_slave(slave);
-
-	debug("spi_release_bus: 0x%08x\n", (u32)slave);
-	writel(~ZYNQ_SPI_ENR_SPI_EN_MASK, &zslave->base->enr);
-}
-
-int spi_xfer(struct spi_slave *slave, unsigned int bitlen, const void *dout,
-		void *din, unsigned long flags)
+static int zynq_spi_xfer(struct udevice *dev, unsigned int bitlen,
+			    const void *dout, void *din, unsigned long flags)
 {
-	struct zynq_spi_slave *zslave = to_zynq_spi_slave(slave);
+	struct udevice *bus = dev->parent;
+	struct zynq_spi_priv *priv = dev_get_priv(bus);
+	struct zynq_spi_regs *regs = priv->regs;
 	u32 len = bitlen / 8;
 	u32 tx_len = len, rx_len = len, tx_tvl;
 	const u8 *tx_buf = dout;
@@ -225,7 +190,7 @@ int spi_xfer(struct spi_slave *slave, unsigned int bitlen, const void *dout,
 	u32 ts, status;
 
 	debug("spi_xfer: bus:%i cs:%i bitlen:%i len:%i flags:%lx\n",
-	      slave->bus, slave->cs, bitlen, len, flags);
+	      bus->seq, priv->cs, bitlen, len, flags);
 
 	if (bitlen % 8) {
 		debug("spi_xfer: Non byte aligned SPI transfer\n");
@@ -233,45 +198,137 @@ int spi_xfer(struct spi_slave *slave, unsigned int bitlen, const void *dout,
 	}
 
 	if (flags & SPI_XFER_BEGIN)
-		spi_cs_activate(slave);
+		spi_cs_activate(dev);
 
 	while (rx_len > 0) {
 		/* Write the data into TX FIFO - tx threshold is fifo_depth */
 		tx_tvl = 0;
-		while ((tx_tvl < zslave->fifo_depth) && tx_len) {
+		while ((tx_tvl < priv->fifo_depth) && tx_len) {
 			if (tx_buf)
 				buf = *tx_buf++;
 			else
 				buf = 0;
-			writel(buf, &zslave->base->txdr);
+			writel(buf, &regs->txdr);
 			tx_len--;
 			tx_tvl++;
 		}
 
 		/* Check TX FIFO completion */
 		ts = get_timer(0);
-		status = readl(&zslave->base->isr);
+		status = readl(&regs->isr);
 		while (!(status & ZYNQ_SPI_IXR_TXOW_MASK)) {
 			if (get_timer(ts) > CONFIG_SYS_ZYNQ_SPI_WAIT) {
 				printf("spi_xfer: Timeout! TX FIFO not full\n");
 				return -1;
 			}
-			status = readl(&zslave->base->isr);
+			status = readl(&regs->isr);
 		}
 
 		/* Read the data from RX FIFO */
-		status = readl(&zslave->base->isr);
+		status = readl(&regs->isr);
 		while (status & ZYNQ_SPI_IXR_RXNEMPTY_MASK) {
-			buf = readl(&zslave->base->rxdr);
+			buf = readl(&regs->rxdr);
 			if (rx_buf)
 				*rx_buf++ = buf;
-			status = readl(&zslave->base->isr);
+			status = readl(&regs->isr);
 			rx_len--;
 		}
 	}
 
 	if (flags & SPI_XFER_END)
-		spi_cs_deactivate(slave);
+		spi_cs_deactivate(dev);
+
+	return 0;
+}
+
+static int zynq_spi_set_speed(struct udevice *bus, uint speed)
+{
+	struct zynq_spi_platdata *plat = bus->platdata;
+	struct zynq_spi_priv *priv = dev_get_priv(bus);
+	struct zynq_spi_regs *regs = priv->regs;
+	uint32_t confr;
+	u8 baud_rate_val = 0;
+
+	if (speed > plat->frequency)
+		speed = plat->frequency;
+
+	/* Set the clock frequency */
+	confr = readl(&regs->cr);
+	if (speed == 0) {
+		/* Set baudrate x8, if the freq is 0 */
+		baud_rate_val = 0x2;
+	} else if (plat->speed_hz != speed) {
+		while ((baud_rate_val < 8) &&
+				((plat->frequency /
+				(2 << baud_rate_val)) > speed))
+			baud_rate_val++;
+		plat->speed_hz = speed / (2 << baud_rate_val);
+	}
+	confr &= ~ZYNQ_SPI_CR_BRD_MASK;
+	confr |= (baud_rate_val << 3);
+
+	writel(confr, &regs->cr);
+	priv->freq = speed;
+
+	debug("zynq_spi_set_speed: regs=%p, mode=%d\n", priv->regs, priv->freq);
 
 	return 0;
 }
+
+static int zynq_spi_set_mode(struct udevice *bus, uint mode)
+{
+	struct zynq_spi_priv *priv = dev_get_priv(bus);
+	struct zynq_spi_regs *regs = priv->regs;
+	uint32_t confr;
+
+	/* Set the SPI Clock phase and polarities */
+	confr = readl(&regs->cr);
+	confr &= ~(ZYNQ_SPI_CR_CPHA_MASK | ZYNQ_SPI_CR_CPOL_MASK);
+
+	if (priv->mode & SPI_CPHA)
+		confr |= ZYNQ_SPI_CR_CPHA_MASK;
+	if (priv->mode & SPI_CPOL)
+		confr |= ZYNQ_SPI_CR_CPOL_MASK;
+
+	writel(confr, &regs->cr);
+	priv->mode = mode;
+
+	debug("zynq_spi_set_mode: regs=%p, mode=%d\n", priv->regs, priv->mode);
+
+	return 0;
+}
+
+static int zynq_cs_info(struct udevice *bus, uint cs,
+			  struct spi_cs_info *info)
+{
+	/* 2 bus with 3 chipselect */
+	if (cs > 2)
+		return -ENODEV;
+	else
+		return 0;
+}
+
+static const struct dm_spi_ops zynq_spi_ops = {
+	.claim_bus	= zynq_spi_claim_bus,
+	.release_bus	= zynq_spi_release_bus,
+	.xfer		= zynq_spi_xfer,
+	.set_speed	= zynq_spi_set_speed,
+	.set_mode	= zynq_spi_set_mode,
+	.cs_info	= zynq_cs_info,
+};
+
+static const struct udevice_id zynq_spi_ids[] = {
+	{ .compatible = "xlnx,zynq-spi" },
+	{ }
+};
+
+U_BOOT_DRIVER(zynq_spi) = {
+	.name	= "zynq_spi",
+	.id	= UCLASS_SPI,
+	.of_match = zynq_spi_ids,
+	.ops	= &zynq_spi_ops,
+	.ofdata_to_platdata = zynq_spi_ofdata_to_platdata,
+	.platdata_auto_alloc_size = sizeof(struct zynq_spi_platdata),
+	.priv_auto_alloc_size = sizeof(struct zynq_spi_priv),
+	.probe	= zynq_spi_probe,
+};
-- 
1.9.1

  parent reply	other threads:[~2015-05-10 15:15 UTC|newest]

Thread overview: 21+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2015-05-10 15:15 [U-Boot] [U-Boot PATCH v2 00/17] spi/sf: Cleansup and driver model conversions Jagan Teki
2015-05-10 15:15 ` [U-Boot] [U-Boot PATCH v2 01/17] spi: Zap andes_spi driver Jagan Teki
2015-05-10 15:15 ` [U-Boot] [U-Boot PATCH v2 02/17] spi: Zap ftssp010_spi driver Jagan Teki
2015-05-10 15:15 ` [U-Boot] [U-Boot PATCH v2 03/17] spi: Zap oc_tiny_spi driver Jagan Teki
2015-05-10 15:15 ` [U-Boot] [U-Boot PATCH v2 04/17] spi: xilinx_spi: Move header code to driver Jagan Teki
2015-05-10 15:15 ` [U-Boot] [U-Boot PATCH v2 05/17] spi: xilinx_spi: Driver clean-up Jagan Teki
2015-05-10 15:15 ` [U-Boot] [U-Boot PATCH v2 06/17] spi: davinci_spi: Move header code to driver Jagan Teki
2015-05-10 15:15 ` [U-Boot] [U-Boot PATCH v2 07/17] spi: davinci_spi: Driver cleanup Jagan Teki
2015-05-10 15:15 ` [U-Boot] [U-Boot PATCH v2 08/17] spi/sf: Minor cleanups Jagan Teki
2015-05-10 15:15 ` Jagan Teki [this message]
2015-05-10 15:15 ` [U-Boot] [U-Boot PATCH v2 10/17] zynq: Kconfig: Enable dm spi and spi_flash Jagan Teki
2015-05-10 15:15 ` [U-Boot] [U-Boot PATCH v2 11/17] dts: zynq: Add zynq spi controller nodes Jagan Teki
2015-05-10 15:15 ` [U-Boot] [U-Boot PATCH v2 12/17] spi: zynq_spi: Add fdt support in driver Jagan Teki
2015-05-10 15:15 ` [U-Boot] [U-Boot PATCH v2 13/17] dts: zynq: Enable spi1 for zc770_xm010 board Jagan Teki
2015-06-16 11:28   ` Jagan Teki
2015-06-16 13:34     ` Michal Simek
2015-05-10 15:15 ` [U-Boot] [U-Boot PATCH v2 14/17] dm: spi: xilinx_spi: Convert to driver model Jagan Teki
2015-05-10 15:15 ` [U-Boot] [U-Boot PATCH v2 15/17] spi: xilinx_spi: Add asm/io.h include file Jagan Teki
2015-05-10 15:15 ` [U-Boot] [U-Boot PATCH v2 16/17] spi: Kconfig: Add Zynq QSPI controller entry Jagan Teki
2015-05-10 15:15 ` [U-Boot] [U-Boot PATCH v2 17/17] spi: Kconfig: Add Zynq SPI " Jagan Teki
2015-05-12  3:57 ` [U-Boot] [U-Boot PATCH v2 00/17] spi/sf: Cleansup and driver model conversions Jagan Teki

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1431270957-6901-10-git-send-email-jteki@openedev.com \
    --to=jteki@openedev.com \
    --cc=u-boot@lists.denx.de \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.