Skip to contentSkip to conversation

spi: pl022_spi: Add support for ARM PL022 spi controller

PATCH Superseded Armando Visconti 3 participants 14 messages Jun 12, 2013 – Jan 8, 2014 SPI

lore
Share & tools
lore
#0 lore raw

PATCH v6 1/1 spi: pl022_spi: 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.

---
v5->v6

1. Make use of spi_alloc_slave() macro.
2. Changed the identation on 'if statement' as requested by Jagan.

 drivers/spi/Makefile    |   1 +
 drivers/spi/pl022_spi.c | 308 ++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 309 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 +308 -0

308 lines not on this page · raw message

Signature · 1 line
1.7.11.7
#1 lore raw

PATCH v6 1/1 spi: pl022_spi: Add support for ARM PL022 spi controller

Thanks for v6 sent.

Have you tested this?
on which board, include/configs/*.h file?

--
Thanks,
Jagan.

Quoted 347 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.

---
v5->v6

1. Make use of spi_alloc_slave() macro.
2. Changed the identation on 'if statement' as requested by Jagan.

 drivers/spi/Makefile    |   1 +
 drivers/spi/pl022_spi.c | 308 ++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 309 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 +308 -1
new file mode 100644
index 0000000..5b47413
@@ -0,0 +1,308 @@
+/*
+ * (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 {
+       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);
+}
+
+/*
+ * 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 */
+}
+
+void __weak spi_cs_deactivate(struct spi_slave *slave)
+{
+       /* do nothing */
+}
+
+void spi_init(void)
+{
+       /* do nothing */
+}
+
+/*
+ * 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;
+
+       /* 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;
+}
+
+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;
+
+       ps = spi_alloc_slave(struct pl022_spi_slave, bus, cs);
+       if (!ps)
+               return NULL;
+
+       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 v6 1/1 spi: pl022_spi: Add support for ARM PL022 spi controller

Quoted 5 lines · Jagan Teki

Thanks for v6 sent.

Have you tested this?
on which board, include/configs/*.h file?

No Jagan.

I have not tested v6, as I currently don't have a spare board. Nevertheless, Vipin tested it up to v3. And he tested it on spear1340 evaluation board.

After v3, no big changes have been performed. Just style changes and make use of spi_alloc_slave()...

But if you prefer to be on safer side I think we need to re-do some checks on a spare 1340 board...

Pls let me know,
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
#3 lore raw

PATCH v6 1/1 spi: pl022_spi: Add support for ARM PL022 spi controller

Quoted 4 lines

But if you prefer to be on safer side I think we need to re-do some checks on a spare 1340 board...

OK, maybe it is better to re-check again.

I need to find some time and a spare board...

I'll let you know,
Arm

#4 lore raw

PATCH v6 1/1 spi: pl022_spi: Add support for ARM PL022 spi controller

Quoted 6 lines · Armando Visconti
Quoted 4 lines

But if you prefer to be on safer side I think we need to re-do some checks on a spare 1340 board...

Quoted 6 lines

OK, maybe it is better to re-check again.

I need to find some time and a spare board...

I'll let you know,
Arm

Do we have an config file available in master, i need to build at-least.

--
Thanks,
Jagan.

#5 lore raw

PATCH v6 1/1 spi: pl022_spi: Add support for ARM PL022 spi controller

Quoted 8 lines · Jagan Teki
Quoted 6 lines · Armando Visconti
Quoted 4 lines

But if you prefer to be on safer side I think we need to re-do some checks on a spare 1340 board...

Quoted 9 lines
Quoted 6 lines

OK, maybe it is better to re-check again.

I need to find some time and a spare board...

I'll let you know,
Arm

Do we have an config file available in master, i need to build at-least.

Mmmh... currently in mainline there is only spear3xx config file, but there is no PL022 support there.

In fact, to compile locally here I had to change it in this way, even if they cannot be used for testing (only compiling):

Quoted 6 lines
include/configs/spear3xx_evb.h +0 -0
index 3cd56dc..03a046e 100644
@@ -54,6 +54,11 @@
 /* Ethernet driver configuration */

include/configs/spear3xx_evb.h line 64

Quoted 10 lines
include/configs/spear3xx_evb.h +5 -0
 #define CONFIG_DW_ALTDESCRIPTOR
 
