Skip to contentSkip to conversation

spi/arm-pl022: Add support for ARM PL022 spi controller

PATCH Superseded Armando Visconti 2 participants 7 messages Jun 7, 2013 – Jun 12, 2013 SPI

v4 of 6 Superseded Latest is v6 →

lore
Share & tools
lore
#0 lore raw

PATCH v4 1/1 spi/arm-pl022: Add support for ARM PL022 spi controller

This patch adds the support for the ARM PL022 SPI controller for the standard variant (0x00041022), which has a 16bit wide and 8 locations deep TX/RX FIFO.

---
v3->v4
Just removed all warnings when running checkpatch. Didn't find Jagan's feedback... So, pls, let me know if we need to change anything else...

Armando

 drivers/spi/Makefile    |   1 +
 drivers/spi/pl022_spi.c | 310 ++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 311 insertions(+)
 create mode 100644 drivers/spi/pl022_spi.c
drivers/spi/Makefile +1 -0
index d08609e..b6443b1 100644
@@ -47,6 +47,7 @@ COBJS-$(CONFIG_MXC_SPI) += mxc_spi.o
 COBJS-$(CONFIG_MXS_SPI) += mxs_spi.o
 COBJS-$(CONFIG_OC_TINY_SPI) += oc_tiny_spi.o
 COBJS-$(CONFIG_OMAP3_SPI) += omap3_spi.o
+COBJS-$(CONFIG_PL022_SPI) += pl022_spi.o
 COBJS-$(CONFIG_SOFT_SPI) += soft_spi.o
 COBJS-$(CONFIG_SH_SPI) += sh_spi.o
 COBJS-$(CONFIG_FSL_ESPI) += fsl_espi.o
drivers/spi/pl022_spi.c new file +310 -0

310 lines not on this page · raw message

Signature · 1 line
1.7.11.7
#1 lore raw

PATCH v4 1/1 spi/arm-pl022: Add support for ARM PL022 spi controller

Hi,

Please use the commit header as below: just to sync with remaining drivers in tree.

spi: arm-pl022: Add support for ARM PL022 spi controller

Quoted 114 lines · Armando Visconti

This patch adds the support for the ARM PL022 SPI controller for the standard variant (0x00041022), which has a 16bit wide and 8 locations deep TX/RX FIFO.

---
v3->v4
Just removed all warnings when running checkpatch. Didn't find Jagan's feedback... So, pls, let me know if we need to change anything else...

Armando

 drivers/spi/Makefile    |   1 +
 drivers/spi/pl022_spi.c | 310 ++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 311 insertions(+)
 create mode 100644 drivers/spi/pl022_spi.c
drivers/spi/Makefile +1 -0
index d08609e..b6443b1 100644
@@ -47,6 +47,7 @@ COBJS-$(CONFIG_MXC_SPI) += mxc_spi.o
 COBJS-$(CONFIG_MXS_SPI) += mxs_spi.o
 COBJS-$(CONFIG_OC_TINY_SPI) += oc_tiny_spi.o
 COBJS-$(CONFIG_OMAP3_SPI) += omap3_spi.o
+COBJS-$(CONFIG_PL022_SPI) += pl022_spi.o
 COBJS-$(CONFIG_SOFT_SPI) += soft_spi.o
 COBJS-$(CONFIG_SH_SPI) += sh_spi.o
 COBJS-$(CONFIG_FSL_ESPI) += fsl_espi.o
