Patchwork [U-Boot,2/4] Armada100: SPI Flash support for Marvell gplugD

login
register
mail settings
Submitter Ajay Bhargav
Date July 8, 2011, 6:22 a.m.
Message ID <1310106168-17166-2-git-send-email-ajay.bhargav@einfochips.com>
Download mbox | patch
Permalink /patch/103767/
State Changes Requested
Headers show

Comments

Ajay Bhargav - July 8, 2011, 6:22 a.m.
SPI Flash support added for Marvell GuruPlug-Display. Environment
variables are now stored in flash.

Signed-off-by: Ajay Bhargav <ajay.bhargav@einfochips.com>
---
 arch/arm/include/asm/arch-armada100/gpio.h     |    2 +-
 arch/arm/include/asm/arch-armada100/mfp.h      |    6 +
 arch/arm/include/asm/arch-armada100/regs-ssp.h |  165 +++++++++++++++
 board/Marvell/gplugd/gplugd.c                  |   20 ++
 drivers/spi/Makefile                           |    1 +
 drivers/spi/pxa3xx_spi.c                       |  256 ++++++++++++++++++++++++
 include/configs/gplugd.h                       |   32 +++-
 7 files changed, 475 insertions(+), 7 deletions(-)
 create mode 100644 arch/arm/include/asm/arch-armada100/regs-ssp.h
 create mode 100644 drivers/spi/pxa3xx_spi.c
Wolfgang Denk - July 8, 2011, 7:55 a.m.
Dear Ajay Bhargav,

In message <1310106168-17166-2-git-send-email-ajay.bhargav@einfochips.com> you wrote:
> SPI Flash support added for Marvell GuruPlug-Display. Environment
> variables are now stored in flash.
...
> --- a/arch/arm/include/asm/arch-armada100/gpio.h
> +++ b/arch/arm/include/asm/arch-armada100/gpio.h
> @@ -25,7 +25,7 @@
>  #define __PXA_GPIO_H
>  
>  
> -#define GPIO_REGS_VIRT (0xD4019000)
> +#define GPIO_REGS_VIRT	(0xD4019000)

No parens areound plain constants values, please.

Please fix globally.

...
> --- /dev/null
> +++ b/arch/arm/include/asm/arch-armada100/regs-ssp.h
> @@ -0,0 +1,165 @@
> +/**************************************************************************
> + *
> + * Copyright (c) 2009, 2010 Marvell International Ltd.

Incorrect multiline comment style.  Please fix globally.

> diff --git a/drivers/spi/Makefile b/drivers/spi/Makefile
> index a9b1ca4..9626772 100644
> --- a/drivers/spi/Makefile
> +++ b/drivers/spi/Makefile
> @@ -40,6 +40,7 @@ COBJS-$(CONFIG_OMAP3_SPI) += omap3_spi.o
>  COBJS-$(CONFIG_SOFT_SPI) += soft_spi.o
>  COBJS-$(CONFIG_SH_SPI) += sh_spi.o
>  COBJS-$(CONFIG_FSL_ESPI) += fsl_espi.o
> +COBJS-$(CONFIG_PXA3XX_SPI) += pxa3xx_spi.o

Please keep / make list sorted.

...
> diff --git a/drivers/spi/pxa3xx_spi.c b/drivers/spi/pxa3xx_spi.c
> new file mode 100644
> index 0000000..8d05f90
> --- /dev/null
> +++ b/drivers/spi/pxa3xx_spi.c
> @@ -0,0 +1,256 @@
> +/**************************************************************************
> + *
> + * Copyright (c) 2009, 2010 Marvell International Ltd.
> + *
> + * This file is part of GNU program.
> + *
> + * GNU 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.
> + *
> + * GNU 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, see http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
> + *
> + *************************************************************************/
> +
> +/*
> + * Driver for simulating ssp as spi device for pxa
> + *
> + * Copyright (c) 2009 Marvell Inc.
> + * Lei Wen <leiwen@marvell.com>
> + *
> + * Licensed under the GPL-2 or later.
> + */

Please remove the redunant parts of the Copyright/License headers.
Please fix globally.


> +#define DEFINE_SSP_REG(reg, off) \
> +	static inline u32 read_##reg(void) \
> +{ return __raw_readl(CONFIG_SYS_SSP_BASE + (off)); } \

We don't allow accesses through base address plus offset; please use
proper C structs instead.