+#define CONFIG_PL022_SPI                1
+#define CONFIG_SYS_SPI_BASE             0xE0100000
+#define CONFIG_SYS_SPI_CLK              83000000
+#define CONFIG_CMD_SPI                  1
+
 #if defined(CONFIG_SPEAR310)
 #define CONFIG_MACB
 #define CONFIG_MACB0_PHY                       0x01

I know that Vipin was going to add support of spear1340 in mainline. His patches are currently already submitted and partially acked but I'm not sure what is the status now...

Vipin, can you update us?

Rgds,
Arm

#6 lore raw

PATCH v6 1/1 spi: pl022_spi: Add support for ARM PL022 spi controller

Any update on this.

Quoted 59 lines · Armando Visconti
Quoted 12 lines · Jagan Teki
Quoted 9 lines · Armando Visconti
Quoted 5 lines

But if you prefer to be on safer side I think we need to re-do some checks on a spare 1340 board...

OK, maybe it is better to re-check again.

Quoted 8 lines
Quoted 4 lines

I need to find some time and a spare board...

I'll let you know,
Arm

Do we have an config file available in master, i need to build at-least.

Mmmh... currently in mainline there is only spear3xx config file, but there is no PL022 support there.

In fact, to compile locally here I had to change it in this way, even if they cannot be used for testing (only compiling):

Quoted 7 lines
include/configs/spear3xx_evb.h +0 -0
index 3cd56dc..03a046e 100644
@@ -54,6 +54,11 @@
 /* Ethernet driver configuration */

include/configs/spear3xx_evb.h line 64

Quoted 10 lines
include/configs/spear3xx_evb.h +5 -0
 #define CONFIG_DW_ALTDESCRIPTOR
 
+#define CONFIG_PL022_SPI                1
+#define CONFIG_SYS_SPI_BASE             0xE0100000
+#define CONFIG_SYS_SPI_CLK              83000000
+#define CONFIG_CMD_SPI                  1
+
 #if defined(CONFIG_SPEAR310)
 #define CONFIG_MACB
 #define CONFIG_MACB0_PHY                       0x01

I know that Vipin was going to add support of spear1340 in mainline. His patches are currently already submitted and partially acked but I'm not sure what is the status now...

Vipin, can you update us?

Rgds,
Arm

Signature · 8 lines
Thanks,
Jagan.
--------
Jagannadha Sutradharudu Teki,
E: jagannadh.teki at gmail.com, P: +91-9676773388
Engineer - System Software Hacker
U-boot - SPI Custodian and Zynq APSOC
Ln: http://www.linkedin.com/in/jaganteki
#7 lore raw

PATCH v6 1/1 spi: pl022_spi: Add support for ARM PL022 spi controller

Quoted 2 lines · Jagan Teki

Any update on this.

This should already be in u-boot mainline

Regards
Vipin

Quoted 64 lines
Quoted 59 lines · Armando Visconti
Quoted 12 lines · Jagan Teki
Quoted 9 lines · Armando Visconti
Quoted 5 lines

But if you prefer to be on safer side I think we need to re-do some checks on a spare 1340 board...

OK, maybe it is better to re-check again.

Quoted 8 lines
Quoted 4 lines

I need to find some time and a spare board...

I'll let you know,
Arm

Do we have an config file available in master, i need to build at-least.

Mmmh... currently in mainline there is only spear3xx config file, but there is no PL022 support there.

In fact, to compile locally here I had to change it in this way, even if they cannot be used for testing (only compiling):

Quoted 7 lines
include/configs/spear3xx_evb.h +0 -0
index 3cd56dc..03a046e 100644
@@ -54,6 +54,11 @@
  /* Ethernet driver configuration */

include/configs/spear3xx_evb.h line 64

Quoted 10 lines
include/configs/spear3xx_evb.h +5 -0
  #define CONFIG_DW_ALTDESCRIPTOR
 
+#define CONFIG_PL022_SPI                1
+#define CONFIG_SYS_SPI_BASE             0xE0100000
+#define CONFIG_SYS_SPI_CLK              83000000
+#define CONFIG_CMD_SPI                  1
+
  #if defined(CONFIG_SPEAR310)
  #define CONFIG_MACB
  #define CONFIG_MACB0_PHY                       0x01

