All of lore.kernel.org
 help / color / mirror / Atom feed
* [U-Boot] [PATCH v6] spi: pl022_spi: Add support for ARM PL022 spi controller
@ 2016-09-08 14:21 Michael Brandl
  2016-09-14 14:39 ` Armando Visconti
  2016-09-14 17:52 ` Jagan Teki
  0 siblings, 2 replies; 20+ messages in thread
From: Michael Brandl @ 2016-09-08 14:21 UTC (permalink / raw)
  To: u-boot

Dear U-Boot (SPI) Developers,

this patch seems to be my only chance to get spi working without/before Linux.

I'm a student from Augsburg (Germany) experimenting with the Hikey Board from 96boards.
The hi6220 processor from HiSilicon isn't fully documented, there is just one document called Function Description:
http://mirror.lemaker.org/Hi6220V100_Multi-Mode_Application_Processor_Function_Description.pdf

U-Boot already supports the Hikey Board to be loaded from ARM Trusted Firmware (ATF) but only UART and SDMMC is supported by now.
I cloned the u-boot-spi.git and tried to integrate this patch but I'm not experienced enough to adjust the specific config for the Hikey Board.

Taking a look at armv7 devices with spi support I started like this:

+++ b/arch/arm/include/asm/arch-hi6220/hi6220.h

+/*Hi6220V100_Multi-Mode_Application_Processor_Function_Description on p.5-45*/
+#define HI6220_SPI_BASE				0xF7106000

  
+++ b/include/configs/hikey.h

+/* Synchronous Serial Port PL022 for SPI */
+#define CONFIG_PL022_SPI


+++ b/board/hisilicon/hikey/hikey.c

  int board_init(void)
  {
+#ifdef CONFIG_PL022_SPI
+	hikey_spi0_hw_init();
+#endif
  	return 0;
  }


+static void hikey_spi0_hw_init(void)
+{
+	hi6220_pinmux_config(PERIPH_ID_SPI0)
+//	at91_set_pio_output(AT91_PIO_PORTC, 3, 1);	/* SPI0_CS0 */
+	gpio_request(0, "PWR_HOLD_GPIO0_0");
+	gpio_direction_output(0, 1);
+
+	/* Enable clock */
+//	at91_periph_clk_enable(ATMEL_ID_SPI0);
+/* from Kernel	{ HI6220_SPI_CLK, "spi_clk", "clk_150m", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x230, 9,  0, }, */
+	hi6220_clk_enable(PERI_CLK0_SPI0, &peri_sc->clk3_en);
+
+}
+#endif /* CONFIG_PL022_SPI */
+
  

+++ b/arch/arm/cpu/armv8/hisilicon/pinmux.c
  
+static void hi6220_spi_config(int peripheral)
+{
+	switch (peripheral) {
+	case PERIPH_ID_SPI0:
+//		at91_set_a_periph(AT91_PIO_PORTC, 0, 0);	/* SPI0_MISO */
+//		at91_set_a_periph(AT91_PIO_PORTC, 1, 0);	/* SPI0_MOSI */
+//		at91_set_a_periph(AT91_PIO_PORTC, 2, 0);	/* SPI0_SPCK */
+		break;
+
+	case PERIPH_ID_SPI1:
+		break;
+
+	default:
+		debug("%s: invalid peripheral %d", __func__, peripheral);
+		return;
+	}
+}

Maybe you can help me to get spi working on Hikey. My overall aim is to port the pl022 driver then to ARM TF ... maybe also that could be interessing for you.

With kind Regards,
Michael Brandl



On Wed, Jan 8, 2014 at 2:49 PM, Armando Visconti
<armando.visconti@st.com <http://lists.denx.de/mailman/listinfo/u-boot>> wrote:
>/Hello Jagan, />//>/Sorry for late reply. />//>//>//>/On 12/20/2013 8:03 PM, Jagan Teki wrote: />>//>>/On Fri, Oct 4, 2013 at 12:20 PM, Jagan Teki <jagannadh.teki@gmail.com 
<http://lists.denx.de/mailman/listinfo/u-boot>> />>/wrote: />>>//>>>/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. />>>//>>>/On Wed, Jun 12, 2013 at 7:55 PM, Jagan Teki <jagannadh.teki@gmail.com 
<http://lists.denx.de/mailman/listinfo/u-boot>> />>>/wrote: />>>>//>>>>/Thanks for v6 sent. />>>>//>>>>/Have you tested this? />>>>/on which board, include/configs/*.h file? />>>>//>>>>/-- />>>>/Thanks, />>>>/Jagan. />>>>//>>>>/On Wed, Jun 12, 2013 at 6:17 PM, Armando Visconti />>>>/<armando.visconti@st.com 
<http://lists.denx.de/mailman/listinfo/u-boot>> wrote: />>>>>//>>>>>/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. />>>>>//>>>>>/Signed-off-by: Armando Visconti <armando.visconti@st.com 
<http://lists.denx.de/mailman/listinfo/u-boot>> />>>>>/Signed-off-by: Vipin Kumar <vipin.kumar@st.com 
<http://lists.denx.de/mailman/listinfo/u-boot>> />>>>>/Acked-by: Stefan Roese <sr@denx.de 
<http://lists.denx.de/mailman/listinfo/u-boot>> />>>>>/--- />>>>>/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 />>>>>//>>>>>/diff --git a/drivers/spi/Makefile b/drivers/spi/Makefile />>>>>/index d08609e..b6443b1 100644 />>>>>/--- a/drivers/spi/Makefile />>>>>/+++ b/drivers/spi/Makefile />>>>>/@@ -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 />>>>>/diff --git a/drivers/spi/pl022_spi.c b/drivers/spi/pl022_spi.c />>>>>/new file mode 100644 />>>>>/index 0000000..5b47413 />>>>>/--- /dev/null />>>>>/+++ b/drivers/spi/pl022_spi.c />>>>>/@@ -0,0 +1,308 @@ />>>>>/+/* />>>>>/+ * (C) Copyright 2012 />>>>>/+ * Armando Visconti, ST Microelectronics, armando.visconti at st.com. 
<http://lists.denx.de/mailman/listinfo/u-boot> />>>>>/+ * />>>>>/+ * 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 />>>>>/+ */ />>>//>>>/Use latest SPDX-License-Identifier: />>>/check for any existing one. />>>//>>>>>/+ />>>>>/+#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 />>>//>>>>>/+ 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 */ />>>>>/+}; />>>>>/+ />>>//>>>/-- TAG+ />>>>>//>>>>>/+/* 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 */ />>>>>/+ />>>//>>>/--- 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. />>>//>>>>>/+struct pl022_spi_slave { />>>>>/+ struct spi_slave slave; />>>>>/+ void *regs; />>>//>>>/Please use the structure pointer instead of void. />>>//>>>>>/+ 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 />>//>>/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. /

^ permalink raw reply	[flat|nested] 20+ messages in thread

* [U-Boot] [PATCH v6] spi: pl022_spi: Add support for ARM PL022 spi controller
  2016-09-08 14:21 [U-Boot] [PATCH v6] spi: pl022_spi: Add support for ARM PL022 spi controller Michael Brandl
@ 2016-09-14 14:39 ` Armando Visconti
  2016-09-19 11:59   ` [U-Boot] ?==?utf-8?q? ?==?utf-8?q? [PATCH v6]?==?utf-8?q? spi:?==?utf-8?q? " Michael Brandl
  2016-09-14 17:52 ` Jagan Teki
  1 sibling, 1 reply; 20+ messages in thread
From: Armando Visconti @ 2016-09-14 14:39 UTC (permalink / raw)
  To: u-boot

Ciao Michael,

On 09/08/2016 04:21 PM, Michael Brandl wrote:
> Dear U-Boot (SPI) Developers,
>
> this patch seems to be my only chance to get spi working without/before Linux.

I wrote and used this code for u-boot for a asic
specified by one of our customers. The patch was generic
enough to be pushed in u-boot, but I didn't have
much time to test it on a different, more generic
platform. So the maintainer decided to drop it...

Would be nice if you could work on it and resurrect it...
:)

Let me know if you have progressed on this or abandoned it.

>
> I'm a student from Augsburg (Germany) experimenting with the Hikey Board from 96boards.
> The hi6220 processor from HiSilicon isn't fully documented, there is just one document called Function Description:
> http://mirror.lemaker.org/Hi6220V100_Multi-Mode_Application_Processor_Function_Description.pdf
>

Yes, I'm currently using HiKey platform for doing my day by day
job here in office. Nevertheless, I don't think I have enough
time to take a look into testing this commit.

> U-Boot already supports the Hikey Board to be loaded from ARM Trusted Firmware (ATF) but only UART and SDMMC is supported by now.
> I cloned the u-boot-spi.git and tried to integrate this patch but I'm not experienced enough to adjust the specific config for the Hikey Board.
>

Maybe I can try to recover the work that was done to integrate
this commit into the customer platform I was talking about.
I'll take a look into it right now...

> Taking a look at armv7 devices with spi support I started like this:
>
> +++ b/arch/arm/include/asm/arch-hi6220/hi6220.h
>
> +/*Hi6220V100_Multi-Mode_Application_Processor_Function_Description on p.5-45*/
> +#define HI6220_SPI_BASE				0xF7106000
>
>
> +++ b/include/configs/hikey.h
>
> +/* Synchronous Serial Port PL022 for SPI */
> +#define CONFIG_PL022_SPI
>
>
> +++ b/board/hisilicon/hikey/hikey.c
>
>  int board_init(void)
>  {
> +#ifdef CONFIG_PL022_SPI
> +	hikey_spi0_hw_init();
> +#endif
>  	return 0;
>  }
>
>
> +static void hikey_spi0_hw_init(void)
> +{
> +	hi6220_pinmux_config(PERIPH_ID_SPI0)
> +//	at91_set_pio_output(AT91_PIO_PORTC, 3, 1);	/* SPI0_CS0 */
> +	gpio_request(0, "PWR_HOLD_GPIO0_0");
> +	gpio_direction_output(0, 1);
> +
> +	/* Enable clock */
> +//	at91_periph_clk_enable(ATMEL_ID_SPI0);
> +/* from Kernel	{ HI6220_SPI_CLK, "spi_clk", "clk_150m", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x230, 9,  0, }, */
> +	hi6220_clk_enable(PERI_CLK0_SPI0, &peri_sc->clk3_en);
> +
> +}
> +#endif /* CONFIG_PL022_SPI */
> +
>
>
> +++ b/arch/arm/cpu/armv8/hisilicon/pinmux.c
>
> +static void hi6220_spi_config(int peripheral)
> +{
> +	switch (peripheral) {
> +	case PERIPH_ID_SPI0:
> +//		at91_set_a_periph(AT91_PIO_PORTC, 0, 0);	/* SPI0_MISO */
> +//		at91_set_a_periph(AT91_PIO_PORTC, 1, 0);	/* SPI0_MOSI */
> +//		at91_set_a_periph(AT91_PIO_PORTC, 2, 0);	/* SPI0_SPCK */
> +		break;
> +
> +	case PERIPH_ID_SPI1:
> +		break;
> +
> +	default:
> +		debug("%s: invalid peripheral %d", __func__, peripheral);
> +		return;
> +	}
> +}
>
> Maybe you can help me to get spi working on Hikey. My overall aim is to port the pl022 driver then to ARM TF ... maybe also that could be interessing for you.
>
> With kind Regards,
> Michael Brandl
>
>
>
>

Rgds,
Armando

^ permalink raw reply	[flat|nested] 20+ messages in thread

* [U-Boot] [PATCH v6] spi: pl022_spi: Add support for ARM PL022 spi controller
  2016-09-08 14:21 [U-Boot] [PATCH v6] spi: pl022_spi: Add support for ARM PL022 spi controller Michael Brandl
  2016-09-14 14:39 ` Armando Visconti