> +DEFINE_SSP_REG(SSCR0, 0x00)
> +DEFINE_SSP_REG(SSCR1, 0x04)
> +DEFINE_SSP_REG(SSSR, 0x08)
> +DEFINE_SSP_REG(SSITR, 0x0c)
> +DEFINE_SSP_REG(SSDR, 0x10)
> +DEFINE_SSP_REG(SSTO, 0x28)
> +DEFINE_SSP_REG(SSPSP, 0x2c)

NAK.  Please use C struct.

> +static void null_writer(struct pxa_spi_slave *pss)
> +{
> +	while (!(read_SSSR() & SSSR_TNF))

We don't allow camel-case identifiers.  Please fix globally.

> +		continue;

Please use a plain ';' instead of this 'continue'.  Please fix
globally.


> @@ -96,10 +121,5 @@
>  
>  #define CONFIG_SYS_NS16550_COM1 ARMD1_UART3_BASE
>  
> -/*
> - * Environment variables configurations
> - */
> -#define CONFIG_ENV_IS_NOWHERE	1	/* if env in SDRAM */
> -#define CONFIG_ENV_SIZE	0x20000		/* 64k */
> -
>  #endif	/* __CONFIG_GPLUGD_H */
> +
> -- 

Please do not add trailing empty lines.

Best regards,

Wolfgang Denk
Prafulla Wadaskar - July 8, 2011, 3:21 p.m.
> -----Original Message-----
> From: Ajay Bhargav [mailto:ajay.bhargav@einfochips.com]
> Sent: Friday, July 08, 2011 11:53 AM
> To: Prafulla Wadaskar
> Cc: u-boot@lists.denx.de; Ajay Bhargav
> Subject: [PATCH 2/4] Armada100: SPI Flash support for Marvell gplugD
> 
> SPI Flash support added for Marvell GuruPlug-Display. Environment
> variables are now stored in flash.
> 
> Signed-off-by: Ajay Bhargav <ajay.bhargav@einfochips.com>
> ---
>  arch/arm/include/asm/arch-armada100/gpio.h     |    2 +-
>  arch/arm/include/asm/arch-armada100/mfp.h      |    6 +
>  arch/arm/include/asm/arch-armada100/regs-ssp.h |  165 +++++++++++++++
>  board/Marvell/gplugd/gplugd.c                  |   20 ++
>  drivers/spi/Makefile                           |    1 +
>  drivers/spi/pxa3xx_spi.c                       |  256

The file name should be mvspi.c

> ++++++++++++++++++++++++
>  include/configs/gplugd.h                       |   32 +++-

Split this patch as SPI driver support for Armada100 followed by enabling it for this board addressing GPIOs separately.

Regards..
Prafulla . .
Ajay Bhargav - July 11, 2011, 4:43 a.m.
Hi Prafulla,

Thanks, I will do that.

Regards,
Ajay Bhargav

----- Original Message -----
From: "Prafulla Wadaskar" <prafulla@marvell.com>
To: "Ajay Bhargav" <ajay.bhargav@einfochips.com>
Cc: u-boot@lists.denx.de, "Ashish Karkare" <akarkare@marvell.com>, "Prabhanjan Sarnaik" <sarnaik@marvell.com>
Sent: Friday, July 8, 2011 8:51:37 PM
Subject: RE: [PATCH 2/4] Armada100: SPI Flash support for Marvell gplugD



> -----Original Message-----
> From: Ajay Bhargav [mailto:ajay.bhargav@einfochips.com]
> Sent: Friday, July 08, 2011 11:53 AM
> To: Prafulla Wadaskar
> Cc: u-boot@lists.denx.de; Ajay Bhargav
> Subject: [PATCH 2/4] Armada100: SPI Flash support for Marvell gplugD
> 
> SPI Flash support added for Marvell GuruPlug-Display. Environment
> variables are now stored in flash.
> 
> Signed-off-by: Ajay Bhargav <ajay.bhargav@einfochips.com>
> ---
>  arch/arm/include/asm/arch-armada100/gpio.h     |    2 +-
>  arch/arm/include/asm/arch-armada100/mfp.h      |    6 +
>  arch/arm/include/asm/arch-armada100/regs-ssp.h |  165 +++++++++++++++
>  board/Marvell/gplugd/gplugd.c                  |   20 ++
>  drivers/spi/Makefile                           |    1 +
>  drivers/spi/pxa3xx_spi.c                       |  256

The file name should be mvspi.c

> ++++++++++++++++++++++++
>  include/configs/gplugd.h                       |   32 +++-

Split this patch as SPI driver support for Armada100 followed by enabling it for this board addressing GPIOs separately.

Regards..
Prafulla . .

Patch

diff --git a/arch/arm/include/asm/arch-armada100/gpio.h b/arch/arm/include/asm/arch-armada100/gpio.h
index e13c2da..dd23908 100644
--- a/arch/arm/include/asm/arch-armada100/gpio.h
+++ b/arch/arm/include/asm/arch-armada100/gpio.h
@@ -25,7 +25,7 @@ 
 #define __PXA_GPIO_H
 
 
-#define GPIO_REGS_VIRT (0xD4019000)
+#define GPIO_REGS_VIRT	(0xD4019000)
 
 #define BANK_OFF(n)     (((n) < 3) ? (n) << 2 : 0x100 + (((n) - 3) << 2))
 #define GPIO_REG(x)     (GPIO_REGS_VIRT + (x))
diff --git a/arch/arm/include/asm/arch-armada100/mfp.h b/arch/arm/include/asm/arch-armada100/mfp.h
index da76b58..e94be3a 100644
--- a/arch/arm/include/asm/arch-armada100/mfp.h
+++ b/arch/arm/include/asm/arch-armada100/mfp.h
@@ -83,6 +83,12 @@ 
 #define MFP101_ETH_MDIO		(MFP_REG(0x194) | MFP_AF5 | MFP_DRIVE_MEDIUM)
 #define MFP103_ETH_RXDV		(MFP_REG(0x19C) | MFP_AF5 | MFP_DRIVE_MEDIUM)
 
+/* SPI */
+#define MFP107_SSP2_RXD         (MFP_REG(0x1AC) | MFP_AF4 | MFP_DRIVE_MEDIUM)
+#define MFP108_SSP2_TXD         (MFP_REG(0x1B0) | MFP_AF4 | MFP_DRIVE_MEDIUM)
+#define MFP110_SSP2_CS          (MFP_REG(0x1B8) | MFP_AF0 | MFP_DRIVE_MEDIUM)
+#define MFP111_SSP2_CLK         (MFP_REG(0x1BC) | MFP_AF4 | MFP_DRIVE_MEDIUM)
+
 /* More macros can be defined here... */
 
 #define MFP_PIN_MAX	117
diff --git a/arch/arm/include/asm/arch-armada100/regs-ssp.h b/arch/arm/include/asm/arch-armada100/regs-ssp.h
new file mode 100644
index 0000000..dbe7e83
--- /dev/null
+++ b/arch/arm/include/asm/arch-armada100/regs-ssp.h
@@ -0,0 +1,165 @@ 
+/**************************************************************************
+ *
+ * Copyright (c) 2009, 2010 Marvell International Ltd.
+ *
+ * This file is part of GNU program.
+ *
+ * GNU 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.
+ *
+ * GNU 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, see http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
+ *
+ *************************************************************************/
+
+#ifndef __ASM_ARCH_REGS_SSP_H
+#define __ASM_ARCH_REGS_SSP_H
+
+/*
+ * SSP Serial Port Registers
+ * PXA250, PXA255, PXA26x and PXA27x SSP controllers are all slightly different.
+ * PXA255, PXA26x and PXA27x have extra ports, registers and bits.
+ */
+
+#define SSCR0		(0x00)  /* SSP Control Register 0 */
+#define SSCR1		(0x04)  /* SSP Control Register 1 */
+#define SSSR		(0x08)  /* SSP Status Register */
+#define SSITR		(0x0C)  /* SSP Interrupt Test Register */
+#define SSDR		(0x10)  /* SSP Data Write/Data Read Register */
+
+#define SSTO		(0x28)  /* SSP Time Out Register */
+#define SSPSP		(0x2C)  /* SSP Programmable Serial Protocol */
+#define SSTSA		(0x30)  /* SSP Tx Timeslot Active */
+#define SSRSA		(0x34)  /* SSP Rx Timeslot Active */
+#define SSTSS		(0x38)  /* SSP Timeslot Status */
+#define SSACD		(0x3C)  /* SSP Audio Clock Divider */
+
+#if defined(CONFIG_PXA3xx) || defined(CONFIG_CPU_PXA910)
+#define SSACDD		(0x40)	/* SSP Audio Clock Dither Divider */
+#endif
+
+/* Common PXA2xx bits first */
+#define SSCR0_DSS	(0x0000000f)	/* Data Size Select (mask) */
+#define SSCR0_DataSize(x)  ((x) - 1)	/* Data Size Select [4..16] */
+#define SSCR0_FRF	(0x00000030)	/* FRame Format (mask) */
+#define SSCR0_Motorola	(0x0 << 4)	/* Motorola's Serial
+					   Peripheral Interface */
+#define SSCR0_TI	(0x1 << 4)	/* TI's Synchronous
+					   Serial Protocol (SSP) */
+#define SSCR0_National	(0x2 << 4)	/* National Microwire */
+#define SSCR0_ECS	(1 << 6)	/* External clock select */
+#define SSCR0_SSE	(1 << 7)	/* Synchronous Serial Port Enable */
+
+#if defined(CONFIG_PXA25x)
+#define SSCR0_SCR	(0x0000ff00)	/* Serial Clock Rate (mask) */
+#define SSCR0_SerClkDiv(x) ((((x) - 2)/2) << 8) /* Divisor [2..512] */
+#elif defined(CONFIG_PXA27x) || \
+	defined(CONFIG_PXA3xx) || \
+	defined(CONFIG_CPU_PXA910)
+#define SSCR0_SCR	(0x000fff00)	/* Serial Clock Rate (mask) */
+#define SSCR0_SerClkDiv(x) (((x) - 1) << 8) /* Divisor [1..4096] */
+#endif
+
+#if defined(CONFIG_PXA27x) || \
+	defined(CONFIG_PXA3xx) || \
+	defined(CONFIG_CPU_PXA910)
+#define SSCR0_EDSS	(1 << 20)	/* Extended data size select */
+#define SSCR0_NCS	(1 << 21)	/* Network clock select */
+#define SSCR0_RIM	(1 << 22)	/* Receive FIFO overrrun
+					   interrupt mask */
+#define SSCR0_TUM	(1 << 23)	/* Transmit FIFO underrun
+					   interrupt mask */
+#define SSCR0_FRDC	(0x07000000)	/* Frame rate divider control (mask) */
+#define SSCR0_SlotsPerFrm(x) (((x) - 1) << 24)
+					/* Time slots per frame [1..8] */
+#define SSCR0_ADC	(1 << 30)	/* Audio clock select */
+#define SSCR0_MOD	(1 << 31)	/* Mode (normal or network) */
+#endif
+
+#if defined(CONFIG_PXA3xx) || defined(CONFIG_CPU_PXA910)
+#define SSCR0_FPCKE	(1 << 29)	/* FIFO packing enable */
+#endif
+
+#define SSCR1_RIE	(1 << 0)	/* Receive FIFO Interrupt Enable */
+#define SSCR1_TIE	(1 << 1)	/* Transmit FIFO Interrupt Enable */
+#define SSCR1_LBM	(1 << 2)	/* Loop-Back Mode */
+#define SSCR1_SPO	(1 << 3)	/* Motorola SPI SSPSCLK
+					   polarity setting */
+#define SSCR1_SPH	(1 << 4)	/* Motorola SPI SSPSCLK phase setting */
+#define SSCR1_MWDS	(1 << 5)	/* Microwire Transmit Data Size */
+#define SSCR1_TFT	(0x000003c0)	/* Transmit FIFO Threshold (mask) */
+#define SSCR1_TxTresh(x) (((x) - 1) << 6) /* level [1..16] */
+#define SSCR1_RFT	(0x00003c00)	/* Receive FIFO Threshold (mask) */
+#define SSCR1_RxTresh(x) (((x) - 1) << 10) /* level [1..16] */
+
+#define SSSR_TNF	(1 << 2)	/* Transmit FIFO Not Full */
+#define SSSR_RNE	(1 << 3)	/* Receive FIFO Not Empty */
+#define SSSR_BSY	(1 << 4)	/* SSP Busy */
+#define SSSR_TFS	(1 << 5)	/* Transmit FIFO Service Request */
+#define SSSR_RFS	(1 << 6)	/* Receive FIFO Service Request */
+#define SSSR_ROR	(1 << 7)	/* Receive FIFO Overrun */
+
+#define SSCR0_TIM	(1 << 23)	/* Transmit FIFO Under Run
+					   Interrupt Mask */
+#define SSCR0_RIM	(1 << 22)	/* Receive FIFO Over
+					   Run interrupt Mask */
+#define SSCR0_NCS	(1 << 21)	/* Network Clock Select */
+#define SSCR0_EDSS	(1 << 20)	/* Extended Data Size Select */
+
+/* extra bits in PXA255, PXA26x and PXA27x SSP ports */
+#define SSCR0_TISSP	(1 << 4)	/* TI Sync Serial Protocol */
+#define SSCR0_PSP	(3 << 4)	/* PSP - Programmable Serial Protocol */
+#define SSCR1_TTELP	(1 << 31)	/* TXD Tristate Enable Last Phase */
+#define SSCR1_TTE	(1 << 30)	/* TXD Tristate Enable */
+#define SSCR1_EBCEI	(1 << 29)	/* Enable Bit Count Error interrupt */
+#define SSCR1_SCFR	(1 << 28)	/* Slave Clock free Running */
+#define SSCR1_ECRA	(1 << 27)	/* Enable Clock Request A */
+#define SSCR1_ECRB	(1 << 26)	/* Enable Clock request B */
+#define SSCR1_SCLKDIR	(1 << 25)	/* Serial Bit Rate Clock Direction */
+#define SSCR1_SFRMDIR	(1 << 24)	/* Frame Direction */
+#define SSCR1_RWOT	(1 << 23)	/* Receive Without Transmit */
+#define SSCR1_TRAIL	(1 << 22)	/* Trailing Byte */
+#define SSCR1_TSRE	(1 << 21)	/* Transmit Service Request Enable */
+#define SSCR1_RSRE	(1 << 20)	/* Receive Service Request Enable */
+#define SSCR1_TINTE	(1 << 19)	/* Receiver Time-out Interrupt enable */
+#define SSCR1_PINTE	(1 << 18)	/* Peripheral Trailing
+					   Byte Interupt Enable */
+#define SSCR1_IFS	(1 << 16)	/* Invert Frame Signal */
+#define SSCR1_STRF	(1 << 15)	/* Select FIFO or EFWR */
+#define SSCR1_EFWR	(1 << 14)	/* Enable FIFO Write/Read */
+
+#define SSSR_BCE	(1 << 23)	/* Bit Count Error */
+#define SSSR_CSS	(1 << 22)	/* Clock Synchronisation Status */
+#define SSSR_TUR	(1 << 21)	/* Transmit FIFO Under Run */
+#define SSSR_EOC	(1 << 20)	/* End Of Chain */
+#define SSSR_TINT	(1 << 19)	/* Receiver Time-out Interrupt */
+#define SSSR_PINT	(1 << 18)	/* Peripheral Trailing Byte Interrupt */
+
+#define SSPSP_FSRT		(1 << 25)	/* Frame Sync Relative Timing */
+#define SSPSP_DMYSTOP(x)	((x) << 23)	/* Dummy Stop */
+#define SSPSP_SFRMWDTH(x)	((x) << 16)	/* Serial Frame Width */
+#define SSPSP_SFRMDLY(x)	((x) << 9)	/* Serial Frame Delay */
+#define SSPSP_DMYSTRT(x)	((x) << 7)	/* Dummy Start */
+#define SSPSP_STRTDLY(x)	((x) << 4)	/* Start Delay */
+#define SSPSP_ETDS		(1 << 3)	/* End of Transfer data State */
+#define SSPSP_SFRMP		(1 << 2)	/* Serial Frame Polarity */
+#define SSPSP_SCMODE(x)		((x) << 0)	/* Serial Bit Rate Clock Mode */
+
+#define SSACD_SCDB		(1 << 3)	/* SSPSYSCLK Divider Bypass */
+#define SSACD_ACPS(x)		((x) << 4)	/* Audio clock PLL select */
+#define SSACD_ACDS(x)		((x) << 0)	/* Audio clock divider select */
+#if defined(CONFIG_PXA3xx) || defined(CONFIG_CPU_PXA910)
+#define SSACD_SCDX8	(1 << 7)	/* SYSCLK division ratio select */
+#endif
+
+
+#endif /* __ASM_ARCH_REGS_SSP_H */
diff --git a/board/Marvell/gplugd/gplugd.c b/board/Marvell/gplugd/gplugd.c
index 81770fc..0c7a8fd 100644
--- a/board/Marvell/gplugd/gplugd.c
+++ b/board/Marvell/gplugd/gplugd.c
@@ -47,6 +47,7 @@  DECLARE_GLOBAL_DATA_PTR;
 #define PHY_LED_VAL             0x5b	/* LINK LED1, ACT LED2 */
 #define PHY_RST			104	/* GPIO104 - PHY RESET */
 #define RTC_IRQ			102	/* GPIO102 - RTC IRQ Input */
+#define SSP2CS			110	/* GPIO110 - SSP Chip Select */
 #define FE_CLK_RST              0x1
 #define FE_CLK_ENA              0x8
 
@@ -80,6 +81,11 @@  int board_early_init_f(void)
 		MFP101_ETH_MDIO,
 		MFP103_ETH_RXDV,
 
+		MFP107_SSP2_RXD,
+		MFP108_SSP2_TXD,
+		MFP110_SSP2_CS,
+		MFP111_SSP2_CLK,
+
 		MFP_EOC		/*End of configuration*/
 	};
 	/* configure MFP's */
