[U-Boot] [U-Boot 0/7] dm: spi: Convert few drivers to driver model

Driver model conversion, patches. - drivers/spi/zynq_spi.c and drivers/spi/xilinx_spi.c
thanks! -- Jagan.
Jagannadha Sutradharudu Teki (7): dm: spi: zynq_spi: Convert to driver model zynq: Kconfig: Enable dm spi and spi_flash dts: zynq: Add zynq spi controller nodes spi: zynq_spi: Add fdt support in driver dts: zynq: Enable spi1 for zc770_xm010 board dm: spi: xilinx_spi: Convert to driver model spi: xilinx_spi: Add asm/io.h include file
arch/arm/Kconfig | 2 + arch/arm/dts/zynq-7000.dtsi | 26 +++ arch/arm/dts/zynq-zc770-xm010.dts | 4 + arch/arm/include/asm/arch-zynq/hardware.h | 2 - doc/device-tree-bindings/spi/spi-zynq.txt | 29 +++ drivers/spi/xilinx_spi.c | 213 +++++++++++--------- drivers/spi/zynq_spi.c | 312 ++++++++++++++++++------------ 7 files changed, 372 insertions(+), 216 deletions(-) create mode 100644 doc/device-tree-bindings/spi/spi-zynq.txt

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: Jagannadha Sutradharudu Teki jagannadh.teki@gmail.com Cc: Simon Glass sjg@chromium.org Cc: Michal Simek michal.simek@xilinx.com Cc: Siva Durga Prasad Paladugu sivadur@xilinx.com --- Note: Siva Durga Prasad, can you test this on zc770_xm010
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 ff1ec6a..62edbbe 100644 --- a/drivers/spi/zynq_spi.c +++ b/drivers/spi/zynq_spi.c @@ -1,5 +1,6 @@ /* * (C) Copyright 2013 Inc. + * (C) Copyright 2015 Jagannadha Sutradharudu Teki jagannadh.teki@gmail.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, ®s->enr);
/* Disable Interrupts */ - writel(ZYNQ_SPI_IXR_ALL_MASK, &zslave->base->idr); + writel(ZYNQ_SPI_IXR_ALL_MASK, ®s->idr);
/* Clear RX FIFO */ - while (readl(&zslave->base->isr) & + while (readl(®s->isr) & ZYNQ_SPI_IXR_RXNEMPTY_MASK) - readl(&zslave->base->rxdr); + readl(®s->rxdr);
/* Clear Interrupts */ - writel(ZYNQ_SPI_IXR_ALL_MASK, &zslave->base->isr); + writel(ZYNQ_SPI_IXR_ALL_MASK, ®s->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, ®s->cr);
/* Enable SPI */ - writel(ZYNQ_SPI_ENR_SPI_EN_MASK, &zslave->base->enr); + writel(ZYNQ_SPI_ENR_SPI_EN_MASK, ®s->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(®s->cr, ZYNQ_SPI_CR_CS_MASK); + cr = readl(®s->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, ®s->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(®s->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, ®s->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, ®s->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, ®s->txdr); tx_len--; tx_tvl++; }
/* Check TX FIFO completion */ ts = get_timer(0); - status = readl(&zslave->base->isr); + status = readl(®s->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(®s->isr); }
/* Read the data from RX FIFO */ - status = readl(&zslave->base->isr); + status = readl(®s->isr); while (status & ZYNQ_SPI_IXR_RXNEMPTY_MASK) { - buf = readl(&zslave->base->rxdr); + buf = readl(®s->rxdr); if (rx_buf) *rx_buf++ = buf; - status = readl(&zslave->base->isr); + status = readl(®s->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(®s->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, ®s->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(®s->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, ®s->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, +};

Hi Jagan,
On 23 April 2015 at 08:15, Jagannadha Sutradharudu Teki jagannadh.teki@gmail.com wrote:
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: Jagannadha Sutradharudu Teki jagannadh.teki@gmail.com Cc: Simon Glass sjg@chromium.org Cc: Michal Simek michal.simek@xilinx.com Cc: Siva Durga Prasad Paladugu sivadur@xilinx.com
Note: Siva Durga Prasad, can you test this on zc770_xm010
drivers/spi/zynq_spi.c | 305 +++++++++++++++++++++++++++++-------------------- 1 file changed, 181 insertions(+), 124 deletions(-)
Acked-by: Simon Glass sjg@chromium.org
diff --git a/drivers/spi/zynq_spi.c b/drivers/spi/zynq_spi.c index ff1ec6a..62edbbe 100644 --- a/drivers/spi/zynq_spi.c +++ b/drivers/spi/zynq_spi.c @@ -1,5 +1,6 @@ /*
- (C) Copyright 2013 Inc.
- (C) Copyright 2015 Jagannadha Sutradharudu Teki jagannadh.teki@gmail.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)
I see you remove this in a latest patch.
{
if (dev)
if (bus->seq) return (struct zynq_spi_regs *)ZYNQ_SPI_BASEADDR1; else return (struct zynq_spi_regs *)ZYNQ_SPI_BASEADDR0;
}
[snip]
Regards, Simon

Hi Simon,
On 23 April 2015 at 23:53, Simon Glass sjg@chromium.org wrote:
Hi Jagan,
On 23 April 2015 at 08:15, Jagannadha Sutradharudu Teki jagannadh.teki@gmail.com wrote:
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: Jagannadha Sutradharudu Teki jagannadh.teki@gmail.com Cc: Simon Glass sjg@chromium.org Cc: Michal Simek michal.simek@xilinx.com Cc: Siva Durga Prasad Paladugu sivadur@xilinx.com
Note: Siva Durga Prasad, can you test this on zc770_xm010
drivers/spi/zynq_spi.c | 305 +++++++++++++++++++++++++++++-------------------- 1 file changed, 181 insertions(+), 124 deletions(-)
Acked-by: Simon Glass sjg@chromium.org
diff --git a/drivers/spi/zynq_spi.c b/drivers/spi/zynq_spi.c index ff1ec6a..62edbbe 100644 --- a/drivers/spi/zynq_spi.c +++ b/drivers/spi/zynq_spi.c @@ -1,5 +1,6 @@ /*
- (C) Copyright 2013 Inc.
- (C) Copyright 2015 Jagannadha Sutradharudu Teki jagannadh.teki@gmail.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)
I see you remove this in a latest patch.
Yes, added dts node for retrieving reg.
{
if (dev)
if (bus->seq) return (struct zynq_spi_regs *)ZYNQ_SPI_BASEADDR1; else return (struct zynq_spi_regs *)ZYNQ_SPI_BASEADDR0;
}
[snip]
thanks!

Enabled CONFIG_DM_SPI and CONFIG_DM_SPI_FLASH for zynq soc.
Signed-off-by: Jagannadha Sutradharudu Teki jagannadh.teki@gmail.com Cc: Simon Glass sjg@chromium.org Cc: Michal Simek michal.simek@xilinx.com Cc: Siva Durga Prasad Paladugu sivadur@xilinx.com --- arch/arm/Kconfig | 2 ++ 1 file changed, 2 insertions(+)
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index 3702bb0..40f1186 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig @@ -670,6 +670,8 @@ config ZYNQ select CPU_V7 select SUPPORT_SPL select DM + select DM_SPI + select DM_SPI_FLASH
config TARGET_XILINX_ZYNQMP bool "Support Xilinx ZynqMP Platform"

On 23 April 2015 at 08:15, Jagannadha Sutradharudu Teki jagannadh.teki@gmail.com wrote:
Enabled CONFIG_DM_SPI and CONFIG_DM_SPI_FLASH for zynq soc.
Signed-off-by: Jagannadha Sutradharudu Teki jagannadh.teki@gmail.com Cc: Simon Glass sjg@chromium.org Cc: Michal Simek michal.simek@xilinx.com Cc: Siva Durga Prasad Paladugu sivadur@xilinx.com
arch/arm/Kconfig | 2 ++ 1 file changed, 2 insertions(+)
Acked-by: Simon Glass sjg@chromium.org

This patch adds zynq spi controller nodes in zynq-7000.dtsi.
Signed-off-by: Jagannadha Sutradharudu Teki jagannadh.teki@gmail.com Cc: Simon Glass sjg@chromium.org Cc: Michal Simek michal.simek@xilinx.com Cc: Siva Durga Prasad Paladugu sivadur@xilinx.com --- arch/arm/dts/zynq-7000.dtsi | 24 ++++++++++++++++++++++++ doc/device-tree-bindings/spi/spi-zynq.txt | 27 +++++++++++++++++++++++++++ 2 files changed, 51 insertions(+) create mode 100644 doc/device-tree-bindings/spi/spi-zynq.txt
diff --git a/arch/arm/dts/zynq-7000.dtsi b/arch/arm/dts/zynq-7000.dtsi index 2d076f1..f66f8dc 100644 --- a/arch/arm/dts/zynq-7000.dtsi +++ b/arch/arm/dts/zynq-7000.dtsi @@ -109,6 +109,30 @@ interrupts = <0 50 4>; };
+ spi0: spi@e0006000 { + compatible = "xlnx,zynq-spi"; + reg = <0xe0006000 0x1000>; + status = "disabled"; + interrupt-parent = <&intc>; + interrupts = <0 26 4>; + clocks = <&clkc 25>, <&clkc 34>; + clock-names = "ref_clk", "pclk"; + #address-cells = <1>; + #size-cells = <0>; + }; + + spi1: spi@e0007000 { + compatible = "xlnx,zynq-spi"; + reg = <0xe0007000 0x1000>; + status = "disabled"; + interrupt-parent = <&intc>; + interrupts = <0 49 4>; + clocks = <&clkc 26>, <&clkc 35>; + clock-names = "ref_clk", "pclk"; + #address-cells = <1>; + #size-cells = <0>; + }; + gem0: ethernet@e000b000 { compatible = "cdns,gem"; reg = <0xe000b000 0x4000>; diff --git a/doc/device-tree-bindings/spi/spi-zynq.txt b/doc/device-tree-bindings/spi/spi-zynq.txt new file mode 100644 index 0000000..a7c2757 --- /dev/null +++ b/doc/device-tree-bindings/spi/spi-zynq.txt @@ -0,0 +1,27 @@ +Zynq SPI controller Device Tree Bindings +---------------------------------------- + +Required properties: +- compatible : Should be "xlnx,spi-zynq". +- reg : Physical base address and size of SPI registers map. +- status : Status will be disabled in dtsi and enabled in required dts. +- interrupt-parent : Must be core interrupt controller. +- interrupts : Property with a value describing the interrupt + number. +- clocks : Clock phandles (see clock bindings for details). +- clock-names : List of input clock names - "ref_clk", "pclk" + (See clock bindings for details). + +Example: + + spi@e0006000 { + compatible = "xlnx,zynq-spi"; + reg = <0xe0006000 0x1000>; + status = "disabled"; + interrupt-parent = <&intc>; + interrupts = <0 26 4>; + clocks = <&clkc 25>, <&clkc 34>; + clock-names = "ref_clk", "pclk"; + #address-cells = <1>; + #size-cells = <0>; + } ;

On 23 April 2015 at 08:15, Jagannadha Sutradharudu Teki jagannadh.teki@gmail.com wrote:
This patch adds zynq spi controller nodes in zynq-7000.dtsi.
Signed-off-by: Jagannadha Sutradharudu Teki jagannadh.teki@gmail.com Cc: Simon Glass sjg@chromium.org Cc: Michal Simek michal.simek@xilinx.com Cc: Siva Durga Prasad Paladugu sivadur@xilinx.com
arch/arm/dts/zynq-7000.dtsi | 24 ++++++++++++++++++++++++ doc/device-tree-bindings/spi/spi-zynq.txt | 27 +++++++++++++++++++++++++++ 2 files changed, 51 insertions(+) create mode 100644 doc/device-tree-bindings/spi/spi-zynq.txt
Acked-by: Simon Glass sjg@chromium.org

Now zynq spi driver platform data is controlled by devicetree, enable the status by saying "okay" on respective board dts to use the devicetree generated platdata.
Ex: &spi1 { status = "okay"; };
Signed-off-by: Jagannadha Sutradharudu Teki jagannadh.teki@gmail.com Cc: Simon Glass sjg@chromium.org Cc: Michal Simek michal.simek@xilinx.com Cc: Siva Durga Prasad Paladugu sivadur@xilinx.com --- arch/arm/dts/zynq-7000.dtsi | 2 ++ arch/arm/include/asm/arch-zynq/hardware.h | 2 -- doc/device-tree-bindings/spi/spi-zynq.txt | 2 ++ drivers/spi/zynq_spi.c | 23 +++++++++++++---------- 4 files changed, 17 insertions(+), 12 deletions(-)
diff --git a/arch/arm/dts/zynq-7000.dtsi b/arch/arm/dts/zynq-7000.dtsi index f66f8dc..9207159 100644 --- a/arch/arm/dts/zynq-7000.dtsi +++ b/arch/arm/dts/zynq-7000.dtsi @@ -117,6 +117,7 @@ interrupts = <0 26 4>; clocks = <&clkc 25>, <&clkc 34>; clock-names = "ref_clk", "pclk"; + spi-max-frequency = <166666700>; #address-cells = <1>; #size-cells = <0>; }; @@ -129,6 +130,7 @@ interrupts = <0 49 4>; clocks = <&clkc 26>, <&clkc 35>; clock-names = "ref_clk", "pclk"; + spi-max-frequency = <166666700>; #address-cells = <1>; #size-cells = <0>; }; diff --git a/arch/arm/include/asm/arch-zynq/hardware.h b/arch/arm/include/asm/arch-zynq/hardware.h index e2e0b73..df9b06b 100644 --- a/arch/arm/include/asm/arch-zynq/hardware.h +++ b/arch/arm/include/asm/arch-zynq/hardware.h @@ -19,8 +19,6 @@ #define ZYNQ_SDHCI_BASEADDR1 0xE0101000 #define ZYNQ_I2C_BASEADDR0 0xE0004000 #define ZYNQ_I2C_BASEADDR1 0xE0005000 -#define ZYNQ_SPI_BASEADDR0 0xE0006000 -#define ZYNQ_SPI_BASEADDR1 0xE0007000 #define ZYNQ_QSPI_BASEADDR 0xE000D000 #define ZYNQ_SMC_BASEADDR 0xE000E000 #define ZYNQ_NAND_BASEADDR 0xE1000000 diff --git a/doc/device-tree-bindings/spi/spi-zynq.txt b/doc/device-tree-bindings/spi/spi-zynq.txt index a7c2757..f397a36 100644 --- a/doc/device-tree-bindings/spi/spi-zynq.txt +++ b/doc/device-tree-bindings/spi/spi-zynq.txt @@ -11,6 +11,7 @@ Required properties: - clocks : Clock phandles (see clock bindings for details). - clock-names : List of input clock names - "ref_clk", "pclk" (See clock bindings for details). +- spi-max-frequency : Maximum SPI clocking speed of device in Hz
Example:
@@ -22,6 +23,7 @@ Example: interrupts = <0 26 4>; clocks = <&clkc 25>, <&clkc 34>; clock-names = "ref_clk", "pclk"; + spi-max-frequency = <166666700>; #address-cells = <1>; #size-cells = <0>; } ; diff --git a/drivers/spi/zynq_spi.c b/drivers/spi/zynq_spi.c index 62edbbe..df4a99e 100644 --- a/drivers/spi/zynq_spi.c +++ b/drivers/spi/zynq_spi.c @@ -13,9 +13,12 @@ #include <errno.h> #include <malloc.h> #include <spi.h> +#include <fdtdec.h> #include <asm/io.h> #include <asm/arch/hardware.h>
+DECLARE_GLOBAL_DATA_PTR; + /* zynq spi register bit masks ZYNQ_SPI_<REG>_<BIT>_MASK */ #define ZYNQ_SPI_CR_MSA_MASK BIT(15) /* Manual start enb */ #define ZYNQ_SPI_CR_MCS_MASK BIT(14) /* Manual chip select */ @@ -64,22 +67,22 @@ struct zynq_spi_priv { u32 freq; /* required frequency */ };
-static inline struct zynq_spi_regs *get_zynq_spi_regs(struct udevice *bus) -{ - if (bus->seq) - return (struct zynq_spi_regs *)ZYNQ_SPI_BASEADDR1; - else - return (struct zynq_spi_regs *)ZYNQ_SPI_BASEADDR0; -} - static int zynq_spi_ofdata_to_platdata(struct udevice *bus) { struct zynq_spi_platdata *plat = bus->platdata; + const void *blob = gd->fdt_blob; + int node = bus->of_offset; + + plat->regs = (struct zynq_spi_regs *)fdtdec_get_addr(blob, node, "reg");
- plat->regs = get_zynq_spi_regs(bus); - plat->frequency = 166666700; + /* FIXME: Use 250MHz as a suitable default */ + plat->frequency = fdtdec_get_int(blob, node, "spi-max-frequency", + 250000000); plat->speed_hz = plat->frequency / 2;
+ debug("zynq_spi_ofdata_to_platdata: regs=%p max-frequency=%d\n", + plat->regs, plat->frequency); + return 0; }

Hi Jagan,
On 23 April 2015 at 08:15, Jagannadha Sutradharudu Teki jagannadh.teki@gmail.com wrote:
Now zynq spi driver platform data is controlled by devicetree, enable the status by saying "okay" on respective board dts to use the devicetree generated platdata.
Ex: &spi1 { status = "okay"; };
Signed-off-by: Jagannadha Sutradharudu Teki jagannadh.teki@gmail.com Cc: Simon Glass sjg@chromium.org Cc: Michal Simek michal.simek@xilinx.com Cc: Siva Durga Prasad Paladugu sivadur@xilinx.com
arch/arm/dts/zynq-7000.dtsi | 2 ++ arch/arm/include/asm/arch-zynq/hardware.h | 2 -- doc/device-tree-bindings/spi/spi-zynq.txt | 2 ++ drivers/spi/zynq_spi.c | 23 +++++++++++++---------- 4 files changed, 17 insertions(+), 12 deletions(-)
Acked-by: Simon Glass sjg@chromium.org
diff --git a/arch/arm/dts/zynq-7000.dtsi b/arch/arm/dts/zynq-7000.dtsi index f66f8dc..9207159 100644 --- a/arch/arm/dts/zynq-7000.dtsi +++ b/arch/arm/dts/zynq-7000.dtsi @@ -117,6 +117,7 @@ interrupts = <0 26 4>; clocks = <&clkc 25>, <&clkc 34>; clock-names = "ref_clk", "pclk";
spi-max-frequency = <166666700>; #address-cells = <1>; #size-cells = <0>; };
@@ -129,6 +130,7 @@ interrupts = <0 49 4>; clocks = <&clkc 26>, <&clkc 35>; clock-names = "ref_clk", "pclk";
spi-max-frequency = <166666700>; #address-cells = <1>; #size-cells = <0>; };
diff --git a/arch/arm/include/asm/arch-zynq/hardware.h b/arch/arm/include/asm/arch-zynq/hardware.h index e2e0b73..df9b06b 100644 --- a/arch/arm/include/asm/arch-zynq/hardware.h +++ b/arch/arm/include/asm/arch-zynq/hardware.h @@ -19,8 +19,6 @@ #define ZYNQ_SDHCI_BASEADDR1 0xE0101000 #define ZYNQ_I2C_BASEADDR0 0xE0004000 #define ZYNQ_I2C_BASEADDR1 0xE0005000 -#define ZYNQ_SPI_BASEADDR0 0xE0006000 -#define ZYNQ_SPI_BASEADDR1 0xE0007000 #define ZYNQ_QSPI_BASEADDR 0xE000D000 #define ZYNQ_SMC_BASEADDR 0xE000E000 #define ZYNQ_NAND_BASEADDR 0xE1000000 diff --git a/doc/device-tree-bindings/spi/spi-zynq.txt b/doc/device-tree-bindings/spi/spi-zynq.txt index a7c2757..f397a36 100644 --- a/doc/device-tree-bindings/spi/spi-zynq.txt +++ b/doc/device-tree-bindings/spi/spi-zynq.txt @@ -11,6 +11,7 @@ Required properties:
- clocks : Clock phandles (see clock bindings for details).
- clock-names : List of input clock names - "ref_clk", "pclk" (See clock bindings for details).
+- spi-max-frequency : Maximum SPI clocking speed of device in Hz
Example:
@@ -22,6 +23,7 @@ Example: interrupts = <0 26 4>; clocks = <&clkc 25>, <&clkc 34>; clock-names = "ref_clk", "pclk";
spi-max-frequency = <166666700>; #address-cells = <1>; #size-cells = <0>; } ;
diff --git a/drivers/spi/zynq_spi.c b/drivers/spi/zynq_spi.c index 62edbbe..df4a99e 100644 --- a/drivers/spi/zynq_spi.c +++ b/drivers/spi/zynq_spi.c @@ -13,9 +13,12 @@ #include <errno.h> #include <malloc.h> #include <spi.h> +#include <fdtdec.h> #include <asm/io.h> #include <asm/arch/hardware.h>
+DECLARE_GLOBAL_DATA_PTR;
/* zynq spi register bit masks ZYNQ_SPI_<REG>_<BIT>_MASK */ #define ZYNQ_SPI_CR_MSA_MASK BIT(15) /* Manual start enb */ #define ZYNQ_SPI_CR_MCS_MASK BIT(14) /* Manual chip select */ @@ -64,22 +67,22 @@ struct zynq_spi_priv { u32 freq; /* required frequency */ };
-static inline struct zynq_spi_regs *get_zynq_spi_regs(struct udevice *bus) -{
if (bus->seq)
return (struct zynq_spi_regs *)ZYNQ_SPI_BASEADDR1;
else
return (struct zynq_spi_regs *)ZYNQ_SPI_BASEADDR0;
-}
static int zynq_spi_ofdata_to_platdata(struct udevice *bus) { struct zynq_spi_platdata *plat = bus->platdata;
const void *blob = gd->fdt_blob;
int node = bus->of_offset;
plat->regs = (struct zynq_spi_regs *)fdtdec_get_addr(blob, node, "reg");
Or dev_get_addr() if you like.
plat->regs = get_zynq_spi_regs(bus);
plat->frequency = 166666700;
/* FIXME: Use 250MHz as a suitable default */
plat->frequency = fdtdec_get_int(blob, node, "spi-max-frequency",
250000000); plat->speed_hz = plat->frequency / 2;
debug("zynq_spi_ofdata_to_platdata: regs=%p max-frequency=%d\n",
plat->regs, plat->frequency);
return 0;
}
-- 1.9.1
Regards, Simon

This patch enables spi1 for zynq zc770_xm010 board dts.
Signed-off-by: Jagannadha Sutradharudu Teki jagannadh.teki@gmail.com Cc: Simon Glass sjg@chromium.org Cc: Michal Simek michal.simek@xilinx.com Cc: Siva Durga Prasad Paladugu sivadur@xilinx.com --- arch/arm/dts/zynq-zc770-xm010.dts | 4 ++++ 1 file changed, 4 insertions(+)
diff --git a/arch/arm/dts/zynq-zc770-xm010.dts b/arch/arm/dts/zynq-zc770-xm010.dts index 5e66174..e793a61 100644 --- a/arch/arm/dts/zynq-zc770-xm010.dts +++ b/arch/arm/dts/zynq-zc770-xm010.dts @@ -21,3 +21,7 @@ reg = <0 0x40000000>; }; }; + +&spi1 { + status = "okay"; +};

On 23 April 2015 at 08:15, Jagannadha Sutradharudu Teki jagannadh.teki@gmail.com wrote:
This patch enables spi1 for zynq zc770_xm010 board dts.
Signed-off-by: Jagannadha Sutradharudu Teki jagannadh.teki@gmail.com Cc: Simon Glass sjg@chromium.org Cc: Michal Simek michal.simek@xilinx.com Cc: Siva Durga Prasad Paladugu sivadur@xilinx.com
arch/arm/dts/zynq-zc770-xm010.dts | 4 ++++ 1 file changed, 4 insertions(+)
Acked-by: Simon Glass sjg@chromium.org
diff --git a/arch/arm/dts/zynq-zc770-xm010.dts b/arch/arm/dts/zynq-zc770-xm010.dts index 5e66174..e793a61 100644 --- a/arch/arm/dts/zynq-zc770-xm010.dts +++ b/arch/arm/dts/zynq-zc770-xm010.dts @@ -21,3 +21,7 @@ reg = <0 0x40000000>; }; };
+&spi1 {
status = "okay";
+};
1.9.1

This converts the xilinx spi driver to use the driver model.
Signed-off-by: Jagannadha Sutradharudu Teki jagannadh.teki@gmail.com Cc: Simon Glass sjg@chromium.org Cc: Michal Simek michal.simek@xilinx.com --- Note: Michal, can you test this, I don't have hardware.
drivers/spi/xilinx_spi.c | 212 +++++++++++++++++++++++++++-------------------- 1 file changed, 124 insertions(+), 88 deletions(-)
diff --git a/drivers/spi/xilinx_spi.c b/drivers/spi/xilinx_spi.c index 3803c4c..4acade4 100644 --- a/drivers/spi/xilinx_spi.c +++ b/drivers/spi/xilinx_spi.c @@ -4,6 +4,7 @@ * Supports 8 bit SPI transfers only, with or w/o FIFO * * Based on bfin_spi.c, by way of altera_spi.c + * Copyright (c) 2015 Jagannadha Sutradharudu Teki jagannadh.teki@gmail.com * Copyright (c) 2012 Stephan Linz linz@li-pro.net * Copyright (c) 2010 Graeme Smecher graeme.smecher@mail.mcgill.ca * Copyright (c) 2010 Thomas Chou thomas@wytron.com.tw @@ -14,6 +15,8 @@
#include <config.h> #include <common.h> +#include <dm.h> +#include <errno.h> #include <malloc.h> #include <spi.h>
@@ -79,7 +82,7 @@ #endif
/* xilinx spi register set */ -struct xilinx_spi_reg { +struct xilinx_spi_regs { u32 __space0__[7]; u32 dgier; /* Device Global Interrupt Enable Register (DGIER) */ u32 ipisr; /* IP Interrupt Status Register (IPISR) */ @@ -97,113 +100,76 @@ struct xilinx_spi_reg { u32 spirfor; /* SPI Receive FIFO Occupancy Register (SPIRFOR) */ };
-/* xilinx spi slave */ -struct xilinx_spi_slave { - struct spi_slave slave; - struct xilinx_spi_reg *regs; +/* xilinx spi priv */ +struct xilinx_spi_priv { + struct xilinx_spi_regs *regs; unsigned int freq; unsigned int mode; + unsigned int cs; };
-static inline struct xilinx_spi_slave *to_xilinx_spi_slave( - struct spi_slave *slave) -{ - return container_of(slave, struct xilinx_spi_slave, slave); -} - static unsigned long xilinx_spi_base_list[] = CONFIG_SYS_XILINX_SPI_LIST; -int spi_cs_is_valid(unsigned int bus, unsigned int cs) +static int xilinx_spi_probe(struct udevice *bus) { - return bus < ARRAY_SIZE(xilinx_spi_base_list) && cs < 32; -} + struct xilinx_spi_priv *priv = dev_get_priv(bus); + struct xilinx_spi_regs *regs = priv->regs;
-void spi_cs_activate(struct spi_slave *slave) -{ - struct xilinx_spi_slave *xilspi = to_xilinx_spi_slave(slave); + priv->regs = (struct xilinx_spi_regs *)xilinx_spi_base_list[bus->seq]; + priv->cs = spi_chip_select(bus);
- writel(SPISSR_ACT(slave->cs), &xilspi->regs->spissr); -} + writel(SPISSR_RESET_VALUE, ®s->srr);
-void spi_cs_deactivate(struct spi_slave *slave) -{ - struct xilinx_spi_slave *xilspi = to_xilinx_spi_slave(slave); - - writel(SPISSR_OFF, &xilspi->regs->spissr); -} - -void spi_init(void) -{ - /* do nothing */ + return 0; }
-struct spi_slave *spi_setup_slave(unsigned int bus, unsigned int cs, - unsigned int max_hz, unsigned int mode) +static void spi_cs_activate(struct udevice *dev) { - struct xilinx_spi_slave *xilspi; - - if (!spi_cs_is_valid(bus, cs)) { - printf("XILSPI error: unsupported bus %d / cs %d\n", bus, cs); - return NULL; - } - - xilspi = spi_alloc_slave(struct xilinx_spi_slave, bus, cs); - if (!xilspi) { - printf("XILSPI error: malloc of SPI structure failed\n"); - return NULL; - } - xilspi->regs = (struct xilinx_spi_reg *)xilinx_spi_base_list[bus]; - xilspi->freq = max_hz; - xilspi->mode = mode; - debug("spi_setup_slave: bus:%i cs:%i base:%p mode:%x max_hz:%d\n", - bus, cs, xilspi->regs, xilspi->mode, xilspi->freq); - - writel(SPISSR_RESET_VALUE, &xilspi->regs->srr); + struct udevice *bus = dev->parent; + struct xilinx_spi_priv *priv = dev_get_priv(bus); + struct xilinx_spi_regs *regs = priv->regs;
- return &xilspi->slave; + writel(SPISSR_ACT(priv->cs), ®s->spissr); }
-void spi_free_slave(struct spi_slave *slave) +static void spi_cs_deactivate(struct udevice *dev) { - struct xilinx_spi_slave *xilspi = to_xilinx_spi_slave(slave); + struct udevice *bus = dev->parent; + struct xilinx_spi_priv *priv = dev_get_priv(bus); + struct xilinx_spi_regs *regs = priv->regs;
- free(xilspi); + writel(SPISSR_OFF, ®s->spissr); }
-int spi_claim_bus(struct spi_slave *slave) +static int xilinx_spi_claim_bus(struct udevice *dev) { - struct xilinx_spi_slave *xilspi = to_xilinx_spi_slave(slave); - u32 spicr; + struct udevice *bus = dev->parent; + struct xilinx_spi_priv *priv = dev_get_priv(bus); + struct xilinx_spi_regs *regs = priv->regs;
- debug("spi_claim_bus: bus:%i cs:%i\n", slave->bus, slave->cs); - writel(SPISSR_OFF, &xilspi->regs->spissr); + writel(SPISSR_OFF, ®s->spissr); + writel(XILSPI_SPICR_DFLT_ON, ®s->spicr);
- spicr = XILSPI_SPICR_DFLT_ON; - if (xilspi->mode & SPI_LSB_FIRST) - spicr |= SPICR_LSB_FIRST; - if (xilspi->mode & SPI_CPHA) - spicr |= SPICR_CPHA; - if (xilspi->mode & SPI_CPOL) - spicr |= SPICR_CPOL; - if (xilspi->mode & SPI_LOOP) - spicr |= SPICR_LOOP; - - writel(spicr, &xilspi->regs->spicr); return 0; }
-void spi_release_bus(struct spi_slave *slave) +static int xilinx_spi_release_bus(struct udevice *dev) { - struct xilinx_spi_slave *xilspi = to_xilinx_spi_slave(slave); + struct udevice *bus = dev->parent; + struct xilinx_spi_priv *priv = dev_get_priv(bus); + struct xilinx_spi_regs *regs = priv->regs; + + writel(SPISSR_OFF, ®s->spissr); + writel(XILSPI_SPICR_DFLT_OFF, ®s->spicr);
- debug("spi_release_bus: bus:%i cs:%i\n", slave->bus, slave->cs); - writel(SPISSR_OFF, &xilspi->regs->spissr); - writel(XILSPI_SPICR_DFLT_OFF, &xilspi->regs->spicr); + return 0; }
-int spi_xfer(struct spi_slave *slave, unsigned int bitlen, const void *dout, - void *din, unsigned long flags) +static int xilinx_spi_xfer(struct udevice *dev, unsigned int bitlen, + const void *dout, void *din, unsigned long flags) { - struct xilinx_spi_slave *xilspi = to_xilinx_spi_slave(slave); + struct udevice *bus = dev->parent; + struct xilinx_spi_priv *priv = dev_get_priv(bus); + struct xilinx_spi_regs *regs = priv->regs; /* assume spi core configured to do 8 bit transfers */ unsigned int bytes = bitlen / XILSPI_MAX_XFER_BITS; const unsigned char *txp = dout; @@ -212,7 +178,7 @@ int spi_xfer(struct spi_slave *slave, unsigned int bitlen, const void *dout, unsigned global_timeout;
debug("spi_xfer: bus:%i cs:%i bitlen:%i bytes:%i flags:%lx\n", - slave->bus, slave->cs, bitlen, bytes, flags); + bus->seq, priv->cs, bitlen, bytes, flags);
if (bitlen == 0) goto done; @@ -225,8 +191,8 @@ int spi_xfer(struct spi_slave *slave, unsigned int bitlen, const void *dout, }
/* empty read buffer */ - while (rxecount && !(readl(&xilspi->regs->spisr) & SPISR_RX_EMPTY)) { - readl(&xilspi->regs->spidrr); + while (rxecount && !(readl(®s->spisr) & SPISR_RX_EMPTY)) { + readl(®s->spidrr); rxecount--; }
@@ -236,11 +202,11 @@ 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);
/* at least 1usec or greater, leftover 1 */ - global_timeout = xilspi->freq > XILSPI_MAX_XFER_BITS * 1000000 ? 2 : - (XILSPI_MAX_XFER_BITS * 1000000 / xilspi->freq) + 1; + global_timeout = priv->freq > XILSPI_MAX_XFER_BITS * 1000000 ? 2 : + (XILSPI_MAX_XFER_BITS * 1000000 / priv->freq) + 1;
while (bytes--) { unsigned timeout = global_timeout; @@ -249,8 +215,8 @@ int spi_xfer(struct spi_slave *slave, unsigned int bitlen, const void *dout, debug("spi_xfer: tx:%x ", d);
/* write out and wait for processing (receive data) */ - writel(d & SPIDTR_8BIT_MASK, &xilspi->regs->spidtr); - while (timeout && readl(&xilspi->regs->spisr) + writel(d & SPIDTR_8BIT_MASK, ®s->spidtr); + while (timeout && readl(®s->spisr) & SPISR_RX_EMPTY) { timeout--; udelay(1); @@ -262,7 +228,7 @@ int spi_xfer(struct spi_slave *slave, unsigned int bitlen, const void *dout, }
/* read Rx element and push into data in buffer */ - d = readl(&xilspi->regs->spidrr) & SPIDRR_8BIT_MASK; + d = readl(®s->spidrr) & SPIDRR_8BIT_MASK; if (rxp) *rxp++ = d; debug("spi_xfer: rx:%x\n", d); @@ -270,7 +236,77 @@ int spi_xfer(struct spi_slave *slave, unsigned int bitlen, const void *dout,
done: if (flags & SPI_XFER_END) - spi_cs_deactivate(slave); + spi_cs_deactivate(dev); + + return 0; +} + +static int xilinx_spi_set_speed(struct udevice *bus, uint speed) +{ + struct xilinx_spi_priv *priv = dev_get_priv(bus); + + priv->freq = speed; + + debug("xilinx_spi_set_speed: regs=%p, mode=%d\n", priv->regs, + priv->freq); + + return 0; +} + +static int xilinx_spi_set_mode(struct udevice *bus, uint mode) +{ + struct xilinx_spi_priv *priv = dev_get_priv(bus); + struct xilinx_spi_regs *regs = priv->regs; + uint32_t spicr; + + spicr = readl(®s->spicr); + if (priv->mode & SPI_LSB_FIRST) + spicr |= SPICR_LSB_FIRST; + if (priv->mode & SPI_CPHA) + spicr |= SPICR_CPHA; + if (priv->mode & SPI_CPOL) + spicr |= SPICR_CPOL; + if (priv->mode & SPI_LOOP) + spicr |= SPICR_LOOP; + + writel(spicr, ®s->spicr); + priv->mode = mode; + + debug("xilinx_spi_set_mode: regs=%p, mode=%d\n", priv->regs, + priv->mode);
return 0; } + +static int xilinx_cs_info(struct udevice *bus, uint cs, + struct spi_cs_info *info) +{ + /* 2 bus with 3 chipselect */ + if (cs > 31) + return -ENODEV; + else + return 0; +} + +static const struct dm_spi_ops xilinx_spi_ops = { + .claim_bus = xilinx_spi_claim_bus, + .release_bus = xilinx_spi_release_bus, + .xfer = xilinx_spi_xfer, + .set_speed = xilinx_spi_set_speed, + .set_mode = xilinx_spi_set_mode, + .cs_info = xilinx_cs_info, +}; + +static const struct udevice_id xilinx_spi_ids[] = { + { .compatible = "xlnx,xilinx-spi" }, + { } +}; + +U_BOOT_DRIVER(xilinx_spi) = { + .name = "xilinx_spi", + .id = UCLASS_SPI, + .of_match = xilinx_spi_ids, + .ops = &xilinx_spi_ops, + .priv_auto_alloc_size = sizeof(struct xilinx_spi_priv), + .probe = xilinx_spi_probe, +};

Hi Jagan,
On 23 April 2015 at 08:15, Jagannadha Sutradharudu Teki jagannadh.teki@gmail.com wrote:
This converts the xilinx spi driver to use the driver model.
Signed-off-by: Jagannadha Sutradharudu Teki jagannadh.teki@gmail.com Cc: Simon Glass sjg@chromium.org Cc: Michal Simek michal.simek@xilinx.com
Note: Michal, can you test this, I don't have hardware.
drivers/spi/xilinx_spi.c | 212 +++++++++++++++++++++++++++-------------------- 1 file changed, 124 insertions(+), 88 deletions(-)
Acked-by: Simon Glass sjg@chromium.org
diff --git a/drivers/spi/xilinx_spi.c b/drivers/spi/xilinx_spi.c index 3803c4c..4acade4 100644 --- a/drivers/spi/xilinx_spi.c +++ b/drivers/spi/xilinx_spi.c @@ -4,6 +4,7 @@
- Supports 8 bit SPI transfers only, with or w/o FIFO
- Based on bfin_spi.c, by way of altera_spi.c
- Copyright (c) 2015 Jagannadha Sutradharudu Teki jagannadh.teki@gmail.com
- Copyright (c) 2012 Stephan Linz linz@li-pro.net
- Copyright (c) 2010 Graeme Smecher graeme.smecher@mail.mcgill.ca
- Copyright (c) 2010 Thomas Chou thomas@wytron.com.tw
@@ -14,6 +15,8 @@
#include <config.h> #include <common.h> +#include <dm.h> +#include <errno.h> #include <malloc.h> #include <spi.h>
@@ -79,7 +82,7 @@ #endif
/* xilinx spi register set */ -struct xilinx_spi_reg { +struct xilinx_spi_regs { u32 __space0__[7]; u32 dgier; /* Device Global Interrupt Enable Register (DGIER) */ u32 ipisr; /* IP Interrupt Status Register (IPISR) */ @@ -97,113 +100,76 @@ struct xilinx_spi_reg { u32 spirfor; /* SPI Receive FIFO Occupancy Register (SPIRFOR) */ };
-/* xilinx spi slave */ -struct xilinx_spi_slave {
struct spi_slave slave;
struct xilinx_spi_reg *regs;
+/* xilinx spi priv */ +struct xilinx_spi_priv {
struct xilinx_spi_regs *regs; unsigned int freq; unsigned int mode;
unsigned int cs;
};
-static inline struct xilinx_spi_slave *to_xilinx_spi_slave(
struct spi_slave *slave)
-{
return container_of(slave, struct xilinx_spi_slave, slave);
-}
static unsigned long xilinx_spi_base_list[] = CONFIG_SYS_XILINX_SPI_LIST; -int spi_cs_is_valid(unsigned int bus, unsigned int cs) +static int xilinx_spi_probe(struct udevice *bus) {
return bus < ARRAY_SIZE(xilinx_spi_base_list) && cs < 32;
-}
struct xilinx_spi_priv *priv = dev_get_priv(bus);
struct xilinx_spi_regs *regs = priv->regs;
-void spi_cs_activate(struct spi_slave *slave) -{
struct xilinx_spi_slave *xilspi = to_xilinx_spi_slave(slave);
priv->regs = (struct xilinx_spi_regs *)xilinx_spi_base_list[bus->seq];
priv->cs = spi_chip_select(bus);
writel(SPISSR_ACT(slave->cs), &xilspi->regs->spissr);
-}
writel(SPISSR_RESET_VALUE, ®s->srr);
-void spi_cs_deactivate(struct spi_slave *slave) -{
struct xilinx_spi_slave *xilspi = to_xilinx_spi_slave(slave);
writel(SPISSR_OFF, &xilspi->regs->spissr);
-}
-void spi_init(void) -{
/* do nothing */
return 0;
}
-struct spi_slave *spi_setup_slave(unsigned int bus, unsigned int cs,
unsigned int max_hz, unsigned int mode)
+static void spi_cs_activate(struct udevice *dev) {
struct xilinx_spi_slave *xilspi;
if (!spi_cs_is_valid(bus, cs)) {
printf("XILSPI error: unsupported bus %d / cs %d\n", bus, cs);
return NULL;
}
xilspi = spi_alloc_slave(struct xilinx_spi_slave, bus, cs);
if (!xilspi) {
printf("XILSPI error: malloc of SPI structure failed\n");
return NULL;
}
xilspi->regs = (struct xilinx_spi_reg *)xilinx_spi_base_list[bus];
xilspi->freq = max_hz;
xilspi->mode = mode;
debug("spi_setup_slave: bus:%i cs:%i base:%p mode:%x max_hz:%d\n",
bus, cs, xilspi->regs, xilspi->mode, xilspi->freq);
writel(SPISSR_RESET_VALUE, &xilspi->regs->srr);
struct udevice *bus = dev->parent;
struct xilinx_spi_priv *priv = dev_get_priv(bus);
struct xilinx_spi_regs *regs = priv->regs;
return &xilspi->slave;
writel(SPISSR_ACT(priv->cs), ®s->spissr);
}
-void spi_free_slave(struct spi_slave *slave) +static void spi_cs_deactivate(struct udevice *dev) {
struct xilinx_spi_slave *xilspi = to_xilinx_spi_slave(slave);
struct udevice *bus = dev->parent;
dev_get_parent() so we can add pointer checking later perhaps.
struct xilinx_spi_priv *priv = dev_get_priv(bus);
struct xilinx_spi_regs *regs = priv->regs;
free(xilspi);
writel(SPISSR_OFF, ®s->spissr);
}
[snip]
Regards, Simon

This patch includes asm/io.h for readl and writel calls.
build errors: drivers/spi/xilinx_spi.c: In function 'xilinx_spi_probe': drivers/spi/xilinx_spi.c:119:2: warning: implicit declaration of function 'writel' [-Wimplicit-function-declaration] drivers/spi/xilinx_spi.c: In function 'xilinx_spi_xfer': drivers/spi/xilinx_spi.c:193:2: warning: implicit declaration of function 'readl' [-Wimplicit-function-declaration]
Signed-off-by: Jagannadha Sutradharudu Teki jagannadh.teki@gmail.com Cc: Michal Simek michal.simek@xilinx.com --- drivers/spi/xilinx_spi.c | 1 + 1 file changed, 1 insertion(+)
diff --git a/drivers/spi/xilinx_spi.c b/drivers/spi/xilinx_spi.c index 4acade4..e9ff804 100644 --- a/drivers/spi/xilinx_spi.c +++ b/drivers/spi/xilinx_spi.c @@ -19,6 +19,7 @@ #include <errno.h> #include <malloc.h> #include <spi.h> +#include <asm/io.h>
/* * [0]: http://www.xilinx.com/support/documentation

Hi Siva Durga Prasad,
On 23 April 2015 at 19:45, Jagannadha Sutradharudu Teki jagannadh.teki@gmail.com wrote:
Driver model conversion, patches. - drivers/spi/zynq_spi.c and drivers/spi/xilinx_spi.c
thanks!
Jagan.
Jagannadha Sutradharudu Teki (7): dm: spi: zynq_spi: Convert to driver model zynq: Kconfig: Enable dm spi and spi_flash dts: zynq: Add zynq spi controller nodes spi: zynq_spi: Add fdt support in driver dts: zynq: Enable spi1 for zc770_xm010 board dm: spi: xilinx_spi: Convert to driver model spi: xilinx_spi: Add asm/io.h include file
Can you just test and let me know any comments from your side.
arch/arm/Kconfig | 2 + arch/arm/dts/zynq-7000.dtsi | 26 +++ arch/arm/dts/zynq-zc770-xm010.dts | 4 + arch/arm/include/asm/arch-zynq/hardware.h | 2 - doc/device-tree-bindings/spi/spi-zynq.txt | 29 +++ drivers/spi/xilinx_spi.c | 213 +++++++++++--------- drivers/spi/zynq_spi.c | 312 ++++++++++++++++++------------ 7 files changed, 372 insertions(+), 216 deletions(-) create mode 100644 doc/device-tree-bindings/spi/spi-zynq.txt
-- 1.9.1
thanks!

Hi Jagan,
I didn't get chance to look at the series. Could you give me some time till next week as I am little busy this week.
Regards, Siva
-----Original Message----- From: Jagan Teki [mailto:jagannadh.teki@gmail.com] Sent: Monday, April 27, 2015 8:32 PM To: u-boot@lists.denx.de; Siva Durga Prasad Paladugu Cc: Jagannadha Sutradharudu Teki; Michal Simek Subject: Re: [U-Boot 0/7] dm: spi: Convert few drivers to driver model
Hi Siva Durga Prasad,
On 23 April 2015 at 19:45, Jagannadha Sutradharudu Teki jagannadh.teki@gmail.com wrote:
Driver model conversion, patches. - drivers/spi/zynq_spi.c and drivers/spi/xilinx_spi.c
thanks!
Jagan.
Jagannadha Sutradharudu Teki (7): dm: spi: zynq_spi: Convert to driver model zynq: Kconfig: Enable dm spi and spi_flash dts: zynq: Add zynq spi controller nodes spi: zynq_spi: Add fdt support in driver dts: zynq: Enable spi1 for zc770_xm010 board dm: spi: xilinx_spi: Convert to driver model spi: xilinx_spi: Add asm/io.h include file
Can you just test and let me know any comments from your side.
arch/arm/Kconfig | 2 + arch/arm/dts/zynq-7000.dtsi | 26 +++ arch/arm/dts/zynq-zc770-xm010.dts | 4 + arch/arm/include/asm/arch-zynq/hardware.h | 2 - doc/device-tree-bindings/spi/spi-zynq.txt | 29 +++ drivers/spi/xilinx_spi.c | 213 +++++++++++--------- drivers/spi/zynq_spi.c | 312 ++++++++++++++++++------------ 7 files changed, 372 insertions(+), 216 deletions(-) create mode 100644 doc/device-tree-bindings/spi/spi-zynq.txt
-- 1.9.1
thanks!
Jagan.
This email and any attachments are intended for the sole use of the named recipient(s) and contain(s) confidential information that may be proprietary, privileged or copyrighted under applicable law. If you are not the intended recipient, do not read, copy, or forward this email message or any attachments. Delete this email message and any attachments immediately.

Hi Siva,
On 28 April 2015 at 18:21, Siva Durga Prasad Paladugu siva.durga.paladugu@xilinx.com wrote:
Hi Jagan,
I didn't get chance to look at the series. Could you give me some time till next week as I am little busy this week.
No issues, If something that I send it for v2 I will let you know.
-----Original Message----- From: Jagan Teki [mailto:jagannadh.teki@gmail.com] Sent: Monday, April 27, 2015 8:32 PM To: u-boot@lists.denx.de; Siva Durga Prasad Paladugu Cc: Jagannadha Sutradharudu Teki; Michal Simek Subject: Re: [U-Boot 0/7] dm: spi: Convert few drivers to driver model
Hi Siva Durga Prasad,
On 23 April 2015 at 19:45, Jagannadha Sutradharudu Teki jagannadh.teki@gmail.com wrote:
Driver model conversion, patches. - drivers/spi/zynq_spi.c and drivers/spi/xilinx_spi.c
thanks!
Jagan.
Jagannadha Sutradharudu Teki (7): dm: spi: zynq_spi: Convert to driver model zynq: Kconfig: Enable dm spi and spi_flash dts: zynq: Add zynq spi controller nodes spi: zynq_spi: Add fdt support in driver dts: zynq: Enable spi1 for zc770_xm010 board dm: spi: xilinx_spi: Convert to driver model spi: xilinx_spi: Add asm/io.h include file
Can you just test and let me know any comments from your side.
arch/arm/Kconfig | 2 + arch/arm/dts/zynq-7000.dtsi | 26 +++ arch/arm/dts/zynq-zc770-xm010.dts | 4 + arch/arm/include/asm/arch-zynq/hardware.h | 2 - doc/device-tree-bindings/spi/spi-zynq.txt | 29 +++ drivers/spi/xilinx_spi.c | 213 +++++++++++--------- drivers/spi/zynq_spi.c | 312 ++++++++++++++++++------------ 7 files changed, 372 insertions(+), 216 deletions(-) create mode 100644 doc/device-tree-bindings/spi/spi-zynq.txt
-- 1.9.1
thanks!
participants (4)
-
Jagan Teki
-
Jagannadha Sutradharudu Teki
-
Simon Glass
-
Siva Durga Prasad Paladugu