drivers/spi/pl022_spi.c new file +77 -0
new file mode 100644
index 0000000..8a8b9ab
@@ -0,0 +1,310 @@
+/*
+ * (C) Copyright 2012
+ * Armando Visconti, ST Microelectronics, armando.visconti at st.com.
+ *
+ * Driver for ARM PL022 SPI Controller. Based on atmel_spi.c
+ * by Atmel Corporation.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include <common.h>
+#include <malloc.h>
+#include <spi.h>
+#include <asm/io.h>
+#include <asm/arch/hardware.h>
+
+/* SSP registers mapping */
+struct pl022 {
+       u32     ssp_cr0;        /* 0x000 */
+       u32     ssp_cr1;        /* 0x004 */
+       u32     ssp_dr;         /* 0x008 */
+       u32     ssp_sr;         /* 0x00c */
+       u32     ssp_cpsr;       /* 0x010 */
+       u32     ssp_imsc;       /* 0x014 */
+       u32     ssp_ris;        /* 0x018 */
+       u32     ssp_mis;        /* 0x01c */
+       u32     ssp_icr;        /* 0x020 */
+       u32     ssp_dmacr;      /* 0x024 */
+       u8      reserved_1[0x080 - 0x028];
+       u32     ssp_itcr;       /* 0x080 */
+       u32     ssp_itip;       /* 0x084 */
+       u32     ssp_itop;       /* 0x088 */
+       u32     ssp_tdr;        /* 0x08c */
+       u8      reserved_2[0xFE0 - 0x090];
+       u32     ssp_pid0;       /* 0xfe0 */
+       u32     ssp_pid1;       /* 0xfe4 */
+       u32     ssp_pid2;       /* 0xfe8 */
+       u32     ssp_pid3;       /* 0xfec */
+       u32     ssp_cid0;       /* 0xff0 */
+       u32     ssp_cid1;       /* 0xff4 */
+       u32     ssp_cid2;       /* 0xff8 */
+       u32     ssp_cid3;       /* 0xffc */
+};
+
+/* SSP Control Register 0  - SSP_CR0 */
+#define SSP_CR0_SPO            (0x1 << 6)
+#define SSP_CR0_SPH            (0x1 << 7)
+#define SSP_CR0_8BIT_MODE      (0x07)
+#define SSP_SCR_MAX            (0xFF)
+#define SSP_SCR_SHFT           8
+
+/* SSP Control Register 0  - SSP_CR1 */
+#define SSP_CR1_MASK_SSE       (0x1 << 1)
+
+#define SSP_CPSR_MAX           (0xFE)
+
+/* SSP Status Register - SSP_SR */
+#define SSP_SR_MASK_TFE                (0x1 << 0) /* Transmit FIFO empty */
+#define SSP_SR_MASK_TNF                (0x1 << 1) /* Transmit FIFO not full */
+#define SSP_SR_MASK_RNE                (0x1 << 2) /* Receive FIFO not empty */
+#define SSP_SR_MASK_RFF                (0x1 << 3) /* Receive FIFO full */
+#define SSP_SR_MASK_BSY                (0x1 << 4) /* Busy Flag */
+
+struct pl022_spi_slave {

drivers/spi/pl022_spi.c line 87

Quoted 10 lines
drivers/spi/pl022_spi.c new file +10 -0
+       struct spi_slave slave;
+       void *regs;
+       unsigned int freq;
+};
+
+static inline struct pl022_spi_slave *to_pl022_spi(struct spi_slave *slave)
+{
+       return container_of(slave, struct pl022_spi_slave, slave);
+}
+

------ TAG+

Quoted 13 lines
drivers/spi/pl022_spi.c new file +13 -0
+/*
+ * Following three functions should be provided by the
+ * board support package.
+ */
+int __weak spi_cs_is_valid(unsigned int bus, unsigned int cs)
+{
+       return 1;
+}
+
+void __weak spi_cs_activate(struct spi_slave *slave)
+{
+       /* do nothing */
+}

drivers/spi/pl022_spi.c line 110

Quoted 10 lines
drivers/spi/pl022_spi.c new file +10 -0
+
+void __weak spi_cs_deactivate(struct spi_slave *slave)
+{
+       /* do nothing */
+}
+
+void spi_init(void)
+{
+       /* do nothing */
+}

-------------------- TAG-

Any specific reason for defining theese on to board? Would it be possible to do the same here, as these are spi specific.

I am trying to collaborate the spi code to generic, so-that it has some identity as other
driver did.

Quoted 5 lines
drivers/spi/pl022_spi.c new file +5 -0
+
+/*
+ * ARM PL022 exists in different 'flavors'.
+ * This drivers currently support the standard variant (0x00041022), that has a
+ * 16bit wide and 8 locations deep TX/RX FIFO.

drivers/spi/pl022_spi.c line 125

Quoted 10 lines
drivers/spi/pl022_spi.c new file +10 -0
+ */
+static int pl022_is_supported(struct pl022_spi_slave *ps)
+{
+       struct pl022 *pl022 = (struct pl022 *)ps->regs;
+
+       /* PL022 version is 0x00041022 */
+       if ((readl(&pl022->ssp_pid0) == 0x22) &&
+           (readl(&pl022->ssp_pid1) == 0x10) &&
+           ((readl(&pl022->ssp_pid2) & 0xf) == 0x04) &&
+           (readl(&pl022->ssp_pid3) == 0x00))

Tab space is required, for this if statement i guess, please check.

Quoted 5 lines
drivers/spi/pl022_spi.c new file +5 -0
+                       return 1;
+
+       return 0;
+}
+

drivers/spi/pl022_spi.c line 140