I know that Vipin was going to add support of spear1340 in mainline. His patches are currently already submitted and partially acked but I'm not sure what is the status now...

Vipin, can you update us?

Rgds,
Arm

#8 lore raw

PATCH v6 1/1 spi: pl022_spi: Add support for ARM PL022 spi controller

Couldn't find in master, can you provide the link atleast.

Quoted 80 lines · Vipin Kumar
Quoted 3 lines · Jagan Teki

Any update on this.

This should already be in u-boot mainline

Regards
Vipin

Quoted 69 lines
Quoted 64 lines · Armando Visconti
Quoted 14 lines · Jagan Teki
Quoted 10 lines · Armando Visconti
Quoted 6 lines

But if you prefer to be on safer side I think we need to re-do some checks on a spare 1340 board...

OK, maybe it is better to re-check again.

Quoted 9 lines
Quoted 4 lines

I need to find some time and a spare board...

I'll let you know,
Arm

Do we have an config file available in master, i need to build at-least.

Mmmh... currently in mainline there is only spear3xx config file, but there is no PL022 support there.

In fact, to compile locally here I had to change it in this way, even if they cannot be used for testing (only compiling):

Quoted 7 lines
include/configs/spear3xx_evb.h +0 -0
index 3cd56dc..03a046e 100644
@@ -54,6 +54,11 @@
  /* Ethernet driver configuration */

include/configs/spear3xx_evb.h line 64

Quoted 10 lines
include/configs/spear3xx_evb.h +5 -0
  #define CONFIG_DW_ALTDESCRIPTOR
 
+#define CONFIG_PL022_SPI                1
+#define CONFIG_SYS_SPI_BASE             0xE0100000
+#define CONFIG_SYS_SPI_CLK              83000000
+#define CONFIG_CMD_SPI                  1
+
  #if defined(CONFIG_SPEAR310)
  #define CONFIG_MACB
  #define CONFIG_MACB0_PHY                       0x01

I know that Vipin was going to add support of spear1340 in mainline. His patches are currently already submitted and partially acked but I'm not sure what is the status now...

Vipin, can you update us?

Rgds,
Arm

Signature · 8 lines
Thanks,
Jagan.
--------
Jagannadha Sutradharudu Teki,
E: jagannadh.teki at gmail.com, P: +91-9676773388
Engineer - System Software Hacker
U-boot - SPI Custodian and Zynq APSOC
Ln: http://www.linkedin.com/in/jaganteki
#9 lore raw

PATCH v6 1/1 spi: pl022_spi: Add support for ARM PL022 spi controller

Quoted 2 lines · Jagan Teki

Couldn't find in master, can you provide the link atleast.

I am sorry. Got confused with something else
You are right. It seems this is not merged yet

May be I have to take this and send a pull request. Meanwhile, can you try taking this patch from the mail itself

Regards
Vipin

Quoted 84 lines · Vipin Kumar
Quoted 80 lines · Jagan Teki
Quoted 3 lines

Any update on this.

This should already be in u-boot mainline

Regards
Vipin

Quoted 69 lines
Quoted 64 lines · Armando Visconti
Quoted 14 lines · Jagan Teki
Quoted 10 lines · Armando Visconti
Quoted 6 lines

But if you prefer to be on safer side I think we need to re-do some checks on a spare 1340 board...

OK, maybe it is better to re-check again.

Quoted 9 lines
Quoted 4 lines

I need to find some time and a spare board...

I'll let you know,
Arm

Do we have an config file available in master, i need to build at-least.

Mmmh... currently in mainline there is only spear3xx config file, but there is no PL022 support there.

In fact, to compile locally here I had to change it in this way, even if they cannot be used for testing (only compiling):

Quoted 7 lines
include/configs/spear3xx_evb.h +0 -0
index 3cd56dc..03a046e 100644
@@ -54,6 +54,11 @@
   /* Ethernet driver configuration */

include/configs/spear3xx_evb.h line 64

Quoted 10 lines
include/configs/spear3xx_evb.h +5 -0
   #define CONFIG_DW_ALTDESCRIPTOR
 
+#define CONFIG_PL022_SPI                1
+#define CONFIG_SYS_SPI_BASE             0xE0100000
+#define CONFIG_SYS_SPI_CLK              83000000
+#define CONFIG_CMD_SPI                  1
+
   #if defined(CONFIG_SPEAR310)
   #define CONFIG_MACB
   #define CONFIG_MACB0_PHY                       0x01