@ 2016-09-14 17:52 ` Jagan Teki
  1 sibling, 0 replies; 20+ messages in thread
From: Jagan Teki @ 2016-09-14 17:52 UTC (permalink / raw)
  To: u-boot

On Thu, Sep 8, 2016 at 7:51 PM, Michael Brandl
<michael.brandl@hs-augsburg.de> wrote:
> Dear U-Boot (SPI) Developers,
>
> this patch seems to be my only chance to get spi working without/before
> Linux.
>
> I'm a student from Augsburg (Germany) experimenting with the Hikey Board
> from 96boards.
> The hi6220 processor from HiSilicon isn't fully documented, there is just
> one document called Function Description:
> http://mirror.lemaker.org/Hi6220V100_Multi-Mode_Application_Processor_Function_Description.pdf
>
> U-Boot already supports the Hikey Board to be loaded from ARM Trusted
> Firmware (ATF) but only UART and SDMMC is supported by now.
> I cloned the u-boot-spi.git and tried to integrate this patch but I'm not
> experienced enough to adjust the specific config for the Hikey Board.

Please try to use u-boot.git and send the patch format.

thanks!
-- 
Jagan Teki
Free Software Engineer | www.openedev.com
U-Boot, Linux | Upstream Maintainer
Hyderabad, India.

^ permalink raw reply	[flat|nested] 20+ messages in thread

* [U-Boot] ?==?utf-8?q? ?==?utf-8?q? [PATCH v6]?==?utf-8?q? spi:?==?utf-8?q? pl022_spi: Add support for ARM PL022 spi controller
  2016-09-14 14:39 ` Armando Visconti
@ 2016-09-19 11:59   ` Michael Brandl
  2016-09-19 14:14     ` [U-Boot] [PATCH v6] spi: " Armando Visconti
  0 siblings, 1 reply; 20+ messages in thread
From: Michael Brandl @ 2016-09-19 11:59 UTC (permalink / raw)
  To: u-boot

Ciao Armando,
Hi Jagan,

On Friday I found another driver implementation already on my desktop, by grepping for pl022 in the upper level ../, but it is more general and not easy to understand. But maybe it helps us to find the information we need.

This is how I started! Now as patchset based on u-boot-spi.git:


diff --git a/arch/arm/cpu/armv8/hisilicon/pinmux.c b/arch/arm/cpu/armv8/hisilicon/pinmux.c
index 3e4c9ce..83f02db 100644
--- a/arch/arm/cpu/armv8/hisilicon/pinmux.c
+++ b/arch/arm/cpu/armv8/hisilicon/pinmux.c
@@ -17,6 +17,24 @@ struct hi6220_pinmux0_regs *pmx0 =
 struct hi6220_pinmux1_regs *pmx1 =
 	(struct hi6220_pinmux1_regs *)HI6220_PINMUX1_BASE;
 