Quoted 10 lines
drivers/spi/pl022_spi.c new file +10 -0
+struct spi_slave *spi_setup_slave(unsigned int bus, unsigned int cs,
+                       unsigned int max_hz, unsigned int mode)
+{
+       struct pl022_spi_slave *ps;
+       struct pl022 *pl022;
+       u16 scr = 1, prescaler, cr0 = 0, cpsr = 0;
+
+       if (!spi_cs_is_valid(bus, cs))
+               return NULL;
+

----- TAG+

drivers/spi/pl022_spi.c line 146

Quoted 6 lines
drivers/spi/pl022_spi.c new file +6 -0
+       ps = malloc(sizeof(*ps));
+       if (!ps)
+               return NULL;
+
+       ps->slave.bus = bus;
+       ps->slave.cs = cs;

----- TAG-

Code from TAG+ to TAG-, please use spi_alloc_slave() refer any ddriver in rivers/spi/*

--
Thanks,
Jagan.

Quoted 166 lines
drivers/spi/pl022_spi.c new file +164 -1
+       ps->freq = max_hz;
+
+       switch (bus) {
+       case 0:
+               ps->regs = (void *)CONFIG_SYS_SPI_BASE;
+               break;
+#ifdef CONFIG_SYS_SPI_BASE1
+       case 1:
+               ps->regs = (void *)CONFIG_SYS_SPI_BASE1;
+               break;
+#endif
+#ifdef CONFIG_SYS_SPI_BASE2
+       case 2:
+               ps->regs = (void *)CONFIG_SYS_SPI_BASE2;
+               break;
+#endif
+#ifdef CONFIG_SYS_SPI_BASE3
+       case 3:
+               ps->regs = (void *)CONFIG_SYS_SPI_BASE3;
+               break;
+#endif
+       default:
+               free(ps);
+               return NULL;
+       }
+
+       pl022 = (struct pl022 *)ps->regs;
+
+       /* Check the PL022 version */
+       if (!pl022_is_supported(ps)) {
+               free(ps);
+               return NULL;
+       }
+
+       /* Set requested polarity and 8bit mode */
+       cr0 = SSP_CR0_8BIT_MODE;
+       cr0 |= (mode & SPI_CPHA) ? SSP_CR0_SPH : 0;
+       cr0 |= (mode & SPI_CPOL) ? SSP_CR0_SPO : 0;
+
+       writel(cr0, &pl022->ssp_cr0);
+
+       /* Program the SSPClk frequency */
+       prescaler = CONFIG_SYS_SPI_CLK / ps->freq;
+
+       if (prescaler <= 0xFF) {
+               cpsr = prescaler;
+       } else {
+               for (scr = 1; scr <= SSP_SCR_MAX; scr++) {
+                       if (!(prescaler % scr)) {
+                               cpsr = prescaler / scr;
+                               if (cpsr <= SSP_CPSR_MAX)
+                                       break;
+                       }
+               }
+
+               if (scr > SSP_SCR_MAX) {
+                       scr = SSP_SCR_MAX;
+                       cpsr = prescaler / scr;
+                       cpsr &= SSP_CPSR_MAX;
+               }
+       }
+
+       if (cpsr & 0x1)
+               cpsr++;
+
+       writel(cpsr, &pl022->ssp_cpsr);
+       cr0 = readl(&pl022->ssp_cr0);
+       writel(cr0 | (scr - 1) << SSP_SCR_SHFT, &pl022->ssp_cr0);
+
+       return &ps->slave;
+}
+
+void spi_free_slave(struct spi_slave *slave)
+{
+       struct pl022_spi_slave *ps = to_pl022_spi(slave);
+
+       free(ps);
+}
+
+int spi_claim_bus(struct spi_slave *slave)
+{
+       struct pl022_spi_slave *ps = to_pl022_spi(slave);
+       struct pl022 *pl022 = (struct pl022 *)ps->regs;
+
+       /* Enable the SPI hardware */
+       setbits_le32(&pl022->ssp_cr1, SSP_CR1_MASK_SSE);
+
+       return 0;
+}
+
+void spi_release_bus(struct spi_slave *slave)
+{
+       struct pl022_spi_slave *ps = to_pl022_spi(slave);
+       struct pl022 *pl022 = (struct pl022 *)ps->regs;
+
+       /* Disable the SPI hardware */
+       writel(0x0, &pl022->ssp_cr1);
+}
+
+int spi_xfer(struct spi_slave *slave, unsigned int bitlen,
+               const void *dout, void *din, unsigned long flags)
+{
+       struct pl022_spi_slave *ps = to_pl022_spi(slave);
+       struct pl022 *pl022 = (struct pl022 *)ps->regs;
+       u32             len_tx = 0, len_rx = 0, len;
+       u32             ret = 0;
+       const u8        *txp = dout;
+       u8              *rxp = din, value;
+
+       if (bitlen == 0)
+               /* Finish any previously submitted transfers */
+               goto out;
+
+       /*
+        * TODO: The controller can do non-multiple-of-8 bit
+        * transfers, but this driver currently doesn't support it.
+        *
+        * It's also not clear how such transfers are supposed to be
+        * represented as a stream of bytes...this is a limitation of
+        * the current SPI interface.
+        */
+       if (bitlen % 8) {
+               ret = -1;
+
+               /* Errors always terminate an ongoing transfer */
+               flags |= SPI_XFER_END;
+               goto out;
+       }
+
+       len = bitlen / 8;
+
+       if (flags & SPI_XFER_BEGIN)
+               spi_cs_activate(slave);
+
+       while (len_tx < len) {
+               if (readl(&pl022->ssp_sr) & SSP_SR_MASK_TNF) {
+                       value = (txp != NULL) ? *txp++ : 0;
+                       writel(value, &pl022->ssp_dr);
+                       len_tx++;
+               }
+
+               if (readl(&pl022->ssp_sr) & SSP_SR_MASK_RNE) {
+                       value = readl(&pl022->ssp_dr);
+                       if (rxp)
+                               *rxp++ = value;
+                       len_rx++;
+               }
+       }
+
+       while (len_rx < len_tx) {
+               if (readl(&pl022->ssp_sr) & SSP_SR_MASK_RNE) {
+                       value = readl(&pl022->ssp_dr);
+                       if (rxp)
+                               *rxp++ = value;
+                       len_rx++;
+               }
+       }
+
+out:
+       if (flags & SPI_XFER_END)
+               spi_cs_deactivate(slave);
+
+       return ret;
+}
--