I know that Vipin was going to add support of spear1340 in mainline. His patches are currently already submitted and partially acked but I'm not sure what is the status now...

Vipin, can you update us?

Rgds,
Arm

#10 lore raw

PATCH v6 1/1 spi: pl022_spi: Add support for ARM PL022 spi controller

In reply to Jagan Teki

Hi Vipin,

I have few quick comments, please fix it.
Please use the u-boot-spi.git with master-probe branch for testing this driver. Let me know for any issues/concerns.

Quoted 61 lines · Jagan Teki

Thanks for v6 sent.

Have you tested this?
on which board, include/configs/*.h file?

--
Thanks,
Jagan.

Quoted 50 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.

---
v5->v6

1. Make use of spi_alloc_slave() macro.
2. Changed the identation on 'if statement' as requested by Jagan.

 drivers/spi/Makefile    |   1 +
 drivers/spi/pl022_spi.c | 308 ++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 309 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 +14 -0
new file mode 100644
index 0000000..5b47413
@@ -0,0 +1,308 @@
+/*
+ * (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
Quoted 8 lines

drivers/spi/pl022_spi.c line 22

Quoted 8 lines
drivers/spi/pl022_spi.c new file +8 -0
+ * 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
+ */

Use latest SPDX-License-Identifier:
check for any existing one.

Quoted 9 lines

drivers/spi/pl022_spi.c line 31

Quoted 9 lines
drivers/spi/pl022_spi.c new file +9 -0
+
+#include <common.h>
+#include <malloc.h>
+#include <spi.h>
+#include <asm/io.h>
+#include <asm/arch/hardware.h>
+
+/* SSP registers mapping */
+struct pl022 {

Something like pl022_spi_regs

Quoted 18 lines
Quoted 18 lines
drivers/spi/pl022_spi.c new file +18 -0
+       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 */
Quoted 8 lines

drivers/spi/pl022_spi.c line 57

Quoted 8 lines
drivers/spi/pl022_spi.c new file +8 -0
+       u32     ssp_pid2;       /* 0xfe8 */
+       u32     ssp_pid3;       /* 0xfec */
+       u32     ssp_cid0;       /* 0xff0 */
+       u32     ssp_cid1;       /* 0xff4 */
+       u32     ssp_cid2;       /* 0xff8 */
+       u32     ssp_cid3;       /* 0xffc */
+};
+

-- TAG+

Quoted 11 lines
Quoted 11 lines
drivers/spi/pl022_spi.c new file +11 -0
+/* 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)
Quoted 8 lines

drivers/spi/pl022_spi.c line 76

Quoted 8 lines
drivers/spi/pl022_spi.c new file +8 -0
+
+/* 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 */
+

--- TAG -

Bit mask macros - please place after headers.
We follow a simple format to write spi driver - please check
http://patchwork.ozlabs.org/patch/265683/

And try to verify your code w.r.t above format - let me know any comments.

Quoted 3 lines

drivers/spi/pl022_spi.c line 79

Quoted 3 lines
drivers/spi/pl022_spi.c new file +3 -0
+struct pl022_spi_slave {
+       struct spi_slave slave;
+       void *regs;

Please use the structure pointer instead of void.

Quoted 232 lines
Quoted 232 lines
drivers/spi/pl022_spi.c new file +229 -1
+       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);
+}
+
+/*
+ * 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 */
+}
+
+void __weak spi_cs_deactivate(struct spi_slave *slave)
+{
+       /* do nothing */
+}
+
+void spi_init(void)
+{
+       /* do nothing */
+}
+
+/*
+ * 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;
+
+       /* 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;
+}
+
+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;
+
+       ps = spi_alloc_slave(struct pl022_spi_slave, bus, cs);
+       if (!ps)
+               return NULL;
+
+       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

Signature · 8 lines
Thanks,
Jagan.
--------
Jagannadha Sutradharudu Teki,
E: jagannadh.teki at gmail.com, P: +91-9676773388
Engineer - System Software Hacker
U-boot - SPI Custodian and Zynq APSOC
Ln: http://www.linkedin.com/in/jaganteki
#11 lore raw

PATCH v6 1/1 spi: pl022_spi: Add support for ARM PL022 spi controller

Quoted 374 lines · Jagan Teki

Hi Vipin,

I have few quick comments, please fix it.
Please use the u-boot-spi.git with master-probe branch for testing this driver. Let me know for any issues/concerns.

Quoted 61 lines · Jagan Teki

Thanks for v6 sent.

Have you tested this?
on which board, include/configs/*.h file?

--
Thanks,
Jagan.

Quoted 50 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.

---
v5->v6

1. Make use of spi_alloc_slave() macro.
2. Changed the identation on 'if statement' as requested by Jagan.

 drivers/spi/Makefile    |   1 +
 drivers/spi/pl022_spi.c | 308 ++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 309 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 +14 -0
new file mode 100644
index 0000000..5b47413
@@ -0,0 +1,308 @@
+/*
+ * (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
Quoted 8 lines

drivers/spi/pl022_spi.c line 22

Quoted 8 lines
drivers/spi/pl022_spi.c new file +8 -0
+ * 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
+ */