@@ -93,11 +99,25 @@  int board_early_init_f(void)
 
 int board_init(void)
 {
+	struct armd1apb1_registers *apb1_regs =
+		(struct armd1apb1_registers *)ARMD1_APBC1_BASE;
+	struct armd1apb2_registers *apb2_regs =
+		(struct armd1apb2_registers *)ARMD1_APBC2_BASE;
+
 	/* arch number of Board */
 	gd->bd->bi_arch_number = MACH_TYPE_SHEEVAD;
 	/* adress of boot parameters */
 	gd->bd->bi_boot_params = armd1_sdram_base(0) + 0x100;
 
+#ifdef CONFIG_PXA3XX_SPI
+	/* Enable SSP2 clock */
+	writel(0x03, &apb2_regs->ssp2_clkrst);
+	/* enable GPIO clock */
+	writel(0x01, &apb1_regs->gpio);
+	/* configure GPIO110 as CS# */
+	gpio_direction_output(SSP2CS, GPIO_SET);
+#endif
+
 	return 0;
 }
 
diff --git a/drivers/spi/Makefile b/drivers/spi/Makefile
index a9b1ca4..9626772 100644
--- a/drivers/spi/Makefile
+++ b/drivers/spi/Makefile
@@ -40,6 +40,7 @@  COBJS-$(CONFIG_OMAP3_SPI) += omap3_spi.o
 COBJS-$(CONFIG_SOFT_SPI) += soft_spi.o
 COBJS-$(CONFIG_SH_SPI) += sh_spi.o
 COBJS-$(CONFIG_FSL_ESPI) += fsl_espi.o