1.7.11.7

#2 lore raw

PATCH v4 1/1 spi/arm-pl022: Add support for ARM PL022 spi controller

Quoted 7 lines · Jagan Teki

Hi,

Please use the commit header as below: just to sync with remaining drivers in tree.

spi: arm-pl022: Add support for ARM PL022 spi controller

OK,
I already did it for v5.
I'll keep it for v6 as well...

Quoted 152 lines
Quoted 114 lines · Armando Visconti

This patch adds the support for the ARM PL022 SPI controller for the standard variant (0x00041022), which has a 16bit wide and 8 locations deep TX/RX FIFO.

---
v3->v4
Just removed all warnings when running checkpatch. Didn't find Jagan's feedback... So, pls, let me know if we need to change anything else...

Armando

  drivers/spi/Makefile    |   1 +
  drivers/spi/pl022_spi.c | 310 ++++++++++++++++++++++++++++++++++++++++++++++++
  2 files changed, 311 insertions(+)

create mode 100644 drivers/spi/pl022_spi.c

drivers/spi/Makefile +1 -0
index d08609e..b6443b1 100644
@@ -47,6 +47,7 @@ COBJS-$(CONFIG_MXC_SPI) += mxc_spi.o
  COBJS-$(CONFIG_MXS_SPI) += mxs_spi.o
  COBJS-$(CONFIG_OC_TINY_SPI) += oc_tiny_spi.o
  COBJS-$(CONFIG_OMAP3_SPI) += omap3_spi.o
+COBJS-$(CONFIG_PL022_SPI) += pl022_spi.o
  COBJS-$(CONFIG_SOFT_SPI) += soft_spi.o
  COBJS-$(CONFIG_SH_SPI) += sh_spi.o
  COBJS-$(CONFIG_FSL_ESPI) += fsl_espi.o
drivers/spi/pl022_spi.c new file +77 -0
new file mode 100644
index 0000000..8a8b9ab
@@ -0,0 +1,310 @@
+/*
+ * (C) Copyright 2012
+ * Armando Visconti, ST Microelectronics, armando.visconti at st.com.
+ *
+ * Driver for ARM PL022 SPI Controller. Based on atmel_spi.c
+ * by Atmel Corporation.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include <common.h>
+#include <malloc.h>
+#include <spi.h>
+#include <asm/io.h>
+#include <asm/arch/hardware.h>
+
+/* SSP registers mapping */
+struct pl022 {
+       u32     ssp_cr0;        /* 0x000 */
+       u32     ssp_cr1;        /* 0x004 */
+       u32     ssp_dr;         /* 0x008 */
+       u32     ssp_sr;         /* 0x00c */
+       u32     ssp_cpsr;       /* 0x010 */
+       u32     ssp_imsc;       /* 0x014 */
+       u32     ssp_ris;        /* 0x018 */
+       u32     ssp_mis;        /* 0x01c */
+       u32     ssp_icr;        /* 0x020 */
+       u32     ssp_dmacr;      /* 0x024 */
+       u8      reserved_1[0x080 - 0x028];
+       u32     ssp_itcr;       /* 0x080 */
+       u32     ssp_itip;       /* 0x084 */
+       u32     ssp_itop;       /* 0x088 */
+       u32     ssp_tdr;        /* 0x08c */
+       u8      reserved_2[0xFE0 - 0x090];
+       u32     ssp_pid0;       /* 0xfe0 */
+       u32     ssp_pid1;       /* 0xfe4 */
+       u32     ssp_pid2;       /* 0xfe8 */
+       u32     ssp_pid3;       /* 0xfec */
+       u32     ssp_cid0;       /* 0xff0 */
+       u32     ssp_cid1;       /* 0xff4 */
+       u32     ssp_cid2;       /* 0xff8 */
+       u32     ssp_cid3;       /* 0xffc */
+};
+
+/* SSP Control Register 0  - SSP_CR0 */
+#define SSP_CR0_SPO            (0x1 << 6)
+#define SSP_CR0_SPH            (0x1 << 7)
+#define SSP_CR0_8BIT_MODE      (0x07)
+#define SSP_SCR_MAX            (0xFF)
+#define SSP_SCR_SHFT           8
+
+/* SSP Control Register 0  - SSP_CR1 */
+#define SSP_CR1_MASK_SSE       (0x1 << 1)
+
+#define SSP_CPSR_MAX           (0xFE)
+
+/* SSP Status Register - SSP_SR */
+#define SSP_SR_MASK_TFE                (0x1 << 0) /* Transmit FIFO empty */
+#define SSP_SR_MASK_TNF                (0x1 << 1) /* Transmit FIFO not full */
+#define SSP_SR_MASK_RNE                (0x1 << 2) /* Receive FIFO not empty */
+#define SSP_SR_MASK_RFF                (0x1 << 3) /* Receive FIFO full */
+#define SSP_SR_MASK_BSY                (0x1 << 4) /* Busy Flag */
+
+struct pl022_spi_slave {

drivers/spi/pl022_spi.c line 87

Quoted 10 lines
drivers/spi/pl022_spi.c new file +10 -0
+       struct spi_slave slave;
+       void *regs;
+       unsigned int freq;
+};
+
+static inline struct pl022_spi_slave *to_pl022_spi(struct spi_slave *slave)
+{
+       return container_of(slave, struct pl022_spi_slave, slave);
+}
+