Use latest SPDX-License-Identifier:
check for any existing one.

Quoted 9 lines

drivers/spi/pl022_spi.c line 31

Quoted 9 lines
drivers/spi/pl022_spi.c new file +9 -0
+
+#include <common.h>
+#include <malloc.h>
+#include <spi.h>
+#include <asm/io.h>
+#include <asm/arch/hardware.h>
+
+/* SSP registers mapping */
+struct pl022 {

Something like pl022_spi_regs

Quoted 18 lines
Quoted 18 lines
drivers/spi/pl022_spi.c new file +18 -0
+       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 */
Quoted 8 lines

drivers/spi/pl022_spi.c line 57

Quoted 8 lines
drivers/spi/pl022_spi.c new file +8 -0
+       u32     ssp_pid2;       /* 0xfe8 */
+       u32     ssp_pid3;       /* 0xfec */
+       u32     ssp_cid0;       /* 0xff0 */
+       u32     ssp_cid1;       /* 0xff4 */
+       u32     ssp_cid2;       /* 0xff8 */
+       u32     ssp_cid3;       /* 0xffc */
+};
+

-- TAG+

Quoted 11 lines
Quoted 11 lines
drivers/spi/pl022_spi.c new file +11 -0
+/* 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)
Quoted 8 lines

drivers/spi/pl022_spi.c line 76

Quoted 8 lines
drivers/spi/pl022_spi.c new file +8 -0
+
+/* 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 */
+

--- TAG -

Bit mask macros - please place after headers.
We follow a simple format to write spi driver - please check
http://patchwork.ozlabs.org/patch/265683/

And try to verify your code w.r.t above format - let me know any comments.

Quoted 3 lines

drivers/spi/pl022_spi.c line 79

Quoted 3 lines
drivers/spi/pl022_spi.c new file +3 -0
+struct pl022_spi_slave {
+       struct spi_slave slave;
+       void *regs;

Please use the structure pointer instead of void.

Quoted 223 lines
Quoted 223 lines
drivers/spi/pl022_spi.c new file +223 -0
+       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);
+}
+
+/*
+ * 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 */
+}
+
+void __weak spi_cs_deactivate(struct spi_slave *slave)
+{
+       /* do nothing */
+}
+
+void spi_init(void)
+{
+       /* do nothing */
+}
+
+/*
+ * 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;
+
+       /* 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;
+}
+
+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;
+
+       ps = spi_alloc_slave(struct pl022_spi_slave, bus, cs);
+       if (!ps)
+               return NULL;
+
+       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++;
+               }
+       }
+
Quoted 8 lines
Quoted 8 lines
Quoted 8 lines
drivers/spi/pl022_spi.c new file +6 -1
+out:
+       if (flags & SPI_XFER_END)
+               spi_cs_deactivate(slave);
+
+       return ret;
+}
--

1.7.11.7

Ping

#12 lore raw

PATCH v6 1/1 spi: pl022_spi: Add support for ARM PL022 spi controller

Hello Jagan,

Sorry for late reply.

Quoted 374 lines · Jagan Teki
Quoted 373 lines · Jagan Teki

Hi Vipin,

I have few quick comments, please fix it.
Please use the u-boot-spi.git with master-probe branch for testing this driver. Let me know for any issues/concerns.

Quoted 61 lines · Jagan Teki

Thanks for v6 sent.

Have you tested this?
on which board, include/configs/*.h file?

--
Thanks,
Jagan.

Quoted 50 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.

---
v5->v6

1. Make use of spi_alloc_slave() macro.
2. Changed the identation on 'if statement' as requested by Jagan.

  drivers/spi/Makefile    |   1 +
  drivers/spi/pl022_spi.c | 308 ++++++++++++++++++++++++++++++++++++++++++++++++
  2 files changed, 309 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 +14 -0
new file mode 100644
index 0000000..5b47413
@@ -0,0 +1,308 @@
+/*
+ * (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
Quoted 8 lines

drivers/spi/pl022_spi.c line 22

Quoted 8 lines
drivers/spi/pl022_spi.c new file +8 -0
+ * 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
+ */