+COBJS-$(CONFIG_PXA3XX_SPI) += pxa3xx_spi.o
 
 COBJS	:= $(COBJS-y)
 SRCS	:= $(COBJS:.o=.c)
diff --git a/drivers/spi/pxa3xx_spi.c b/drivers/spi/pxa3xx_spi.c
new file mode 100644
index 0000000..8d05f90
--- /dev/null
+++ b/drivers/spi/pxa3xx_spi.c
@@ -0,0 +1,256 @@ 
+/**************************************************************************
+ *
+ * Copyright (c) 2009, 2010 Marvell International Ltd.
+ *
+ * This file is part of GNU program.
+ *
+ * GNU 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.
+ *
+ * GNU 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, see http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
+ *
+ *************************************************************************/
+
+/*
+ * Driver for simulating ssp as spi device for pxa
+ *
+ * Copyright (c) 2009 Marvell Inc.
+ * Lei Wen <leiwen@marvell.com>
+ *
+ * Licensed under the GPL-2 or later.
+ */
+
+
+#include <common.h>
+#include <malloc.h>
+#include <spi.h>
+
+#include <asm/io.h>
+#include <asm/arch/regs-ssp.h>
+#include <asm/arch/gpio.h>
+
+struct pxa_spi_slave {
+	struct spi_slave slave;
+	u32 cr0, cr1;
+	u32 int_cr1;
+	u32 clear_sr;
+	const void *tx;
+	void *rx;
+	int gpio_cs_inverted;
+
+	void (*write)(struct pxa_spi_slave *pss);
+	void (*read)(struct pxa_spi_slave *pss);
+};
+
+#define to_pxa_spi_slave(s) container_of(s, struct pxa_spi_slave, slave)
+
+#define DEFINE_SSP_REG(reg, off) \
+	static inline u32 read_##reg(void) \
+{ return __raw_readl(CONFIG_SYS_SSP_BASE + (off)); } \
+\
+static inline void write_##reg(u32 v) \
+{ __raw_writel(v, CONFIG_SYS_SSP_BASE + (off)); }
+
+DEFINE_SSP_REG(SSCR0, 0x00)
+DEFINE_SSP_REG(SSCR1, 0x04)
+DEFINE_SSP_REG(SSSR, 0x08)
+DEFINE_SSP_REG(SSITR, 0x0c)
+DEFINE_SSP_REG(SSDR, 0x10)
+DEFINE_SSP_REG(SSTO, 0x28)
+DEFINE_SSP_REG(SSPSP, 0x2c)
+
+#define DEFAULT_WORD_LEN	8
+#define SSP_FLUSH_NUM		0x2000
+#define RX_THRESH_DFLT		8
+#define TX_THRESH_DFLT		8
+#define TIMOUT_DFLT		1000
+
+void spi_cs_activate(struct spi_slave *slave)
+{
+	struct pxa_spi_slave *pss = to_pxa_spi_slave(slave);
+	gpio_set_value(slave->cs, pss->gpio_cs_inverted);
+}
+
+void spi_cs_deactivate(struct spi_slave *slave)
+{
+	struct pxa_spi_slave *pss = to_pxa_spi_slave(slave);
+	gpio_set_value(slave->cs, !pss->gpio_cs_inverted);
+}
+
+static void null_writer(struct pxa_spi_slave *pss)
+{
+	while (!(read_SSSR() & SSSR_TNF))
+		continue;
+
+	write_SSDR(0);
+}
+
+static void null_reader(struct pxa_spi_slave *pss)
+{
+	while (!(read_SSSR() & SSSR_RNE))
+		continue;
+	read_SSDR();
+}
+
+static void u8_writer(struct pxa_spi_slave *pss)
+{
+	while (!(read_SSSR() & SSSR_TNF))
+		continue;
+
+	write_SSDR(*(u8 *)(pss->tx));
+	++pss->tx;
+}
+
+static void u8_reader(struct pxa_spi_slave *pss)
+{
+	while (!(read_SSSR() & SSSR_RNE))
+		continue;
+	*(u8 *)(pss->rx) = read_SSDR();
+	++pss->rx;
+}
+
+static int flush(void)
+{
+	unsigned long limit = SSP_FLUSH_NUM;
+
+	do {
+		while (read_SSSR() & SSSR_RNE)
+			read_SSDR();
+	} while ((read_SSSR() & SSSR_BSY) && limit--);
+	write_SSSR(SSSR_ROR);
+
+	return limit;
+}
+
+struct spi_slave *spi_setup_slave(unsigned int bus, unsigned int cs,
+		unsigned int max_hz, unsigned int mode)
+{
+	struct pxa_spi_slave *pss;
+	unsigned int clk_div;
+
+	clk_div = ((CONFIG_SSP_CLK / max_hz - 1) & 0xfff) << 8;
+
+	pss = malloc(sizeof(*pss));
+	if (!pss)
+		return NULL;
+
+	pss->slave.bus = bus;
+	pss->slave.cs = cs;
+
+	pss->cr0 = clk_div
+		| SSCR0_Motorola
+		| SSCR0_DataSize(DEFAULT_WORD_LEN)
+		| SSCR0_SSE;
+
+	pss->cr1 = (SSCR1_RxTresh(RX_THRESH_DFLT) & SSCR1_RFT) |
+		(SSCR1_TxTresh(TX_THRESH_DFLT) & SSCR1_TFT);
+	pss->cr1 &= ~(SSCR1_SPO | SSCR1_SPH);
+	pss->cr1 |= (((mode & SPI_CPHA) != 0) ? SSCR1_SPH : 0)
+		| (((mode & SPI_CPOL) != 0) ? SSCR1_SPO : 0);
+
+	pss->int_cr1 = SSCR1_TIE | SSCR1_RIE | SSCR1_TINTE;
+	pss->clear_sr = SSSR_ROR | SSSR_TINT;
+
+	pss->gpio_cs_inverted = mode & SPI_CS_HIGH;
+	gpio_set_value(cs, !pss->gpio_cs_inverted);
+
+	return &pss->slave;
+}
+
+void spi_free_slave(struct spi_slave *slave)
+{
+	struct pxa_spi_slave *pss = to_pxa_spi_slave(slave);
+	free(pss);
+}
+
+void spi_init()
+{
+	/* Load default SSP configuration */
+	write_SSCR0(0);
+	write_SSCR1(SSCR1_RxTresh(RX_THRESH_DFLT) |
+			SSCR1_TxTresh(TX_THRESH_DFLT));
+	write_SSCR0(SSCR0_SerClkDiv(2)
+			| SSCR0_Motorola
+			| SSCR0_DataSize(DEFAULT_WORD_LEN));
+	write_SSTO(0);
+	write_SSPSP(0);
+}
+
+int spi_claim_bus(struct spi_slave *slave)
+{
+	debug("%s: bus:%i cs:%i\n", __func__, slave->bus, slave->cs);
+	if (flush() == 0)
+		return -1;
+
+	return 0;
+}
+
+void spi_release_bus(struct spi_slave *slave)
+{
+}
+
+int spi_xfer(struct spi_slave *slave, unsigned int bitlen, const void *dout,
+		void *din, unsigned long flags)
+{
+	struct pxa_spi_slave *pss = to_pxa_spi_slave(slave);
+	uint bytes = bitlen / 8;
+	unsigned long limit;
+	int ret = 0;
+
+	if (bitlen == 0)
+		goto done;
+
+	/* we can only do 8 bit transfers */
+	if (bitlen % 8) {
+		flags |= SPI_XFER_END;
+		goto done;
+	}
+
+	if (dout) {
+		pss->tx = dout;
+		pss->write = u8_writer;
+	} else
+		pss->write = null_writer;
+
+	if (din) {
+		pss->rx = din;
+		pss->read = u8_reader;
+	} else
+		pss->read = null_reader;
+
+	if (flags & SPI_XFER_BEGIN) {
+		spi_cs_activate(slave);
+		write_SSCR1(pss->cr1 | pss->int_cr1);
+		write_SSTO(TIMOUT_DFLT);
+		write_SSCR0(pss->cr0);
+	}
+
+	while (bytes--) {
+		limit = SSP_FLUSH_NUM;
+		pss->write(pss);
+		while ((read_SSSR() & SSSR_BSY) && limit--)
+			udelay(1);
+		pss->read(pss);
+	}
+
+ done:
+	if (flags & SPI_XFER_END) {
+		/* Stop SSP */
+		write_SSSR(pss->clear_sr);
+		write_SSCR1(read_SSCR1() & ~pss->int_cr1);
+		write_SSTO(0);
+		spi_cs_deactivate(slave);
+	}
+
+	return ret;
+}
diff --git a/include/configs/gplugd.h b/include/configs/gplugd.h
index d2b91d7..f0fb057 100644
--- a/include/configs/gplugd.h
+++ b/include/configs/gplugd.h
@@ -83,6 +83,31 @@ 
 #define CONFIG_ROOTPATH			"/tftpboot"
 #define CONFIG_SYS_IMG_NAME		"uImage"
 