------ TAG+

Quoted 13 lines
drivers/spi/pl022_spi.c new file +13 -0
+/*
+ * Following three functions should be provided by the
+ * board support package.
+ */
+int __weak spi_cs_is_valid(unsigned int bus, unsigned int cs)
+{
+       return 1;
+}
+
+void __weak spi_cs_activate(struct spi_slave *slave)
+{
+       /* do nothing */
+}

drivers/spi/pl022_spi.c line 110

Quoted 10 lines
drivers/spi/pl022_spi.c new file +10 -0
+
+void __weak spi_cs_deactivate(struct spi_slave *slave)
+{
+       /* do nothing */
+}
+
+void spi_init(void)
+{
+       /* do nothing */
+}

-------------------- TAG-

Quoted 6 lines

Any specific reason for defining theese on to board? Would it be possible to do the same here, as these are spi specific.

I am trying to collaborate the spi code to generic, so-that it has some identity as other
driver did.

The pl022 SPI controller, differently from other SPI controller, does not provide a chip select pin.
Therefore the CS must handled in a soc-specific way.
What the driver has to do is to provide dummy functions that MUST be overwritten by soc specific ones.

If you see the pl022 linux driver does the same.

Quoted 10 lines
Quoted 10 lines
drivers/spi/pl022_spi.c new file +9 -0
+
+/*
+ * ARM PL022 exists in different 'flavors'.
+ * This drivers currently support the standard variant (0x00041022), that has a
+ * 16bit wide and 8 locations deep TX/RX FIFO.
+ */
+static int pl022_is_supported(struct pl022_spi_slave *ps)
+{
+       struct pl022 *pl022 = (struct pl022 *)ps->regs;
Quoted 9 lines

drivers/spi/pl022_spi.c line 125

Quoted 6 lines
drivers/spi/pl022_spi.c new file +6 -0
+
+       /* PL022 version is 0x00041022 */
+       if ((readl(&pl022->ssp_pid0) == 0x22) &&
+           (readl(&pl022->ssp_pid1) == 0x10) &&
+           ((readl(&pl022->ssp_pid2) & 0xf) == 0x04) &&
+           (readl(&pl022->ssp_pid3) == 0x00))

Tab space is required, for this if statement i guess, please check.

If I do then checkpatch reports a warning, saying that I need to keep all lines of a 'if' statement aligned properly...

So, I guess that this way is more proper.

Quoted 23 lines
Quoted 5 lines
drivers/spi/pl022_spi.c new file +5 -0
+                       return 1;
+
+       return 0;
+}
+

drivers/spi/pl022_spi.c line 140