Use latest SPDX-License-Identifier:
check for any existing one.

Quoted 9 lines

drivers/spi/pl022_spi.c line 31

Quoted 9 lines
drivers/spi/pl022_spi.c new file +9 -0
+
+#include <common.h>
+#include <malloc.h>
+#include <spi.h>
+#include <asm/io.h>
+#include <asm/arch/hardware.h>
+
+/* SSP registers mapping */
+struct pl022 {

Something like pl022_spi_regs

Quoted 18 lines
Quoted 18 lines
drivers/spi/pl022_spi.c new file +18 -0
+       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 */
Quoted 8 lines

drivers/spi/pl022_spi.c line 57

Quoted 8 lines
drivers/spi/pl022_spi.c new file +8 -0
+       u32     ssp_pid2;       /* 0xfe8 */
+       u32     ssp_pid3;       /* 0xfec */
+       u32     ssp_cid0;       /* 0xff0 */
+       u32     ssp_cid1;       /* 0xff4 */
+       u32     ssp_cid2;       /* 0xff8 */
+       u32     ssp_cid3;       /* 0xffc */
+};
+

-- TAG+

Quoted 11 lines
Quoted 11 lines
drivers/spi/pl022_spi.c new file +11 -0
+/* 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)
Quoted 8 lines

drivers/spi/pl022_spi.c line 76

Quoted 8 lines
drivers/spi/pl022_spi.c new file +8 -0
+
+/* 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 */
+

--- TAG -

Bit mask macros - please place after headers.
We follow a simple format to write spi driver - please check
http://patchwork.ozlabs.org/patch/265683/

And try to verify your code w.r.t above format - let me know any comments.

Quoted 3 lines

drivers/spi/pl022_spi.c line 79

Quoted 3 lines
drivers/spi/pl022_spi.c new file +3 -0
+struct pl022_spi_slave {
+       struct spi_slave slave;
+       void *regs;

Please use the structure pointer instead of void.

Quoted 224 lines
Quoted 224 lines
drivers/spi/pl022_spi.c new file +224 -0
+       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);
+}
+
+/*
+ * 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 */
+}
+
+void __weak spi_cs_deactivate(struct spi_slave *slave)
+{
+       /* do nothing */
+}
+
+void spi_init(void)
+{
+       /* do nothing */
+}
+
+/*
+ * 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;
+
+       /* 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;
+}
+
+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;
+
+       ps = spi_alloc_slave(struct pl022_spi_slave, bus, cs);
+       if (!ps)
+               return NULL;
+
+       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:
Quoted 9 lines
Quoted 7 lines
Quoted 7 lines
Quoted 7 lines
drivers/spi/pl022_spi.c new file +5 -1
+       if (flags & SPI_XFER_END)
+               spi_cs_deactivate(slave);
+
+       return ret;
+}
--

1.7.11.7

Ping

Unfortunately lot of changes happened to our organization and we (myself and Vipin) are no longer able to proceed in doing this job.

So I think we need to drop this patch, unless someone from the u-boot community has the possibility to (and is willing to) proceed in implementing and testing the proper changes.

Sorry for that,
Armando

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

PATCH v6 1/1 spi: pl022_spi: Add support for ARM PL022 spi controller

Quoted 415 lines · Armando Visconti

Hello Jagan,

Sorry for late reply.

Quoted 398 lines · Jagan Teki
Quoted 395 lines · Jagan Teki

Hi Vipin,

I have few quick comments, please fix it.
Please use the u-boot-spi.git with master-probe branch for testing this driver.
Let me know for any issues/concerns.

Quoted 66 lines · Jagan Teki

Thanks for v6 sent.

Have you tested this?
on which board, include/configs/*.h file?

--
Thanks,
Jagan.

Quoted 54 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.

---
v5->v6

1. Make use of spi_alloc_slave() macro.
2. Changed the identation on 'if statement' as requested by Jagan.

  drivers/spi/Makefile    |   1 +
  drivers/spi/pl022_spi.c | 308
++++++++++++++++++++++++++++++++++++++++++++++++
  2 files changed, 309 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 +14 -0
new file mode 100644
index 0000000..5b47413
@@ -0,0 +1,308 @@
+/*
+ * (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
Quoted 8 lines

drivers/spi/pl022_spi.c line 22

Quoted 8 lines
drivers/spi/pl022_spi.c new file +8 -0
+ * 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
+ */