+/* Flash support */
+#define CONFIG_PXA3XX_SPI
+
+#define CONFIG_ENV_IS_IN_SPI_FLASH
+#define CONFIG_ENV_SECT_SIZE            0x4000
+#define CONFIG_ENV_SIZE			0x4000
+#define CONFIG_ENV_OFFSET               0x07C000
+
+#if defined(CONFIG_PXA3XX_SPI)
+#define CONFIG_PXA3xx
+#define CONFIG_SSP_CLK                  6500000
+#define CONFIG_SYS_SSP_BASE             0xD401C000
+#define CONFIG_ENV_SPI_BUS              0
+#define CONFIG_ENV_SPI_CS               110
+#define CONFIG_ENV_SPI_MAX_HZ           26000
+#define CONFIG_ENV_SPI_MODE             0
+#define CONFIG_CMD_SF
+#define SF_PROBE_ONCE_FOR_COMMAND
+#define CONFIG_PROBE_FLASH_INIT
+#define CONFIG_SPI_FLASH_ATMEL          1
+#define CONFIG_CMD_ASKENV
+#define CONFIG_CMD_EDITENV
+#define CONFIG_CMD_SAVEENV
+#endif /*CONFIG_PXA3XX_SPI*/
+
 /*
  * mv-common.h should be defined after CMD configs since it used them
  * to enable certain macros
@@ -96,10 +121,5 @@ 
 
 #define CONFIG_SYS_NS16550_COM1 ARMD1_UART3_BASE
 
-/*
- * Environment variables configurations
- */
-#define CONFIG_ENV_IS_NOWHERE	1	/* if env in SDRAM */
-#define CONFIG_ENV_SIZE	0x20000		/* 64k */
-
 #endif	/* __CONFIG_GPLUGD_H */
+