+static void hi6220_spi_config(int peripheral)
+{
+	switch (peripheral) {
+	case PERIPH_ID_SPI0:
+//		at91_set_a_periph(AT91_PIO_PORTC, 0, 0);	/* SPI0_MISO */
+//		at91_set_a_periph(AT91_PIO_PORTC, 1, 0);	/* SPI0_MOSI */
+//		at91_set_a_periph(AT91_PIO_PORTC, 2, 0);	/* SPI0_SPCK */
+		break;
+
+	case PERIPH_ID_SPI1:
+		break;
+
+	default:
+		debug("%s: invalid peripheral %d", __func__, peripheral);
+		return;
+	}
+}
+
 static void hi6220_uart_config(int peripheral)
 {
 	switch (peripheral) {
@@ -164,6 +182,9 @@ static int hi6220_mmc_config(int peripheral)
 int hi6220_pinmux_config(int peripheral)
 {
 	switch (peripheral) {
+	case PERIPH_ID_SPI0:
+		hi6220_spi_config(peripheral);
+		break;
 	case PERIPH_ID_UART0:
 	case PERIPH_ID_UART1:
 	case PERIPH_ID_UART2:
diff --git a/arch/arm/include/asm/arch-hi6220/hi6220.h b/arch/arm/include/asm/arch-hi6220/hi6220.h
index 3a12c75..1b73f42 100644
--- a/arch/arm/include/asm/arch-hi6220/hi6220.h
+++ b/arch/arm/include/asm/arch-hi6220/hi6220.h
@@ -19,6 +19,8 @@
 #define HI6220_PMUSSI_BASE			0xF8000000
 
 #define HI6220_PERI_BASE			0xF7030000
+/*Hi6220V100_Multi-Mode_Application_Processor_Function_Description on p.5-45*/
+#define HI6220_SPI_BASE				0xF7106000
 
 struct peri_sc_periph_regs {
 	u32 ctrl1;		/*0x0*/
diff --git a/arch/arm/include/asm/arch-hi6220/periph.h b/arch/arm/include/asm/arch-hi6220/periph.h
index 7155f60..b58a0f7 100644
--- a/arch/arm/include/asm/arch-hi6220/periph.h
+++ b/arch/arm/include/asm/arch-hi6220/periph.h
@@ -25,6 +25,8 @@ enum periph_id {
 	PERIPH_ID_SDMMC1,
 
 	PERIPH_ID_NONE = -1,
+	PERIPH_ID_SPI0,
+	PERIPH_ID_SPI1,
 };
 
 #endif /* __ASM_ARM_ARCH_PERIPH_H */
diff --git a/board/hisilicon/hikey/hikey.c b/board/hisilicon/hikey/hikey.c
index 72d6334..e90ea74 100644
--- a/board/hisilicon/hikey/hikey.c
+++ b/board/hisilicon/hikey/hikey.c
@@ -21,6 +21,10 @@
 #include <asm/arch/hi6220.h>
 #include <asm/armv8/mmu.h>
 
+#ifdef CONFIG_PL022_SPI
+#include <spi.h>
+#endif
+
 /*TODO drop this table in favour of device tree */
 static const struct hikey_gpio_platdata hi6220_gpio[] = {
 	{ 0, HI6220_GPIO_BASE(0)},
@@ -335,9 +339,46 @@ int misc_init_r(void)
 {
 	return 0;
 }
+#ifdef CONFIG_PL022_SPI
+int spi_cs_is_valid(unsigned int bus, unsigned int cs)
+{
+	return bus == 0 && cs == 0;
+}
+
+void spi_cs_activate(struct spi_slave *slave)
+{
+//	at91_set_pio_output(AT91_PIO_PORTC, 3, 0);
+	gpio_request(0, "PWR_HOLD_GPIO0_0");
+	gpio_direction_output(0, 1);
+}
+
+void spi_cs_deactivate(struct spi_slave *slave)
+{
+//	at91_set_pio_output(AT91_PIO_PORTC, 3, 1);
+	gpio_request(0, "PWR_HOLD_GPIO0_0");
+	gpio_direction_output(0, 1);
+}
+
+static void hikey_spi0_hw_init(void)
+{
+	hi6220_pinmux_config(PERIPH_ID_SPI0);
+//	at91_set_pio_output(AT91_PIO_PORTC, 3, 1);	/* SPI0_CS0 */
+	gpio_request(0, "PWR_HOLD_GPIO0_0");
+	gpio_direction_output(0, 1);
+
+	/* Enable clock */
+//	at91_periph_clk_enable(ATMEL_ID_SPI0);
+/* from Kernel	{ HI6220_SPI_CLK, "spi_clk", "clk_150m", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x230, 9,  0, }, */
+//	hi6220_clk_enable(PERI_CLK0_SPI0, &peri_sc->clk3_en);
+
+}
+#endif /* CONFIG_PL022_SPI */
 
 int board_init(void)
 {
+#ifdef CONFIG_PL022_SPI
+	hikey_spi0_hw_init();
+#endif
 	return 0;
 }
 
diff --git a/drivers/spi/Makefile b/drivers/spi/Makefile
index b1d9e20..a509d93 100644
--- a/drivers/spi/Makefile
+++ b/drivers/spi/Makefile
@@ -6,6 +6,8 @@
 #
 
 # There are many options which enable SPI, so make this library available
+obj-$(CONFIG_PL022_SPI) += pl022_spi.o
+
 ifdef CONFIG_DM_SPI
 obj-y += spi-uclass.o
 obj-$(CONFIG_SANDBOX) += spi-emul-uclass.o
diff --git a/drivers/spi/pl022_spi.c b/drivers/spi/pl022_spi.c
index e69de29..e80fed3 100644
--- a/drivers/spi/pl022_spi.c
+++ b/drivers/spi/pl022_spi.c
@@ -0,0 +1,321 @@
+/*
+ * (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
+ */
+/* Comment by Jagan: Use latest SPDX-License-Identifier: >> check for any existing one. */
+
+#include <common.h>
+#include <malloc.h>
+#include <spi.h>
+#include <asm/io.h>
+//#include <asm/arch/hardware.h>
+
+/* SSP registers mapping */
+/* Comment by Jagan: Something like pl022_spi_regs*/
+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 */
+};
+
+/* Comment by Jagan: -- TAG+*/
+/* 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 */
+
+/* Comment by Jagan: --- TAG -*/
+/* Comment by Jagan: 
+ * 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.
+ */
+struct pl022_spi_slave {
+       struct spi_slave slave;
+       void *regs;
+/* Comment by Jagan: Please use the structure pointer instead of void. */
+
+       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;
+}
diff --git a/include/configs/hikey.h b/include/configs/hikey.h
index ffcc4d2..5ac8997 100644
--- a/include/configs/hikey.h
+++ b/include/configs/hikey.h
@@ -76,6 +76,24 @@
 
 #define CONFIG_HIKEY_GPIO
 
+/* Synchronous Serial Port PL022 for SPI */
+#define CONFIG_PL022_SPI
+
+/* SPI Configuration */
+#define CONFIG_SYS_SPI_BASE		0xF7106000
+//#define CONFIG_DAVINCI_SPI
+//#define CONFIG_SYS_SPI_CLK		clk_get_rate(KS2_CLK1_6)
+//#define CONFIG_SYS_SPI_CLK		24000000
+//#define CONFIG_SYS_SPI_CLK		83000000
+#define CONFIG_SYS_SPI_CLK		121000000
+//#define CONFIG_SF_DEFAULT_SPEED		30000000
+//#define CONFIG_ENV_SPI_MAX_HZ		CONFIG_SF_DEFAULT_SPEED
+#ifdef CONFIG_SPL_BUILD
+#undef CONFIG_DM_SPI
+#undef CONFIG_DM_SPI_FLASH
+#endif
+
+
 
 
 
 
Am Mittwoch, September 14, 2016 16:39 CEST, Armando Visconti <armando.visconti@st.com> schrieb: 
 
> Ciao Michael,
> 
> On 09/08/2016 04:21 PM, Michael Brandl wrote:
> > Dear U-Boot (SPI) Developers,
> >
> > this patch seems to be my only chance to get spi working without/before Linux.
> 
> I wrote and used this code for u-boot for a asic
> specified by one of our customers. The patch was generic
> enough to be pushed in u-boot, but I didn't have
> much time to test it on a different, more generic
> platform. So the maintainer decided to drop it...
> 
> Would be nice if you could work on it and resurrect it...
> :)
> 
> Let me know if you have progressed on this or abandoned it.
> 
> >
> > I'm a student from Augsburg (Germany) experimenting with the Hikey Board from 96boards.
> > The hi6220 processor from HiSilicon isn't fully documented, there is just one document called Function Description:
> > http://mirror.lemaker.org/Hi6220V100_Multi-Mode_Application_Processor_Function_Description.pdf
> >
> 
> Yes, I'm currently using HiKey platform for doing my day by day
> job here in office. Nevertheless, I don't think I have enough
> time to take a look into testing this commit.
> 
> > U-Boot already supports the Hikey Board to be loaded from ARM Trusted Firmware (ATF) but only UART and SDMMC is supported by now.
> > I cloned the u-boot-spi.git and tried to integrate this patch but I'm not experienced enough to adjust the specific config for the Hikey Board.
> >
> 
> Maybe I can try to recover the work that was done to integrate
> this commit into the customer platform I was talking about.
> I'll take a look into it right now...
> 
> > Taking a look at armv7 devices with spi support I started like this:
> >
> > +++ b/arch/arm/include/asm/arch-hi6220/hi6220.h
> >
> > +/*Hi6220V100_Multi-Mode_Application_Processor_Function_Description on p.5-45*/
> > +#define HI6220_SPI_BASE				0xF7106000
> >
> >
> > +++ b/include/configs/hikey.h
> >
> > +/* Synchronous Serial Port PL022 for SPI */
> > +#define CONFIG_PL022_SPI
> >
> >
> > +++ b/board/hisilicon/hikey/hikey.c
> >
> >  int board_init(void)
> >  {
> > +#ifdef CONFIG_PL022_SPI
> > +	hikey_spi0_hw_init();
> > +#endif
> >  	return 0;
> >  }
> >
> >
> > +static void hikey_spi0_hw_init(void)
> > +{
> > +	hi6220_pinmux_config(PERIPH_ID_SPI0)
> > +//	at91_set_pio_output(AT91_PIO_PORTC, 3, 1);	/* SPI0_CS0 */
> > +	gpio_request(0, "PWR_HOLD_GPIO0_0");
> > +	gpio_direction_output(0, 1);
> > +
> > +	/* Enable clock */
> > +//	at91_periph_clk_enable(ATMEL_ID_SPI0);
> > +/* from Kernel	{ HI6220_SPI_CLK, "spi_clk", "clk_150m", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x230, 9,  0, }, */
> > +	hi6220_clk_enable(PERI_CLK0_SPI0, &peri_sc->clk3_en);
> > +
> > +}
> > +#endif /* CONFIG_PL022_SPI */
> > +
> >
> >
> > +++ b/arch/arm/cpu/armv8/hisilicon/pinmux.c
> >
> > +static void hi6220_spi_config(int peripheral)
> > +{
> > +	switch (peripheral) {
> > +	case PERIPH_ID_SPI0:
> > +//		at91_set_a_periph(AT91_PIO_PORTC, 0, 0);	/* SPI0_MISO */
> > +//		at91_set_a_periph(AT91_PIO_PORTC, 1, 0);	/* SPI0_MOSI */
> > +//		at91_set_a_periph(AT91_PIO_PORTC, 2, 0);	/* SPI0_SPCK */
> > +		break;
> > +
> > +	case PERIPH_ID_SPI1:
> > +		break;
> > +
> > +	default:
> > +		debug("%s: invalid peripheral %d", __func__, peripheral);
> > +		return;
> > +	}
> > +}
> >
> > Maybe you can help me to get spi working on Hikey. My overall aim is to port the pl022 driver then to ARM TF ... maybe also that could be interessing for you.
> >
> > With kind Regards,
> > Michael Brandl
> >
> >
> >
> >
> 
> Rgds,
> Armando
>

^ permalink raw reply related	[flat|nested] 20+ messages in thread

* [U-Boot] [PATCH v6] spi: pl022_spi: Add support for ARM PL022 spi controller
  2016-09-19 11:59   ` [U-Boot] ?==?utf-8?q? ?==?utf-8?q? [PATCH v6]?==?utf-8?q? spi:?==?utf-8?q? " Michael Brandl
@ 2016-09-19 14:14     ` Armando Visconti
  2016-09-20  6:25       ` Michael Brandl
  0 siblings, 1 reply; 20+ messages in thread
From: Armando Visconti @ 2016-09-19 14:14 UTC (permalink / raw)
  To: u-boot

Ciao Michael,

Did you test it?
It seems that all the platform related changes (pinmux, board file,
...) are there.

Pls let us know,
Armando

On 09/19/2016 01:59 PM, Michael Brandl wrote:
> Ciao Armando,
> Hi Jagan,
>
> On Friday I found another driver implementation already on my desktop, by grepping for pl022 in the upper level ../, but it is more general and not easy to understand. But maybe it helps us to find the information we need.
>
> This is how I started! Now as patchset based on u-boot-spi.git:
>
>
> diff --git a/arch/arm/cpu/armv8/hisilicon/pinmux.c b/arch/arm/cpu/armv8/hisilicon/pinmux.c
> index 3e4c9ce..83f02db 100644
> --- a/arch/arm/cpu/armv8/hisilicon/pinmux.c
> +++ b/arch/arm/cpu/armv8/hisilicon/pinmux.c
> @@ -17,6 +17,24 @@ struct hi6220_pinmux0_regs *pmx0 =
>  struct hi6220_pinmux1_regs *pmx1 =
>         (struct hi6220_pinmux1_regs *)HI6220_PINMUX1_BASE;
>
> +static void hi6220_spi_config(int peripheral)
> +{
> +       switch (peripheral) {
> +       case PERIPH_ID_SPI0:
> +//             at91_set_a_periph(AT91_PIO_PORTC, 0, 0);        /* SPI0_MISO */
> +//             at91_set_a_periph(AT91_PIO_PORTC, 1, 0);        /* SPI0_MOSI */
> +//             at91_set_a_periph(AT91_PIO_PORTC, 2, 0);        /* SPI0_SPCK */
> +               break;
> +
> +       case PERIPH_ID_SPI1:
> +               break;
> +
> +       default:
> +               debug("%s: invalid peripheral %d", __func__, peripheral);
> +               return;
> +       }
> +}
> +
>  static void hi6220_uart_config(int peripheral)
>  {
>         switch (peripheral) {
> @@ -164,6 +182,9 @@ static int hi6220_mmc_config(int peripheral)
>  int hi6220_pinmux_config(int peripheral)
>  {
>         switch (peripheral) {
> +       case PERIPH_ID_SPI0:
> +               hi6220_spi_config(peripheral);
> +               break;
>         case PERIPH_ID_UART0:
>         case PERIPH_ID_UART1:
>         case PERIPH_ID_UART2:
> diff --git a/arch/arm/include/asm/arch-hi6220/hi6220.h b/arch/arm/include/asm/arch-hi6220/hi6220.h
> index 3a12c75..1b73f42 100644
> --- a/arch/arm/include/asm/arch-hi6220/hi6220.h
> +++ b/arch/arm/include/asm/arch-hi6220/hi6220.h
> @@ -19,6 +19,8 @@
>  #define HI6220_PMUSSI_BASE                     0xF8000000
>
>  #define HI6220_PERI_BASE                       0xF7030000
> +/*Hi6220V100_Multi-Mode_Application_Processor_Function_Description on p.5-45*/
> +#define HI6220_SPI_BASE                                0xF7106000
>
>  struct peri_sc_periph_regs {
>         u32 ctrl1;              /*0x0*/
> diff --git a/arch/arm/include/asm/arch-hi6220/periph.h b/arch/arm/include/asm/arch-hi6220/periph.h
> index 7155f60..b58a0f7 100644
> --- a/arch/arm/include/asm/arch-hi6220/periph.h
> +++ b/arch/arm/include/asm/arch-hi6220/periph.h
> @@ -25,6 +25,8 @@ enum periph_id {
>         PERIPH_ID_SDMMC1,
>
>         PERIPH_ID_NONE = -1,
> +       PERIPH_ID_SPI0,
> +       PERIPH_ID_SPI1,
>  };
>
>  #endif /* __ASM_ARM_ARCH_PERIPH_H */
> diff --git a/board/hisilicon/hikey/hikey.c b/board/hisilicon/hikey/hikey.c
> index 72d6334..e90ea74 100644
> --- a/board/hisilicon/hikey/hikey.c
> +++ b/board/hisilicon/hikey/hikey.c
> @@ -21,6 +21,10 @@
>  #include <asm/arch/hi6220.h>
>  #include <asm/armv8/mmu.h>
>
> +#ifdef CONFIG_PL022_SPI
> +#include <spi.h>
> +#endif
> +
>  /*TODO drop this table in favour of device tree */
>  static const struct hikey_gpio_platdata hi6220_gpio[] = {
>         { 0, HI6220_GPIO_BASE(0)},
> @@ -335,9 +339,46 @@ int misc_init_r(void)
>  {
>         return 0;
>  }
> +#ifdef CONFIG_PL022_SPI
> +int spi_cs_is_valid(unsigned int bus, unsigned int cs)
> +{
> +       return bus == 0 && cs == 0;
> +}
> +
> +void spi_cs_activate(struct spi_slave *slave)
> +{
> +//     at91_set_pio_output(AT91_PIO_PORTC, 3, 0);
> +       gpio_request(0, "PWR_HOLD_GPIO0_0");
> +       gpio_direction_output(0, 1);
> +}
> +
> +void spi_cs_deactivate(struct spi_slave *slave)
> +{
> +//     at91_set_pio_output(AT91_PIO_PORTC, 3, 1);
> +       gpio_request(0, "PWR_HOLD_GPIO0_0");
> +       gpio_direction_output(0, 1);
> +}
> +
> +static void hikey_spi0_hw_init(void)
> +{
> +       hi6220_pinmux_config(PERIPH_ID_SPI0);
> +//     at91_set_pio_output(AT91_PIO_PORTC, 3, 1);      /* SPI0_CS0 */
> +       gpio_request(0, "PWR_HOLD_GPIO0_0");
> +       gpio_direction_output(0, 1);
> +
> +       /* Enable clock */
> +//     at91_periph_clk_enable(ATMEL_ID_SPI0);
> +/* from Kernel { HI6220_SPI_CLK, "spi_clk", "clk_150m", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x230, 9,  0, }, */
> +//     hi6220_clk_enable(PERI_CLK0_SPI0, &peri_sc->clk3_en);
> +
> +}
> +#endif /* CONFIG_PL022_SPI */
>
>  int board_init(void)
>  {
> +#ifdef CONFIG_PL022_SPI
> +       hikey_spi0_hw_init();
> +#endif
>         return 0;
>  }
>
> diff --git a/drivers/spi/Makefile b/drivers/spi/Makefile
> index b1d9e20..a509d93 100644
> --- a/drivers/spi/Makefile
> +++ b/drivers/spi/Makefile
> @@ -6,6 +6,8 @@
>  #
>
>  # There are many options which enable SPI, so make this library available
> +obj-$(CONFIG_PL022_SPI) += pl022_spi.o
> +
>  ifdef CONFIG_DM_SPI
>  obj-y += spi-uclass.o
>  obj-$(CONFIG_SANDBOX) += spi-emul-uclass.o
> diff --git a/drivers/spi/pl022_spi.c b/drivers/spi/pl022_spi.c
> index e69de29..e80fed3 100644
> --- a/drivers/spi/pl022_spi.c
> +++ b/drivers/spi/pl022_spi.c
> @@ -0,0 +1,321 @@
> +/*
> + * (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
> + */
> +/* Comment by Jagan: Use latest SPDX-License-Identifier: >> check for any existing one. */
> +
> +#include <common.h>
> +#include <malloc.h>
> +#include <spi.h>
> +#include <asm/io.h>
> +//#include <asm/arch/hardware.h>
> +
> +/* SSP registers mapping */
> +/* Comment by Jagan: Something like pl022_spi_regs*/
> +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 */
> +};
> +
> +/* Comment by Jagan: -- TAG+*/
> +/* 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 */
> +
> +/* Comment by Jagan: --- TAG -*/
> +/* Comment by Jagan:
> + * 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.
> + */
> +struct pl022_spi_slave {
> +       struct spi_slave slave;
> +       void *regs;
> +/* Comment by Jagan: Please use the structure pointer instead of void. */
> +
> +       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;
> +}
> diff --git a/include/configs/hikey.h b/include/configs/hikey.h
> index ffcc4d2..5ac8997 100644
> --- a/include/configs/hikey.h
> +++ b/include/configs/hikey.h
> @@ -76,6 +76,24 @@
>
>  #define CONFIG_HIKEY_GPIO
>
> +/* Synchronous Serial Port PL022 for SPI */
> +#define CONFIG_PL022_SPI
> +
> +/* SPI Configuration */
> +#define CONFIG_SYS_SPI_BASE            0xF7106000
> +//#define CONFIG_DAVINCI_SPI
> +//#define CONFIG_SYS_SPI_CLK           clk_get_rate(KS2_CLK1_6)
> +//#define CONFIG_SYS_SPI_CLK           24000000
> +//#define CONFIG_SYS_SPI_CLK           83000000
> +#define CONFIG_SYS_SPI_CLK             121000000
> +//#define CONFIG_SF_DEFAULT_SPEED              30000000
> +//#define CONFIG_ENV_SPI_MAX_HZ                CONFIG_SF_DEFAULT_SPEED
> +#ifdef CONFIG_SPL_BUILD
> +#undef CONFIG_DM_SPI
> +#undef CONFIG_DM_SPI_FLASH
> +#endif
> +
> +
>
>
>
>
> Am Mittwoch, September 14, 2016 16:39 CEST, Armando Visconti <armando.visconti@st.com> schrieb:
>
>> Ciao Michael,
>>
>> On 09/08/2016 04:21 PM, Michael Brandl wrote:
>>> Dear U-Boot (SPI) Developers,
>>>
>>> this patch seems to be my only chance to get spi working without/before Linux.
>>
>> I wrote and used this code for u-boot for a asic
>> specified by one of our customers. The patch was generic
>> enough to be pushed in u-boot, but I didn't have
>> much time to test it on a different, more generic
>> platform. So the maintainer decided to drop it...
>>
>> Would be nice if you could work on it and resurrect it...
>> :)
>>
>> Let me know if you have progressed on this or abandoned it.
>>
>>>
>>> I'm a student from Augsburg (Germany) experimenting with the Hikey Board from 96boards.
>>> The hi6220 processor from HiSilicon isn't fully documented, there is just one document called Function Description:
>>> http://mirror.lemaker.org/Hi6220V100_Multi-Mode_Application_Processor_Function_Description.pdf
>>>
>>
>> Yes, I'm currently using HiKey platform for doing my day by day
>> job here in office. Nevertheless, I don't think I have enough
>> time to take a look into testing this commit.
>>
>>> U-Boot already supports the Hikey Board to be loaded from ARM Trusted Firmware (ATF) but only UART and SDMMC is supported by now.
>>> I cloned the u-boot-spi.git and tried to integrate this patch but I'm not experienced enough to adjust the specific config for the Hikey Board.
>>>
>>
>> Maybe I can try to recover the work that was done to integrate
>> this commit into the customer platform I was talking about.
>> I'll take a look into it right now...
>>
>>> Taking a look at armv7 devices with spi support I started like this:
>>>
>>> +++ b/arch/arm/include/asm/arch-hi6220/hi6220.h
>>>
>>> +/*Hi6220V100_Multi-Mode_Application_Processor_Function_Description on p.5-45*/
>>> +#define HI6220_SPI_BASE                            0xF7106000
>>>
>>>
>>> +++ b/include/configs/hikey.h
>>>
>>> +/* Synchronous Serial Port PL022 for SPI */
>>> +#define CONFIG_PL022_SPI
>>>
>>>
>>> +++ b/board/hisilicon/hikey/hikey.c
>>>
>>>  int board_init(void)
>>>  {
>>> +#ifdef CONFIG_PL022_SPI
>>> +   hikey_spi0_hw_init();
>>> +#endif
>>>     return 0;
>>>  }
>>>
>>>
>>> +static void hikey_spi0_hw_init(void)
>>> +{
>>> +   hi6220_pinmux_config(PERIPH_ID_SPI0)
>>> +// at91_set_pio_output(AT91_PIO_PORTC, 3, 1);      /* SPI0_CS0 */
>>> +   gpio_request(0, "PWR_HOLD_GPIO0_0");
>>> +   gpio_direction_output(0, 1);
>>> +
>>> +   /* Enable clock */
>>> +// at91_periph_clk_enable(ATMEL_ID_SPI0);
>>> +/* from Kernel     { HI6220_SPI_CLK, "spi_clk", "clk_150m", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x230, 9,  0, }, */
>>> +   hi6220_clk_enable(PERI_CLK0_SPI0, &peri_sc->clk3_en);
>>> +
>>> +}
>>> +#endif /* CONFIG_PL022_SPI */
>>> +
>>>
>>>
>>> +++ b/arch/arm/cpu/armv8/hisilicon/pinmux.c
>>>
>>> +static void hi6220_spi_config(int peripheral)
>>> +{
>>> +   switch (peripheral) {
>>> +   case PERIPH_ID_SPI0:
>>> +//         at91_set_a_periph(AT91_PIO_PORTC, 0, 0);        /* SPI0_MISO */
>>> +//         at91_set_a_periph(AT91_PIO_PORTC, 1, 0);        /* SPI0_MOSI */
>>> +//         at91_set_a_periph(AT91_PIO_PORTC, 2, 0);        /* SPI0_SPCK */
>>> +           break;
>>> +
>>> +   case PERIPH_ID_SPI1:
>>> +           break;
>>> +
>>> +   default:
>>> +           debug("%s: invalid peripheral %d", __func__, peripheral);
>>> +           return;
>>> +   }
>>> +}
>>>
>>> Maybe you can help me to get spi working on Hikey. My overall aim is to port the pl022 driver then to ARM TF ... maybe also that could be interessing for you.
>>>
>>> With kind Regards,
>>> Michael Brandl
>>>
>>>
>>>
>>>
>>
>> Rgds,
>> Armando
>>
>

^ permalink raw reply	[flat|nested] 20+ messages in thread

* [U-Boot] [PATCH v6] spi: pl022_spi: Add support for ARM PL022 spi controller
  2016-09-19 14:14     ` [U-Boot] [PATCH v6] spi: " Armando Visconti
@ 2016-09-20  6:25       ` Michael Brandl
  0 siblings, 0 replies; 20+ messages in thread
From: Michael Brandl @ 2016-09-20  6:25 UTC (permalink / raw)
  To: u-boot

No sry,

ports are not configured yet and I don't know which clock to use. I just 
created the structure looking on other implementations.

That's what I neeed your help for!

Michael


On 19.09.2016 16:14, Armando Visconti wrote:
> Ciao Michael,
>
> Did you test it?
> It seems that all the platform related changes (pinmux, board file,
> ...) are there.
>
> Pls let us know,
> Armando
>
> On 09/19/2016 01:59 PM, Michael Brandl wrote:
>> Ciao Armando,
>> Hi Jagan,
>>
>> On Friday I found another driver implementation already on my 
>> desktop, by grepping for pl022 in the upper level ../, but it is more 
>> general and not easy to understand. But maybe it helps us to find the 
>> information we need.
>>
>> This is how I started! Now as patchset based on u-boot-spi.git:
>>
>>
>> diff --git a/arch/arm/cpu/armv8/hisilicon/pinmux.c 
>> b/arch/arm/cpu/armv8/hisilicon/pinmux.c
>> index 3e4c9ce..83f02db 100644
>> --- a/arch/arm/cpu/armv8/hisilicon/pinmux.c
>> +++ b/arch/arm/cpu/armv8/hisilicon/pinmux.c
>> @@ -17,6 +17,24 @@ struct hi6220_pinmux0_regs *pmx0 =
>>  struct hi6220_pinmux1_regs *pmx1 =
>>         (struct hi6220_pinmux1_regs *)HI6220_PINMUX1_BASE;
>>
>> +static void hi6220_spi_config(int peripheral)
>> +{
>> +       switch (peripheral) {
>> +       case PERIPH_ID_SPI0:
>> +//             at91_set_a_periph(AT91_PIO_PORTC, 0, 0); /* SPI0_MISO */
>> +//             at91_set_a_periph(AT91_PIO_PORTC, 1, 0); /* SPI0_MOSI */
>> +//             at91_set_a_periph(AT91_PIO_PORTC, 2, 0); /* SPI0_SPCK */
>> +               break;
>> +
>> +       case PERIPH_ID_SPI1:
>> +               break;
>> +
>> +       default:
>> +               debug("%s: invalid peripheral %d", __func__, 
>> peripheral);
>> +               return;
>> +       }
>> +}
>> +
>>  static void hi6220_uart_config(int peripheral)
>>  {
>>         switch (peripheral) {
>> @@ -164,6 +182,9 @@ static int hi6220_mmc_config(int peripheral)
>>  int hi6220_pinmux_config(int peripheral)
>>  {
>>         switch (peripheral) {
>> +       case PERIPH_ID_SPI0:
>> +               hi6220_spi_config(peripheral);
>> +               break;
>>         case PERIPH_ID_UART0:
>>         case PERIPH_ID_UART1:
>>         case PERIPH_ID_UART2:
>> diff --git a/arch/arm/include/asm/arch-hi6220/hi6220.h 
>> b/arch/arm/include/asm/arch-hi6220/hi6220.h
>> index 3a12c75..1b73f42 100644
>> --- a/arch/arm/include/asm/arch-hi6220/hi6220.h
>> +++ b/arch/arm/include/asm/arch-hi6220/hi6220.h
>> @@ -19,6 +19,8 @@
>>  #define HI6220_PMUSSI_BASE                     0xF8000000
>>
>>  #define HI6220_PERI_BASE                       0xF7030000
>> +/*Hi6220V100_Multi-Mode_Application_Processor_Function_Description 
>> on p.5-45*/
>> +#define HI6220_SPI_BASE 0xF7106000
>>
>>  struct peri_sc_periph_regs {
>>         u32 ctrl1;              /*0x0*/
>> diff --git a/arch/arm/include/asm/arch-hi6220/periph.h 
>> b/arch/arm/include/asm/arch-hi6220/periph.h
>> index 7155f60..b58a0f7 100644
>> --- a/arch/arm/include/asm/arch-hi6220/periph.h
>> +++ b/arch/arm/include/asm/arch-hi6220/periph.h
>> @@ -25,6 +25,8 @@ enum periph_id {
>>         PERIPH_ID_SDMMC1,
>>
>>         PERIPH_ID_NONE = -1,
>> +       PERIPH_ID_SPI0,
>> +       PERIPH_ID_SPI1,
>>  };
>>
>>  #endif /* __ASM_ARM_ARCH_PERIPH_H */
>> diff --git a/board/hisilicon/hikey/hikey.c 
>> b/board/hisilicon/hikey/hikey.c
>> index 72d6334..e90ea74 100644
>> --- a/board/hisilicon/hikey/hikey.c
>> +++ b/board/hisilicon/hikey/hikey.c
>> @@ -21,6 +21,10 @@
>>  #include <asm/arch/hi6220.h>
>>  #include <asm/armv8/mmu.h>
>>
>> +#ifdef CONFIG_PL022_SPI
>> +#include <spi.h>
>> +#endif
>> +
>>  /*TODO drop this table in favour of device tree */
>>  static const struct hikey_gpio_platdata hi6220_gpio[] = {
>>         { 0, HI6220_GPIO_BASE(0)},
>> @@ -335,9 +339,46 @@ int misc_init_r(void)
>>  {
>>         return 0;
>>  }
>> +#ifdef CONFIG_PL022_SPI
>> +int spi_cs_is_valid(unsigned int bus, unsigned int cs)
>> +{
>> +       return bus == 0 && cs == 0;
>> +}
>> +
>> +void spi_cs_activate(struct spi_slave *slave)
>> +{
>> +//     at91_set_pio_output(AT91_PIO_PORTC, 3, 0);
>> +       gpio_request(0, "PWR_HOLD_GPIO0_0");
>> +       gpio_direction_output(0, 1);
>> +}
>> +
>> +void spi_cs_deactivate(struct spi_slave *slave)
>> +{
>> +//     at91_set_pio_output(AT91_PIO_PORTC, 3, 1);
>> +       gpio_request(0, "PWR_HOLD_GPIO0_0");
>> +       gpio_direction_output(0, 1);
>> +}
>> +
>> +static void hikey_spi0_hw_init(void)
>> +{
>> +       hi6220_pinmux_config(PERIPH_ID_SPI0);
>> +//     at91_set_pio_output(AT91_PIO_PORTC, 3, 1);      /* SPI0_CS0 */
>> +       gpio_request(0, "PWR_HOLD_GPIO0_0");
>> +       gpio_direction_output(0, 1);
>> +
>> +       /* Enable clock */
>> +//     at91_periph_clk_enable(ATMEL_ID_SPI0);
>> +/* from Kernel { HI6220_SPI_CLK, "spi_clk", "clk_150m", 
>> CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x230, 9,  0, }, */
>> +//     hi6220_clk_enable(PERI_CLK0_SPI0, &peri_sc->clk3_en);
>> +
>> +}
>> +#endif /* CONFIG_PL022_SPI */
>>
>>  int board_init(void)
>>  {
>> +#ifdef CONFIG_PL022_SPI
>> +       hikey_spi0_hw_init();
>> +#endif
>>         return 0;
>>  }
>>
>> diff --git a/drivers/spi/Makefile b/drivers/spi/Makefile
>> index b1d9e20..a509d93 100644
>> --- a/drivers/spi/Makefile
>> +++ b/drivers/spi/Makefile
>> @@ -6,6 +6,8 @@
>>  #
>>
>>  # There are many options which enable SPI, so make this library 
>> available
>> +obj-$(CONFIG_PL022_SPI) += pl022_spi.o
>> +
>>  ifdef CONFIG_DM_SPI
>>  obj-y += spi-uclass.o
>>  obj-$(CONFIG_SANDBOX) += spi-emul-uclass.o
>> diff --git a/drivers/spi/pl022_spi.c b/drivers/spi/pl022_spi.c
>> index e69de29..e80fed3 100644
>> --- a/drivers/spi/pl022_spi.c
>> +++ b/drivers/spi/pl022_spi.c
>> @@ -0,0 +1,321 @@
>> +/*
>> + * (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
>> + */
>> +/* Comment by Jagan: Use latest SPDX-License-Identifier: >> check 
>> for any existing one. */
>> +
>> +#include <common.h>
>> +#include <malloc.h>
>> +#include <spi.h>
>> +#include <asm/io.h>
>> +//#include <asm/arch/hardware.h>
>> +
>> +/* SSP registers mapping */
>> +/* Comment by Jagan: Something like pl022_spi_regs*/
>> +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 */
>> +};
>> +
>> +/* Comment by Jagan: -- TAG+*/
>> +/* 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 */
>> +
>> +/* Comment by Jagan: --- TAG -*/
>> +/* Comment by Jagan:
>> + * 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.
>> + */
>> +struct pl022_spi_slave {
>> +       struct spi_slave slave;
>> +       void *regs;
>> +/* Comment by Jagan: Please use the structure pointer instead of 
>> void. */
>> +
>> +       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;
>> +}
>> diff --git a/include/configs/hikey.h b/include/configs/hikey.h
>> index ffcc4d2..5ac8997 100644
>> --- a/include/configs/hikey.h
>> +++ b/include/configs/hikey.h
>> @@ -76,6 +76,24 @@
>>
>>  #define CONFIG_HIKEY_GPIO
>>
>> +/* Synchronous Serial Port PL022 for SPI */
>> +#define CONFIG_PL022_SPI
>> +
>> +/* SPI Configuration */
>> +#define CONFIG_SYS_SPI_BASE            0xF7106000
>> +//#define CONFIG_DAVINCI_SPI
>> +//#define CONFIG_SYS_SPI_CLK           clk_get_rate(KS2_CLK1_6)
>> +//#define CONFIG_SYS_SPI_CLK           24000000
>> +//#define CONFIG_SYS_SPI_CLK           83000000
>> +#define CONFIG_SYS_SPI_CLK             121000000
>> +//#define CONFIG_SF_DEFAULT_SPEED              30000000
>> +//#define CONFIG_ENV_SPI_MAX_HZ CONFIG_SF_DEFAULT_SPEED
>> +#ifdef CONFIG_SPL_BUILD
>> +#undef CONFIG_DM_SPI
>> +#undef CONFIG_DM_SPI_FLASH
>> +#endif
>> +
>> +
>>
>>
>>
>>
>> Am Mittwoch, September 14, 2016 16:39 CEST, Armando Visconti 
>> <armando.visconti@st.com> schrieb:
>>
>>> Ciao Michael,
>>>
>>> On 09/08/2016 04:21 PM, Michael Brandl wrote:
>>>> Dear U-Boot (SPI) Developers,
>>>>
>>>> this patch seems to be my only chance to get spi working 
>>>> without/before Linux.
>>>
>>> I wrote and used this code for u-boot for a asic
>>> specified by one of our customers. The patch was generic
>>> enough to be pushed in u-boot, but I didn't have
>>> much time to test it on a different, more generic
>>> platform. So the maintainer decided to drop it...
>>>
>>> Would be nice if you could work on it and resurrect it...
>>> :)
>>>
>>> Let me know if you have progressed on this or abandoned it.
>>>
>>>>
>>>> I'm a student from Augsburg (Germany) experimenting with the Hikey 
>>>> Board from 96boards.
>>>> The hi6220 processor from HiSilicon isn't fully documented, there 
>>>> is just one document called Function Description:
>>>> http://mirror.lemaker.org/Hi6220V100_Multi-Mode_Application_Processor_Function_Description.pdf 
>>>>
>>>>
>>>
>>> Yes, I'm currently using HiKey platform for doing my day by day
>>> job here in office. Nevertheless, I don't think I have enough
>>> time to take a look into testing this commit.
>>>
>>>> U-Boot already supports the Hikey Board to be loaded from ARM 
>>>> Trusted Firmware (ATF) but only UART and SDMMC is supported by now.
>>>> I cloned the u-boot-spi.git and tried to integrate this patch but 
>>>> I'm not experienced enough to adjust the specific config for the 
>>>> Hikey Board.
>>>>
>>>
>>> Maybe I can try to recover the work that was done to integrate
>>> this commit into the customer platform I was talking about.
>>> I'll take a look into it right now...
>>>
>>>> Taking a look at armv7 devices with spi support I started like this:
>>>>
>>>> +++ b/arch/arm/include/asm/arch-hi6220/hi6220.h
>>>>
>>>> +/*Hi6220V100_Multi-Mode_Application_Processor_Function_Description 
>>>> on p.5-45*/
>>>> +#define HI6220_SPI_BASE 0xF7106000
>>>>
>>>>
>>>> +++ b/include/configs/hikey.h
>>>>
>>>> +/* Synchronous Serial Port PL022 for SPI */
>>>> +#define CONFIG_PL022_SPI
>>>>
>>>>
>>>> +++ b/board/hisilicon/hikey/hikey.c
>>>>
>>>>  int board_init(void)
>>>>  {
>>>> +#ifdef CONFIG_PL022_SPI
>>>> +   hikey_spi0_hw_init();
>>>> +#endif
>>>>     return 0;
>>>>  }
>>>>
>>>>
>>>> +static void hikey_spi0_hw_init(void)
>>>> +{
>>>> +   hi6220_pinmux_config(PERIPH_ID_SPI0)
>>>> +// at91_set_pio_output(AT91_PIO_PORTC, 3, 1);      /* SPI0_CS0 */
>>>> +   gpio_request(0, "PWR_HOLD_GPIO0_0");
>>>> +   gpio_direction_output(0, 1);
>>>> +
>>>> +   /* Enable clock */
>>>> +// at91_periph_clk_enable(ATMEL_ID_SPI0);
>>>> +/* from Kernel     { HI6220_SPI_CLK, "spi_clk", "clk_150m", 
>>>> CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x230, 9,  0, }, */
>>>> +   hi6220_clk_enable(PERI_CLK0_SPI0, &peri_sc->clk3_en);
>>>> +
>>>> +}
>>>> +#endif /* CONFIG_PL022_SPI */
>>>> +
>>>>
>>>>
>>>> +++ b/arch/arm/cpu/armv8/hisilicon/pinmux.c
>>>>
>>>> +static void hi6220_spi_config(int peripheral)
>>>> +{
>>>> +   switch (peripheral) {
>>>> +   case PERIPH_ID_SPI0:
>>>> +//         at91_set_a_periph(AT91_PIO_PORTC, 0, 0); /* SPI0_MISO */
>>>> +//         at91_set_a_periph(AT91_PIO_PORTC, 1, 0); /* SPI0_MOSI */
>>>> +//         at91_set_a_periph(AT91_PIO_PORTC, 2, 0); /* SPI0_SPCK */
>>>> +           break;
>>>> +
>>>> +   case PERIPH_ID_SPI1:
>>>> +           break;
>>>> +
>>>> +   default:
>>>> +           debug("%s: invalid peripheral %d", __func__, peripheral);
>>>> +           return;
>>>> +   }
>>>> +}
>>>>
>>>> Maybe you can help me to get spi working on Hikey. My overall aim 
>>>> is to port the pl022 driver then to ARM TF ... maybe also that 
>>>> could be interessing for you.
>>>>
>>>> With kind Regards,
>>>> Michael Brandl
>>>>
>>>>
>>>>
>>>>
>>>
>>> Rgds,
>>> Armando
>>>
>>

^ permalink raw reply	[flat|nested] 20+ messages in thread

* [U-Boot] [PATCH v6] spi: pl022_spi: Add support for ARM PL022 spi controller
  2014-01-08  9:19       ` Armando Visconti
@ 2014-01-08 10:30         ` Jagan Teki
  0 siblings, 0 replies; 20+ messages in thread
From: Jagan Teki @ 2014-01-08 10:30 UTC (permalink / raw)
  To: u-boot

On Wed, Jan 8, 2014 at 2:49 PM, Armando Visconti
<armando.visconti@st.com> wrote:
> Hello Jagan,
>
> Sorry for late reply.
>
>
>
> On 12/20/2013 8:03 PM, Jagan Teki wrote:
>>
>> On Fri, Oct 4, 2013 at 12:20 PM, Jagan Teki <jagannadh.teki@gmail.com>
>> wrote:
>>>
>>> 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.
>>>
>>> On Wed, Jun 12, 2013 at 7:55 PM, Jagan Teki <jagannadh.teki@gmail.com>
>>> wrote:
>>>>
>>>> Thanks for v6 sent.
>>>>
>>>> Have you tested this?
>>>> on which board, include/configs/*.h file?
>>>>
>>>> --
>>>> Thanks,
>>>> Jagan.
>>>>
>>>> On Wed, Jun 12, 2013 at 6:17 PM, Armando Visconti
>>>> <armando.visconti@st.com> wrote:
>>>>>
>>>>> 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.
>>>>>
>>>>> Signed-off-by: Armando Visconti <armando.visconti@st.com>
>>>>> Signed-off-by: Vipin Kumar <vipin.kumar@st.com>
>>>>> Acked-by: Stefan Roese <sr@denx.de>
>>>>> ---
>>>>> 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
>>>>>
>>>>> diff --git a/drivers/spi/Makefile b/drivers/spi/Makefile
>>>>> index d08609e..b6443b1 100644
>>>>> --- a/drivers/spi/Makefile
>>>>> +++ b/drivers/spi/Makefile
>>>>> @@ -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
>>>>> diff --git a/drivers/spi/pl022_spi.c b/drivers/spi/pl022_spi.c
>>>>> new file mode 100644
>>>>> index 0000000..5b47413
>>>>> --- /dev/null
>>>>> +++ b/drivers/spi/pl022_spi.c
>>>>> @@ -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
>>>>> + */
>>>
>>> Use latest SPDX-License-Identifier:
>>> check for any existing one.
>>>
>>>>> +
>>>>> +#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
>>>
>>>>> +       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 */
>>>>> +};
>>>>> +
>>>
>>> -- TAG+
>>>>>
>>>>> +/* 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 */
>>>>> +
>>>
>>> --- 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.
>>>
>>>>> +struct pl022_spi_slave {
>>>>> +       struct spi_slave slave;
>>>>> +       void *regs;
>>>
>>> Please use the structure pointer instead of void.
>>>
>>>>> +       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
>>
>> 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.

Thanks,

--
Jagan.

^ permalink raw reply	[flat|nested] 20+ messages in thread

* [U-Boot] [PATCH v6] spi: pl022_spi: Add support for ARM PL022 spi controller
  2013-12-20 19:03     ` Jagan Teki
@ 2014-01-08  9:19       ` Armando Visconti
  2014-01-08 10:30         ` Jagan Teki
  0 siblings, 1 reply; 20+ messages in thread
From: Armando Visconti @ 2014-01-08  9:19 UTC (permalink / raw)
  To: u-boot

Hello Jagan,

Sorry for late reply.


On 12/20/2013 8:03 PM, Jagan Teki wrote:
> On Fri, Oct 4, 2013 at 12:20 PM, Jagan Teki <jagannadh.teki@gmail.com> wrote:
>> 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.
>>
>> On Wed, Jun 12, 2013 at 7:55 PM, Jagan Teki <jagannadh.teki@gmail.com> wrote:
>>> Thanks for v6 sent.
>>>
>>> Have you tested this?
>>> on which board, include/configs/*.h file?
>>>
>>> --
>>> Thanks,
>>> Jagan.
>>>
>>> On Wed, Jun 12, 2013 at 6:17 PM, Armando Visconti
>>> <armando.visconti@st.com> wrote:
>>>> 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.
>>>>
>>>> Signed-off-by: Armando Visconti <armando.visconti@st.com>
>>>> Signed-off-by: Vipin Kumar <vipin.kumar@st.com>
>>>> Acked-by: Stefan Roese <sr@denx.de>
>>>> ---
>>>> 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
>>>>
>>>> diff --git a/drivers/spi/Makefile b/drivers/spi/Makefile
>>>> index d08609e..b6443b1 100644
>>>> --- a/drivers/spi/Makefile
>>>> +++ b/drivers/spi/Makefile
>>>> @@ -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
>>>> diff --git a/drivers/spi/pl022_spi.c b/drivers/spi/pl022_spi.c
>>>> new file mode 100644
>>>> index 0000000..5b47413
>>>> --- /dev/null
>>>> +++ b/drivers/spi/pl022_spi.c
>>>> @@ -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
>>>> + */
>> Use latest SPDX-License-Identifier:
>> check for any existing one.
>>
>>>> +
>>>> +#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
>>
>>>> +       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 */
>>>> +};
>>>> +
>> -- TAG+
>>>> +/* 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 */
>>>> +
>> --- 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.
>>
>>>> +struct pl022_spi_slave {
>>>> +       struct spi_slave slave;
>>>> +       void *regs;
>> Please use the structure pointer instead of void.
>>
>>>> +       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
> 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

-- 
-- "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
                                     
  

^ permalink raw reply	[flat|nested] 20+ messages in thread

* [U-Boot] [PATCH v6] spi: pl022_spi: Add support for ARM PL022 spi controller
  2013-10-04  6:50   ` Jagan Teki
@ 2013-12-20 19:03     ` Jagan Teki
  2014-01-08  9:19       ` Armando Visconti
  0 siblings, 1 reply; 20+ messages in thread
From: Jagan Teki @ 2013-12-20 19:03 UTC (permalink / raw)
  To: u-boot

On Fri, Oct 4, 2013 at 12:20 PM, Jagan Teki <jagannadh.teki@gmail.com> wrote:
> 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.
>
> On Wed, Jun 12, 2013 at 7:55 PM, Jagan Teki <jagannadh.teki@gmail.com> wrote:
>> Thanks for v6 sent.
>>
>> Have you tested this?
>> on which board, include/configs/*.h file?
>>
>> --
>> Thanks,
>> Jagan.
>>
>> On Wed, Jun 12, 2013 at 6:17 PM, Armando Visconti
>> <armando.visconti@st.com> wrote:
>>> 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.
>>>
>>> Signed-off-by: Armando Visconti <armando.visconti@st.com>
>>> Signed-off-by: Vipin Kumar <vipin.kumar@st.com>
>>> Acked-by: Stefan Roese <sr@denx.de>
>>> ---
>>> 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
>>>
>>> diff --git a/drivers/spi/Makefile b/drivers/spi/Makefile
>>> index d08609e..b6443b1 100644
>>> --- a/drivers/spi/Makefile
>>> +++ b/drivers/spi/Makefile
>>> @@ -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
>>> diff --git a/drivers/spi/pl022_spi.c b/drivers/spi/pl022_spi.c
>>> new file mode 100644
>>> index 0000000..5b47413
>>> --- /dev/null
>>> +++ b/drivers/spi/pl022_spi.c
>>> @@ -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
>>> + */
> Use latest SPDX-License-Identifier:
> check for any existing one.
>
>>> +
>>> +#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
>
>>> +       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 */
>>> +};
>>> +
>
> -- TAG+
>>> +/* 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 */
>>> +
> --- 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.
>
>>> +struct pl022_spi_slave {
>>> +       struct spi_slave slave;
>>> +       void *regs;
>
> Please use the structure pointer instead of void.
>
>>> +       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
Ping

^ permalink raw reply	[flat|nested] 20+ messages in thread

* [U-Boot] [PATCH v6] spi: pl022_spi: Add support for ARM PL022 spi controller
  2013-06-12 14:25 ` Jagan Teki
  2013-06-12 15:07   ` Armando Visconti
@ 2013-10-04  6:50   ` Jagan Teki
  2013-12-20 19:03     ` Jagan Teki
  1 sibling, 1 reply; 20+ messages in thread
From: Jagan Teki @ 2013-10-04  6:50 UTC (permalink / raw)
  To: u-boot

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.

On Wed, Jun 12, 2013 at 7:55 PM, Jagan Teki <jagannadh.teki@gmail.com> wrote:
> Thanks for v6 sent.
>
> Have you tested this?
> on which board, include/configs/*.h file?
>
> --
> Thanks,
> Jagan.
>
> On Wed, Jun 12, 2013 at 6:17 PM, Armando Visconti
> <armando.visconti@st.com> wrote:
>> 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.
>>
>> Signed-off-by: Armando Visconti <armando.visconti@st.com>
>> Signed-off-by: Vipin Kumar <vipin.kumar@st.com>
>> Acked-by: Stefan Roese <sr@denx.de>
>> ---
>> 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
>>
>> diff --git a/drivers/spi/Makefile b/drivers/spi/Makefile
>> index d08609e..b6443b1 100644
>> --- a/drivers/spi/Makefile
>> +++ b/drivers/spi/Makefile
>> @@ -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
>> diff --git a/drivers/spi/pl022_spi.c b/drivers/spi/pl022_spi.c
>> new file mode 100644
>> index 0000000..5b47413
>> --- /dev/null
>> +++ b/drivers/spi/pl022_spi.c
>> @@ -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
>> + */
Use latest SPDX-License-Identifier:
check for any existing one.

>> +
>> +#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

>> +       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 */
>> +};
>> +

-- TAG+
>> +/* 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 */
>> +
--- 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.

>> +struct pl022_spi_slave {
>> +       struct spi_slave slave;
>> +       void *regs;

Please use the structure pointer instead of void.

>> +       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
>>

-- 
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

^ permalink raw reply	[flat|nested] 20+ messages in thread

* [U-Boot] [PATCH v6] spi: pl022_spi: Add support for ARM PL022 spi controller
  2013-10-04  6:02               ` Jagan Teki
@ 2013-10-04  6:27                 ` Vipin Kumar
  0 siblings, 0 replies; 20+ messages in thread
From: Vipin Kumar @ 2013-10-04  6:27 UTC (permalink / raw)
  To: u-boot

On 10/4/2013 11:32 AM, Jagan Teki wrote:
> 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

> On Fri, Oct 4, 2013 at 9:40 AM, Vipin Kumar<vipin.kumar@st.com>  wrote:
>> On 10/4/2013 1:22 AM, Jagan Teki wrote:
>>>
>>> Any update on this.
>>>
>>
>> This should already be in u-boot mainline
>>
>> Regards
>> Vipin
>>
>>> On Wed, Jun 12, 2013 at 9:25 PM, Armando Visconti
>>> <armando.visconti@st.com>   wrote:
>>>>
>>>> On 06/12/2013 05:29 PM, Jagan Teki wrote:
>>>>>
>>>>>
>>>>> On Wed, Jun 12, 2013 at 8:49 PM, Armando Visconti
>>>>> <armando.visconti@st.com>   wrote:
>>>>>>>
>>>>>>>
>>>>>>>
>>>>>>> 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
>>>>>
>>>>>
>>>>>
>>>>> 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):
>>>>
>>>>> diff --git a/include/configs/spear3xx_evb.h
>>>>> b/include/configs/spear3xx_evb.h
>>>>> index 3cd56dc..03a046e 100644
>>>>> --- a/include/configs/spear3xx_evb.h
>>>>> +++ b/include/configs/spear3xx_evb.h
>>>>> @@ -54,6 +54,11 @@
>>>>>    /* Ethernet driver configuration */
>>>>>    #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
>>>>
>>>>
>>>>
>>>
>>>
>>>
>>
>
>
>

^ permalink raw reply	[flat|nested] 20+ messages in thread

* [U-Boot] [PATCH v6] spi: pl022_spi: Add support for ARM PL022 spi controller
  2013-10-04  4:10             ` Vipin Kumar
@ 2013-10-04  6:02               ` Jagan Teki
  2013-10-04  6:27                 ` Vipin Kumar
  0 siblings, 1 reply; 20+ messages in thread
From: Jagan Teki @ 2013-10-04  6:02 UTC (permalink / raw)
  To: u-boot

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

On Fri, Oct 4, 2013 at 9:40 AM, Vipin Kumar <vipin.kumar@st.com> wrote:
> On 10/4/2013 1:22 AM, Jagan Teki wrote:
>>
>> Any update on this.
>>
>
> This should already be in u-boot mainline
>
> Regards
> Vipin
>
>> On Wed, Jun 12, 2013 at 9:25 PM, Armando Visconti
>> <armando.visconti@st.com>  wrote:
>>>
>>> On 06/12/2013 05:29 PM, Jagan Teki wrote:
>>>>
>>>>
>>>> On Wed, Jun 12, 2013 at 8:49 PM, Armando Visconti
>>>> <armando.visconti@st.com>  wrote:
>>>>>>
>>>>>>
>>>>>>
>>>>>> 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
>>>>
>>>>
>>>>
>>>> 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):
>>>
>>>> diff --git a/include/configs/spear3xx_evb.h
>>>> b/include/configs/spear3xx_evb.h
>>>> index 3cd56dc..03a046e 100644
>>>> --- a/include/configs/spear3xx_evb.h
>>>> +++ b/include/configs/spear3xx_evb.h
>>>> @@ -54,6 +54,11 @@
>>>>   /* Ethernet driver configuration */
>>>>   #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
>>>
>>>
>>>
>>
>>
>>
>



-- 
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

^ permalink raw reply	[flat|nested] 20+ messages in thread

* [U-Boot] [PATCH v6] spi: pl022_spi: Add support for ARM PL022 spi controller
  2013-10-03 19:52           ` Jagan Teki
@ 2013-10-04  4:10             ` Vipin Kumar
  2013-10-04  6:02               ` Jagan Teki
  0 siblings, 1 reply; 20+ messages in thread
From: Vipin Kumar @ 2013-10-04  4:10 UTC (permalink / raw)
  To: u-boot

On 10/4/2013 1:22 AM, Jagan Teki wrote:
> Any update on this.
>

This should already be in u-boot mainline

Regards
Vipin

> On Wed, Jun 12, 2013 at 9:25 PM, Armando Visconti
> <armando.visconti@st.com>  wrote:
>> On 06/12/2013 05:29 PM, Jagan Teki wrote:
>>>
>>> On Wed, Jun 12, 2013 at 8:49 PM, Armando Visconti
>>> <armando.visconti@st.com>  wrote:
>>>>>
>>>>>
>>>>> 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
>>>
>>>
>>> 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):
>>
>>> diff --git a/include/configs/spear3xx_evb.h
>>> b/include/configs/spear3xx_evb.h
>>> index 3cd56dc..03a046e 100644
>>> --- a/include/configs/spear3xx_evb.h
>>> +++ b/include/configs/spear3xx_evb.h
>>> @@ -54,6 +54,11 @@
>>>   /* Ethernet driver configuration */
>>>   #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
>>
>>
>>
>
>
>

^ permalink raw reply	[flat|nested] 20+ messages in thread

* [U-Boot] [PATCH v6] spi: pl022_spi: Add support for ARM PL022 spi controller
  2013-06-12 15:55         ` Armando Visconti
@ 2013-10-03 19:52           ` Jagan Teki
  2013-10-04  4:10             ` Vipin Kumar
  0 siblings, 1 reply; 20+ messages in thread
From: Jagan Teki @ 2013-10-03 19:52 UTC (permalink / raw)
  To: u-boot

Any update on this.

On Wed, Jun 12, 2013 at 9:25 PM, Armando Visconti
<armando.visconti@st.com> wrote:
> On 06/12/2013 05:29 PM, Jagan Teki wrote:
>>
>> On Wed, Jun 12, 2013 at 8:49 PM, Armando Visconti
>> <armando.visconti@st.com> wrote:
>>>>
>>>>
>>>> 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
>>
>>
>> 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):
>
>> diff --git a/include/configs/spear3xx_evb.h
>> b/include/configs/spear3xx_evb.h
>> index 3cd56dc..03a046e 100644
>> --- a/include/configs/spear3xx_evb.h
>> +++ b/include/configs/spear3xx_evb.h
>> @@ -54,6 +54,11 @@
>>  /* Ethernet driver configuration */
>>  #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
>
>
>



-- 
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

^ permalink raw reply	[flat|nested] 20+ messages in thread

* [U-Boot] [PATCH v6] spi: pl022_spi: Add support for ARM PL022 spi controller
  2013-06-12 15:29       ` Jagan Teki
@ 2013-06-12 15:55         ` Armando Visconti
  2013-10-03 19:52           ` Jagan Teki
  0 siblings, 1 reply; 20+ messages in thread
From: Armando Visconti @ 2013-06-12 15:55 UTC (permalink / raw)
  To: u-boot

On 06/12/2013 05:29 PM, Jagan Teki wrote:
> On Wed, Jun 12, 2013 at 8:49 PM, Armando Visconti
> <armando.visconti@st.com> wrote:
>>>
>>> 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
>
> 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):

> diff --git a/include/configs/spear3xx_evb.h b/include/configs/spear3xx_evb.h
> index 3cd56dc..03a046e 100644
> --- a/include/configs/spear3xx_evb.h
> +++ b/include/configs/spear3xx_evb.h
> @@ -54,6 +54,11 @@
>  /* Ethernet driver configuration */
>  #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

^ permalink raw reply	[flat|nested] 20+ messages in thread

* [U-Boot] [PATCH v6] spi: pl022_spi: Add support for ARM PL022 spi controller
  2013-06-12 15:19     ` Armando Visconti
@ 2013-06-12 15:29       ` Jagan Teki
  2013-06-12 15:55         ` Armando Visconti
  0 siblings, 1 reply; 20+ messages in thread
From: Jagan Teki @ 2013-06-12 15:29 UTC (permalink / raw)
  To: u-boot

On Wed, Jun 12, 2013 at 8:49 PM, Armando Visconti
<armando.visconti@st.com> wrote:
>>
>> 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

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

--
Thanks,
Jagan.

^ permalink raw reply	[flat|nested] 20+ messages in thread

* [U-Boot] [PATCH v6] spi: pl022_spi: Add support for ARM PL022 spi controller
  2013-06-12 15:07   ` Armando Visconti
@ 2013-06-12 15:19     ` Armando Visconti
  2013-06-12 15:29       ` Jagan Teki
  0 siblings, 1 reply; 20+ messages in thread
From: Armando Visconti @ 2013-06-12 15:19 UTC (permalink / raw)
  To: u-boot

>
> 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

^ permalink raw reply	[flat|nested] 20+ messages in thread

* [U-Boot] [PATCH v6] spi: pl022_spi: Add support for ARM PL022 spi controller
  2013-06-12 14:25 ` Jagan Teki
@ 2013-06-12 15:07   ` Armando Visconti
  2013-06-12 15:19     ` Armando Visconti
  2013-10-04  6:50   ` Jagan Teki
  1 sibling, 1 reply; 20+ messages in thread
From: Armando Visconti @ 2013-06-12 15:07 UTC (permalink / raw)
  To: u-boot

On 06/12/2013 04:25 PM, Jagan Teki wrote:
> 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

-- 
-- "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

^ permalink raw reply	[flat|nested] 20+ messages in thread

* [U-Boot] [PATCH v6] spi: pl022_spi: Add support for ARM PL022 spi controller
  2013-06-12 12:47 Armando Visconti
@ 2013-06-12 14:25 ` Jagan Teki
  2013-06-12 15:07   ` Armando Visconti
  2013-10-04  6:50   ` Jagan Teki
  0 siblings, 2 replies; 20+ messages in thread
From: Jagan Teki @ 2013-06-12 14:25 UTC (permalink / raw)
  To: u-boot

Thanks for v6 sent.

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

--
Thanks,
Jagan.

On Wed, Jun 12, 2013 at 6:17 PM, Armando Visconti
<armando.visconti@st.com> wrote:
> 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.
>
> Signed-off-by: Armando Visconti <armando.visconti@st.com>
> Signed-off-by: Vipin Kumar <vipin.kumar@st.com>
> Acked-by: Stefan Roese <sr@denx.de>
> ---
> 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
>
> diff --git a/drivers/spi/Makefile b/drivers/spi/Makefile
> index d08609e..b6443b1 100644
> --- a/drivers/spi/Makefile
> +++ b/drivers/spi/Makefile
> @@ -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
> diff --git a/drivers/spi/pl022_spi.c b/drivers/spi/pl022_spi.c
> new file mode 100644
> index 0000000..5b47413
> --- /dev/null
> +++ b/drivers/spi/pl022_spi.c
> @@ -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
>

^ permalink raw reply	[flat|nested] 20+ messages in thread

* [U-Boot] [PATCH v6] spi: pl022_spi: Add support for ARM PL022 spi controller
@ 2013-06-12 12:47 Armando Visconti
  2013-06-12 14:25 ` Jagan Teki
  0 siblings, 1 reply; 20+ messages in thread
From: Armando Visconti @ 2013-06-12 12:47 UTC (permalink / raw)
  To: u-boot

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.

Signed-off-by: Armando Visconti <armando.visconti@st.com>
Signed-off-by: Vipin Kumar <vipin.kumar@st.com>
Acked-by: Stefan Roese <sr@denx.de>
---
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

diff --git a/drivers/spi/Makefile b/drivers/spi/Makefile
index d08609e..b6443b1 100644
--- a/drivers/spi/Makefile
+++ b/drivers/spi/Makefile
@@ -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
diff --git a/drivers/spi/pl022_spi.c b/drivers/spi/pl022_spi.c
new file mode 100644
index 0000000..5b47413
--- /dev/null
+++ b/drivers/spi/pl022_spi.c
@@ -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

^ permalink raw reply related	[flat|nested] 20+ messages in thread

end of thread, other threads:[~2016-09-20  6:25 UTC | newest]

Thread overview: 20+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2016-09-08 14:21 [U-Boot] [PATCH v6] spi: pl022_spi: Add support for ARM PL022 spi controller Michael Brandl
2016-09-14 14:39 ` Armando Visconti
2016-09-19 11:59   ` [U-Boot] ?==?utf-8?q? ?==?utf-8?q? [PATCH v6]?==?utf-8?q? spi:?==?utf-8?q? " Michael Brandl
2016-09-19 14:14     ` [U-Boot] [PATCH v6] spi: " Armando Visconti
2016-09-20  6:25       ` Michael Brandl
2016-09-14 17:52 ` Jagan Teki
  -- strict thread matches above, loose matches on Subject: below --
2013-06-12 12:47 Armando Visconti
2013-06-12 14:25 ` Jagan Teki
2013-06-12 15:07   ` Armando Visconti
2013-06-12 15:19     ` Armando Visconti
2013-06-12 15:29       ` Jagan Teki
2013-06-12 15:55         ` Armando Visconti
2013-10-03 19:52           ` Jagan Teki
2013-10-04  4:10             ` Vipin Kumar
2013-10-04  6:02               ` Jagan Teki
2013-10-04  6:27                 ` Vipin Kumar
2013-10-04  6:50   ` Jagan Teki
2013-12-20 19:03     ` Jagan Teki
2014-01-08  9:19       ` Armando Visconti
2014-01-08 10:30         ` Jagan Teki

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.