Use latest SPDX-License-Identifier:
check for any existing one.

Quoted 9 lines

drivers/spi/pl022_spi.c line 31

Quoted 9 lines
drivers/spi/pl022_spi.c new file +9 -0
+
+#include <common.h>
+#include <malloc.h>
+#include <spi.h>
+#include <asm/io.h>
+#include <asm/arch/hardware.h>
+
+/* SSP registers mapping */
+struct pl022 {

Something like pl022_spi_regs

Quoted 18 lines
Quoted 18 lines
drivers/spi/pl022_spi.c new file +18 -0
+       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 */
Quoted 8 lines

drivers/spi/pl022_spi.c line 57

Quoted 8 lines
drivers/spi/pl022_spi.c new file +8 -0
+       u32     ssp_pid2;       /* 0xfe8 */
+       u32     ssp_pid3;       /* 0xfec */
+       u32     ssp_cid0;       /* 0xff0 */
+       u32     ssp_cid1;       /* 0xff4 */
+       u32     ssp_cid2;       /* 0xff8 */
+       u32     ssp_cid3;       /* 0xffc */
+};
+

-- TAG+

Quoted 16 lines
Quoted 16 lines
drivers/spi/pl022_spi.c new file +14 -0
+/* 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 */

Quoted 8 lines

drivers/spi/pl022_spi.c

Quoted 8 lines

+#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 +2 -0
+#define SSP_SR_MASK_BSY                (0x1 << 4) /* Busy Flag */
+

--- TAG -

Bit mask macros - please place after headers.
We follow a simple format to write spi driver - please check
http://patchwork.ozlabs.org/patch/265683/

And try to verify your code w.r.t above format - let me know any comments.

Quoted 3 lines

drivers/spi/pl022_spi.c line 79

Quoted 3 lines
drivers/spi/pl022_spi.c new file +3 -0
+struct pl022_spi_slave {
+       struct spi_slave slave;
+       void *regs;

Please use the structure pointer instead of void.

Quoted 227 lines
Quoted 227 lines
drivers/spi/pl022_spi.c new file +4 -0
+       unsigned int freq;
+};
+
+static inline struct pl022_spi_slave *to_pl022_spi(struct spi_slave

*slave)

drivers/spi/pl022_spi.c new file +31 -0
+{
+       return container_of(slave, struct pl022_spi_slave, slave);
+}
+
+/*
+ * 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 */
+}
+
+void __weak spi_cs_deactivate(struct spi_slave *slave)
+{
+       /* do nothing */
+}
+
+void spi_init(void)
+{
+       /* do nothing */
+}
+
+/*
+ * 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 +188 -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;
+}
+
+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;
+
+       ps = spi_alloc_slave(struct pl022_spi_slave, bus, cs);
+       if (!ps)
+               return NULL;
+
+       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)
Quoted 9 lines
Quoted 6 lines
Quoted 6 lines
Quoted 6 lines
drivers/spi/pl022_spi.c new file +4 -1
+               spi_cs_deactivate(slave);
+
+       return ret;
+}
--

1.7.11.7

Ping

Quoted 7 lines

Unfortunately lot of changes happened to our organization and we (myself and Vipin) are no longer able to proceed in doing this job.

So I think we need to drop this patch, unless someone from the u-boot community has the possibility to (and is willing to) proceed in implementing and testing the proper changes.

Thanks,

--
Jagan.