Quoted 10 lines
drivers/spi/pl022_spi.c new file +10 -0
+struct spi_slave *spi_setup_slave(unsigned int bus, unsigned int cs,
+                       unsigned int max_hz, unsigned int mode)
+{
+       struct pl022_spi_slave *ps;
+       struct pl022 *pl022;
+       u16 scr = 1, prescaler, cr0 = 0, cpsr = 0;
+
+       if (!spi_cs_is_valid(bus, cs))
+               return NULL;
+

----- TAG+

drivers/spi/pl022_spi.c line 146

Quoted 6 lines
drivers/spi/pl022_spi.c new file +6 -0
+       ps = malloc(sizeof(*ps));
+       if (!ps)
+               return NULL;
+
+       ps->slave.bus = bus;
+       ps->slave.cs = cs;
Quoted 5 lines

----- TAG-

Code from TAG+ to TAG-, please use spi_alloc_slave() refer any ddriver in rivers/spi/*

ok, I'll do it!

Pls let me know if we are now fine...

Thx,
Arm

#3 lore raw

PATCH v4 1/1 spi/arm-pl022: Add support for ARM PL022 spi controller

Quoted 219 lines · Armando Visconti
Quoted 8 lines · Jagan Teki

Hi,

Please use the commit header as below: just to sync with remaining drivers in tree.

spi: arm-pl022: Add support for ARM PL022 spi controller

OK,
I already did it for v5.
I'll keep it for v6 as well...

Quoted 164 lines
Quoted 129 lines · Armando Visconti

This patch adds the support for the ARM PL022 SPI controller for the standard
variant (0x00041022), which has a 16bit wide and 8 locations deep TX/RX FIFO.

---
v3->v4
Just removed all warnings when running checkpatch. Didn't find Jagan's feedback... So, pls, let me know if we need to change anything else...

Armando

  drivers/spi/Makefile    |   1 +
  drivers/spi/pl022_spi.c | 310
++++++++++++++++++++++++++++++++++++++++++++++++
  2 files changed, 311 insertions(+)

create mode 100644 drivers/spi/pl022_spi.c

drivers/spi/Makefile +1 -0
index d08609e..b6443b1 100644
@@ -47,6 +47,7 @@ COBJS-$(CONFIG_MXC_SPI) += mxc_spi.o
  COBJS-$(CONFIG_MXS_SPI) += mxs_spi.o
  COBJS-$(CONFIG_OC_TINY_SPI) += oc_tiny_spi.o
  COBJS-$(CONFIG_OMAP3_SPI) += omap3_spi.o
+COBJS-$(CONFIG_PL022_SPI) += pl022_spi.o
  COBJS-$(CONFIG_SOFT_SPI) += soft_spi.o
  COBJS-$(CONFIG_SH_SPI) += sh_spi.o
  COBJS-$(CONFIG_FSL_ESPI) += fsl_espi.o
drivers/spi/pl022_spi.c new file +71 -0
new file mode 100644
index 0000000..8a8b9ab
@@ -0,0 +1,310 @@
+/*
+ * (C) Copyright 2012
+ * Armando Visconti, ST Microelectronics, armando.visconti at st.com.
+ *
+ * Driver for ARM PL022 SPI Controller. Based on atmel_spi.c
+ * by Atmel Corporation.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include <common.h>
+#include <malloc.h>
+#include <spi.h>
+#include <asm/io.h>
+#include <asm/arch/hardware.h>
+
+/* SSP registers mapping */
+struct pl022 {
+       u32     ssp_cr0;        /* 0x000 */
+       u32     ssp_cr1;        /* 0x004 */
+       u32     ssp_dr;         /* 0x008 */
+       u32     ssp_sr;         /* 0x00c */
+       u32     ssp_cpsr;       /* 0x010 */
+       u32     ssp_imsc;       /* 0x014 */
+       u32     ssp_ris;        /* 0x018 */
+       u32     ssp_mis;        /* 0x01c */
+       u32     ssp_icr;        /* 0x020 */
+       u32     ssp_dmacr;      /* 0x024 */
+       u8      reserved_1[0x080 - 0x028];
+       u32     ssp_itcr;       /* 0x080 */
+       u32     ssp_itip;       /* 0x084 */
+       u32     ssp_itop;       /* 0x088 */
+       u32     ssp_tdr;        /* 0x08c */
+       u8      reserved_2[0xFE0 - 0x090];
+       u32     ssp_pid0;       /* 0xfe0 */
+       u32     ssp_pid1;       /* 0xfe4 */
+       u32     ssp_pid2;       /* 0xfe8 */
+       u32     ssp_pid3;       /* 0xfec */
+       u32     ssp_cid0;       /* 0xff0 */
+       u32     ssp_cid1;       /* 0xff4 */
+       u32     ssp_cid2;       /* 0xff8 */
+       u32     ssp_cid3;       /* 0xffc */
+};
+
+/* SSP Control Register 0  - SSP_CR0 */
+#define SSP_CR0_SPO            (0x1 << 6)
+#define SSP_CR0_SPH            (0x1 << 7)
+#define SSP_CR0_8BIT_MODE      (0x07)
+#define SSP_SCR_MAX            (0xFF)
+#define SSP_SCR_SHFT           8
+
+/* SSP Control Register 0  - SSP_CR1 */
+#define SSP_CR1_MASK_SSE       (0x1 << 1)
+
+#define SSP_CPSR_MAX           (0xFE)
+
+/* SSP Status Register - SSP_SR */
+#define SSP_SR_MASK_TFE                (0x1 << 0) /* Transmit FIFO empty

*/
+#define SSP_SR_MASK_TNF (0x1 << 1) /* Transmit FIFO not
full */
+#define SSP_SR_MASK_RNE (0x1 << 2) /* Receive FIFO not
empty */
+#define SSP_SR_MASK_RFF (0x1 << 3) /* Receive FIFO full
*/

drivers/spi/pl022_spi.c new file +9 -0
+#define SSP_SR_MASK_BSY                (0x1 << 4) /* Busy Flag */
+
+struct pl022_spi_slave {
+       struct spi_slave slave;
+       void *regs;
+       unsigned int freq;
+};
+
+static inline struct pl022_spi_slave *to_pl022_spi(struct spi_slave

*slave)

drivers/spi/pl022_spi.c line 87

Quoted 4 lines
drivers/spi/pl022_spi.c new file +4 -0
+{
+       return container_of(slave, struct pl022_spi_slave, slave);
+}
+

------ TAG+

Quoted 14 lines
drivers/spi/pl022_spi.c new file +13 -0
+/*
+ * Following three functions should be provided by the
+ * board support package.
+ */
+int __weak spi_cs_is_valid(unsigned int bus, unsigned int cs)
+{
+       return 1;
+}
+
+void __weak spi_cs_activate(struct spi_slave *slave)
+{
+       /* do nothing */
+}

drivers/spi/pl022_spi.c line 110

Quoted 10 lines
drivers/spi/pl022_spi.c new file +10 -0
+
+void __weak spi_cs_deactivate(struct spi_slave *slave)
+{
+       /* do nothing */
+}
+
+void spi_init(void)
+{
+       /* do nothing */
+}

-------------------- TAG-

Quoted 6 lines

Any specific reason for defining theese on to board? Would it be possible to do the same here, as these are spi specific.

I am trying to collaborate the spi code to generic, so-that it has some identity as other
driver did.

The pl022 SPI controller, differently from other SPI controller, does not provide a chip select pin.
Therefore the CS must handled in a soc-specific way.
What the driver has to do is to provide dummy functions that MUST be overwritten by soc specific ones.

If you see the pl022 linux driver does the same.

Quoted 12 lines
Quoted 12 lines
drivers/spi/pl022_spi.c new file +4 -0
+
+/*
+ * ARM PL022 exists in different 'flavors'.
+ * This drivers currently support the standard variant (0x00041022),

that has a
+ * 16bit wide and 8 locations deep TX/RX FIFO.
+ */

drivers/spi/pl022_spi.c new file +4 -0
+static int pl022_is_supported(struct pl022_spi_slave *ps)
+{
+       struct pl022 *pl022 = (struct pl022 *)ps->regs;
+
Quoted 9 lines

drivers/spi/pl022_spi.c line 125

Quoted 5 lines
drivers/spi/pl022_spi.c new file +5 -0
+       /* PL022 version is 0x00041022 */
+       if ((readl(&pl022->ssp_pid0) == 0x22) &&
+           (readl(&pl022->ssp_pid1) == 0x10) &&
+           ((readl(&pl022->ssp_pid2) & 0xf) == 0x04) &&
+           (readl(&pl022->ssp_pid3) == 0x00))

Tab space is required, for this if statement i guess, please check.

Quoted 4 lines

If I do then checkpatch reports a warning, saying that I need to keep all lines of a 'if' statement aligned properly...

So, I guess that this way is more proper.

Agree, but it should be easy to interpret where should the if block end and where should the code block starts.
I always use tab space like

+static int pl022_is_supported(struct pl022_spi_slave *ps) +{
+ struct pl022 *pl022 = (struct pl022 *)ps->regs;
+
+ /* PL022 version is 0x00041022 */
+ if ((readl(&pl022->ssp_pid0) == 0x22) &&

+                       (readl(&pl022->ssp_pid1) == 0x10) &&
+                       ((readl(&pl022->ssp_pid2) & 0xf) == 0x04) &&
+                       (readl(&pl022->ssp_pid3) == 0x00))

+ return 1;
+
+ return 0;
+}

If you see return 1 is code block, so prior to this if ends.

--
Thanks,
Jagan.

Quoted 43 lines
Quoted 29 lines
Quoted 8 lines
drivers/spi/pl022_spi.c new file +5 -0
+                       return 1;
+
+       return 0;
+}
+

drivers/spi/pl022_spi.c line 140

Quoted 10 lines
drivers/spi/pl022_spi.c new file +10 -0
+struct spi_slave *spi_setup_slave(unsigned int bus, unsigned int cs,
+                       unsigned int max_hz, unsigned int mode)
+{
+       struct pl022_spi_slave *ps;
+       struct pl022 *pl022;
+       u16 scr = 1, prescaler, cr0 = 0, cpsr = 0;
+
+       if (!spi_cs_is_valid(bus, cs))
+               return NULL;
+

----- TAG+

drivers/spi/pl022_spi.c line 146

Quoted 7 lines
drivers/spi/pl022_spi.c new file +6 -0
+       ps = malloc(sizeof(*ps));
+       if (!ps)
+               return NULL;
+
+       ps->slave.bus = bus;
+       ps->slave.cs = cs;
Quoted 5 lines

----- TAG-

Code from TAG+ to TAG-, please use spi_alloc_slave() refer any ddriver in rivers/spi/*

ok, I'll do it!

Pls let me know if we are now fine...

Thx,
Arm

#4 lore raw

PATCH v4 1/1 spi/arm-pl022: Add support for ARM PL022 spi controller

Hello Jagan,

Quoted 46 lines
Quoted 22 lines
Quoted 12 lines
Quoted 12 lines
drivers/spi/pl022_spi.c new file +4 -0
+
+/*
+ * ARM PL022 exists in different 'flavors'.
+ * This drivers currently support the standard variant (0x00041022),

that has a
+ * 16bit wide and 8 locations deep TX/RX FIFO.
+ */

drivers/spi/pl022_spi.c new file +4 -0
+static int pl022_is_supported(struct pl022_spi_slave *ps)
+{
+       struct pl022 *pl022 = (struct pl022 *)ps->regs;
+
Quoted 9 lines

drivers/spi/pl022_spi.c line 125

Quoted 5 lines
drivers/spi/pl022_spi.c new file +5 -0
+       /* PL022 version is 0x00041022 */
+       if ((readl(&pl022->ssp_pid0) == 0x22) &&
+           (readl(&pl022->ssp_pid1) == 0x10) &&
+           ((readl(&pl022->ssp_pid2) & 0xf) == 0x04) &&
+           (readl(&pl022->ssp_pid3) == 0x00))

Tab space is required, for this if statement i guess, please check.

Quoted 4 lines

If I do then checkpatch reports a warning, saying that I need to keep all lines of a 'if' statement aligned properly...

So, I guess that this way is more proper.

Agree, but it should be easy to interpret where should the if block end and where should the code block starts.
I always use tab space like

drivers/spi/pl022_spi.c new file +13 -0
+static int pl022_is_supported(struct pl022_spi_slave *ps)
+{
+       struct pl022 *pl022 = (struct pl022 *)ps->regs;
+
+       /* PL022 version is 0x00041022 */
+       if ((readl(&pl022->ssp_pid0) == 0x22) &&
+                       (readl(&pl022->ssp_pid1) == 0x10) &&
+                       ((readl(&pl022->ssp_pid2) & 0xf) == 0x04) &&
+                       (readl(&pl022->ssp_pid3) == 0x00))
+               return 1;
+
+       return 0;
+}
Quoted 2 lines

If you see return 1 is code block, so prior to this if ends.

OK, I'll do it in this way even if it may generate warnings. Give me few mins and I'll send a v6 patch!

Thx,
Arm

Signature · 8 lines
-- "Every step appears to be the unavoidable consequence of the
-- preceding one." (A. Einstein)
-- 
Armando Visconti                  Mobile: (+39) 346 8879146
Senior SW Engineer                Fax:    (+39) 02 93519290
CPG                               Work:   (+39) 02 93519683
Computer System Division          e-mail: armando.visconti at st.com
ST Microelectronics               TINA:   051  4683
#5 lore raw

PATCH v4 1/1 spi/arm-pl022: Add support for ARM PL022 spi controller

Quoted 65 lines · Armando Visconti

Hello Jagan,

Quoted 48 lines
Quoted 23 lines
Quoted 13 lines
Quoted 13 lines
drivers/spi/pl022_spi.c new file +4 -0
+
+/*
+ * ARM PL022 exists in different 'flavors'.
+ * This drivers currently support the standard variant (0x00041022),

that has a
+ * 16bit wide and 8 locations deep TX/RX FIFO.
+ */

drivers/spi/pl022_spi.c new file +5 -0
+static int pl022_is_supported(struct pl022_spi_slave *ps)
+{
+       struct pl022 *pl022 = (struct pl022 *)ps->regs;
+
+       /* PL022 version is 0x00041022 */
Quoted 9 lines

drivers/spi/pl022_spi.c line 125

Quoted 4 lines
drivers/spi/pl022_spi.c new file +4 -0
+       if ((readl(&pl022->ssp_pid0) == 0x22) &&
+           (readl(&pl022->ssp_pid1) == 0x10) &&
+           ((readl(&pl022->ssp_pid2) & 0xf) == 0x04) &&
+           (readl(&pl022->ssp_pid3) == 0x00))

Tab space is required, for this if statement i guess, please check.

Quoted 4 lines

If I do then checkpatch reports a warning, saying that I need to keep all lines of a 'if' statement aligned properly...

So, I guess that this way is more proper.

Agree, but it should be easy to interpret where should the if block end and where should the code block starts.
I always use tab space like

drivers/spi/pl022_spi.c new file +13 -0
+static int pl022_is_supported(struct pl022_spi_slave *ps)
+{
+       struct pl022 *pl022 = (struct pl022 *)ps->regs;
+
+       /* PL022 version is 0x00041022 */
+       if ((readl(&pl022->ssp_pid0) == 0x22) &&
+                       (readl(&pl022->ssp_pid1) == 0x10) &&
+                       ((readl(&pl022->ssp_pid2) & 0xf) == 0x04) &&
+                       (readl(&pl022->ssp_pid3) == 0x00))
+               return 1;
+
+       return 0;
+}
Quoted 2 lines

If you see return 1 is code block, so prior to this if ends.

OK, I'll do it in this way even if it may generate warnings. Give me few mins and I'll send a v6 patch!

Thx,
Arm

--
-- "Every step appears to be the unavoidable consequence of the -- preceding one." (A. Einstein)
--

Quoted 7 lines
Armando Visconti                  Mobile: (+39) 346 8879146
Senior SW Engineer                Fax:    (+39) 02 93519290
CPG                               Work:   (+39) 02 93519683
Computer System Division          e-mail: armando.visconti at st.com
ST Microelectronics               TINA:   051  4683

Please use the commit header as "spi: pl022_spi: " as you haven't use the same on v5 i guess, please check.

--
Thanks,
Jagan.

#6 lore raw

PATCH v4 1/1 spi/arm-pl022: Add support for ARM PL022 spi controller

Quoted 4 lines

Please use the commit header as "spi: pl022_spi: " as you haven't use the same on v5 i guess, please check.

OK, Jagan,
I'll do it!

Armando