m68knommu: Coldfire QSPI platform support
authorSteven King <sfking@fdwdc.com>
Fri, 22 Jan 2010 20:43:03 +0000 (12:43 -0800)
committerGreg Ungerer <gerg@uclinux.org>
Mon, 17 May 2010 01:04:19 +0000 (11:04 +1000)
Since Grant has added the coldfire-qspi driver to next-spi, here is the
platform support for the parts that have qspi hardware.  This sets up
gpio to do the spi chip select using the default chip select pins; it should
be trivial for boards that require different or additional spi chip selects to
use other gpios as needed.

Signed-off-by: Steven King <sfking@fdwdc.com>
Signed-off-by: Greg Ungerer <gerg@uclinux.org>
13 files changed:
arch/m68k/include/asm/m520xsim.h
arch/m68k/include/asm/m523xsim.h
arch/m68k/include/asm/m5249sim.h
arch/m68k/include/asm/m527xsim.h
arch/m68k/include/asm/m528xsim.h
arch/m68k/include/asm/m532xsim.h
arch/m68k/include/asm/mcfqspi.h [new file with mode: 0644]
arch/m68knommu/platform/520x/config.c
arch/m68knommu/platform/523x/config.c
arch/m68knommu/platform/5249/config.c
arch/m68knommu/platform/527x/config.c
arch/m68knommu/platform/528x/config.c
arch/m68knommu/platform/532x/config.c

index ed2b69b..db824a4 100644 (file)
 
 #define MCF_GPIO_PAR_UART                   (0xA4036)
 #define MCF_GPIO_PAR_FECI2C                 (0xA4033)
+#define MCF_GPIO_PAR_QSPI                   (0xA4034)
 #define MCF_GPIO_PAR_FEC                    (0xA4038)
 
 #define MCF_GPIO_PAR_UART_PAR_URXD0         (0x0001)
index a34894c..e8d06b2 100644 (file)
 #define MCFGPIO_IRQ_MAX                        8
 #define MCFGPIO_IRQ_VECBASE            MCFINT_VECBASE
 
+/*
+ * Pin Assignment
+*/
+#define        MCFGPIO_PAR_QSPI        (MCF_IPSBAR + 0x10004A)
+#define        MCFGPIO_PAR_TIMER       (MCF_IPSBAR + 0x10004C)
 /****************************************************************************/
 #endif /* m523xsim_h */
index 14bce87..79b7b40 100644 (file)
 #define        MCFSIM_DMA1ICR          MCFSIM_ICR7     /* DMA 1 ICR */
 #define        MCFSIM_DMA2ICR          MCFSIM_ICR8     /* DMA 2 ICR */
 #define        MCFSIM_DMA3ICR          MCFSIM_ICR9     /* DMA 3 ICR */
+#define        MCFSIM_QSPIICR          MCFSIM_ICR10    /* QSPI ICR */
 
 /*
  *     Define system peripheral IRQ usage.
  */
+#define        MCF_IRQ_QSPI            28              /* QSPI, Level 4 */
 #define        MCF_IRQ_TIMER           30              /* Timer0, Level 6 */
 #define        MCF_IRQ_PROFILER        31              /* Timer1, Level 7 */
 
index 453356d..1feb46f 100644 (file)
@@ -31,6 +31,7 @@
 #define        MCFINT_UART0            13              /* Interrupt number for UART0 */
 #define        MCFINT_UART1            14              /* Interrupt number for UART1 */
 #define        MCFINT_UART2            15              /* Interrupt number for UART2 */
+#define        MCFINT_QSPI             18              /* Interrupt number for QSPI */
 #define        MCFINT_PIT1             36              /* Interrupt number for PIT1 */
 
 /*
 #define MCFGPIO_PIN_MAX                        100
 #define MCFGPIO_IRQ_MAX                        8
 #define MCFGPIO_IRQ_VECBASE            MCFINT_VECBASE
+
+#define MCFGPIO_PAR_QSPI       (MCF_IPSBAR + 0x10004A)
+#define MCFGPIO_PAR_TIMER      (MCF_IPSBAR + 0x10004C)
 #endif
 
 #ifdef CONFIG_M5275
 #define MCFGPIO_PIN_MAX                        148
 #define MCFGPIO_IRQ_MAX                        8
 #define MCFGPIO_IRQ_VECBASE            MCFINT_VECBASE
+
+#define MCFGPIO_PAR_QSPI       (MCF_IPSBAR + 0x10007E)
 #endif
 
 /*
 #define MCFEPORT_EPPDR         (MCF_IPSBAR + 0x130005)
 
 
+
 /*
  *     GPIO pins setups to enable the UARTs.
  */
index e2ad1f4..891cbed 100644 (file)
@@ -29,6 +29,7 @@
 
 #define        MCFINT_VECBASE          64              /* Vector base number */
 #define        MCFINT_UART0            13              /* Interrupt number for UART0 */
+#define        MCFINT_QSPI             18              /* Interrupt number for QSPI */
 #define        MCFINT_PIT1             55              /* Interrupt number for PIT1 */
 
 /*
 #define MCF5282_I2C_I2SR_RXAK   (0x01)  // received acknowledge
 
 
-
-/*********************************************************************
-*
-* Queued Serial Peripheral Interface (QSPI) Module
-*
-*********************************************************************/
-/* Derek - 21 Feb 2005 */
-/* change to the format used in I2C */
-/* Read/Write access macros for general use */
-#define MCF5282_QSPI_QMR        MCF_IPSBAR + 0x0340
-#define MCF5282_QSPI_QDLYR      MCF_IPSBAR + 0x0344
-#define MCF5282_QSPI_QWR        MCF_IPSBAR + 0x0348
-#define MCF5282_QSPI_QIR        MCF_IPSBAR + 0x034C
-#define MCF5282_QSPI_QAR        MCF_IPSBAR + 0x0350
-#define MCF5282_QSPI_QDR        MCF_IPSBAR + 0x0354
-#define MCF5282_QSPI_QCR        MCF_IPSBAR + 0x0354
-
-/* Bit level definitions and macros */
-#define MCF5282_QSPI_QMR_MSTR                           (0x8000)
-#define MCF5282_QSPI_QMR_DOHIE                          (0x4000)
-#define MCF5282_QSPI_QMR_BITS_16                        (0x0000)
-#define MCF5282_QSPI_QMR_BITS_8                         (0x2000)
-#define MCF5282_QSPI_QMR_BITS_9                         (0x2400)
-#define MCF5282_QSPI_QMR_BITS_10                        (0x2800)
-#define MCF5282_QSPI_QMR_BITS_11                        (0x2C00)
-#define MCF5282_QSPI_QMR_BITS_12                        (0x3000)
-#define MCF5282_QSPI_QMR_BITS_13                        (0x3400)
-#define MCF5282_QSPI_QMR_BITS_14                        (0x3800)
-#define MCF5282_QSPI_QMR_BITS_15                        (0x3C00)
-#define MCF5282_QSPI_QMR_CPOL                           (0x0200)
-#define MCF5282_QSPI_QMR_CPHA                           (0x0100)
-#define MCF5282_QSPI_QMR_BAUD(x)                        (((x)&0x00FF))
-
-#define MCF5282_QSPI_QDLYR_SPE                          (0x80)
-#define MCF5282_QSPI_QDLYR_QCD(x)                       (((x)&0x007F)<<8)
-#define MCF5282_QSPI_QDLYR_DTL(x)                       (((x)&0x00FF))
-
-#define MCF5282_QSPI_QWR_HALT                           (0x8000)
-#define MCF5282_QSPI_QWR_WREN                           (0x4000)
-#define MCF5282_QSPI_QWR_WRTO                           (0x2000)
-#define MCF5282_QSPI_QWR_CSIV                           (0x1000)
-#define MCF5282_QSPI_QWR_ENDQP(x)                       (((x)&0x000F)<<8)
-#define MCF5282_QSPI_QWR_CPTQP(x)                       (((x)&0x000F)<<4)
-#define MCF5282_QSPI_QWR_NEWQP(x)                       (((x)&0x000F))
-
-#define MCF5282_QSPI_QIR_WCEFB                          (0x8000)
-#define MCF5282_QSPI_QIR_ABRTB                          (0x4000)
-#define MCF5282_QSPI_QIR_ABRTL                          (0x1000)
-#define MCF5282_QSPI_QIR_WCEFE                          (0x0800)
-#define MCF5282_QSPI_QIR_ABRTE                          (0x0400)
-#define MCF5282_QSPI_QIR_SPIFE                          (0x0100)
-#define MCF5282_QSPI_QIR_WCEF                           (0x0008)
-#define MCF5282_QSPI_QIR_ABRT                           (0x0004)
-#define MCF5282_QSPI_QIR_SPIF                           (0x0001)
-
-#define MCF5282_QSPI_QAR_ADDR(x)                        (((x)&0x003F))
-
-#define MCF5282_QSPI_QDR_COMMAND(x)                     (((x)&0xFF00))
-#define MCF5282_QSPI_QCR_DATA(x)                        (((x)&0x00FF)<<8)
-#define MCF5282_QSPI_QCR_CONT                           (0x8000)
-#define MCF5282_QSPI_QCR_BITSE                          (0x4000)
-#define MCF5282_QSPI_QCR_DT                             (0x2000)
-#define MCF5282_QSPI_QCR_DSCK                           (0x1000)
-#define MCF5282_QSPI_QCR_CS                             (((x)&0x000F)<<8)
-
-/****************************************************************************/
 #endif /* m528xsim_h */
index 36bf15a..c4bf1c8 100644 (file)
@@ -17,6 +17,7 @@
 #define MCFINT_UART0        26          /* Interrupt number for UART0 */
 #define MCFINT_UART1        27          /* Interrupt number for UART1 */
 #define MCFINT_UART2        28          /* Interrupt number for UART2 */
+#define MCFINT_QSPI         31          /* Interrupt number for QSPI */
 
 #define MCF_WTM_WCR    MCF_REG16(0xFC098000)
 
diff --git a/arch/m68k/include/asm/mcfqspi.h b/arch/m68k/include/asm/mcfqspi.h
new file mode 100644 (file)
index 0000000..39d90d5
--- /dev/null
@@ -0,0 +1,64 @@
+/*
+ * Definitions for Freescale Coldfire QSPI module
+ *
+ * Copyright 2010 Steven King <sfking@fdwdc.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ *
+ * 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.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+*/
+
+#ifndef mcfqspi_h
+#define mcfqspi_h
+
+#if defined(CONFIG_M523x) || defined(CONFIG_M527x) || defined(CONFIG_M528x)
+#define        MCFQSPI_IOBASE          (MCF_IPSBAR + 0x340)
+#elif defined(CONFIG_M5249)
+#define MCFQSPI_IOBASE         (MCF_MBAR + 0x300)
+#elif defined(CONFIG_M520x) || defined(CONFIG_M532x)
+#define MCFQSPI_IOBASE         0xFC058000
+#endif
+#define MCFQSPI_IOSIZE         0x40
+
+/**
+ * struct mcfqspi_cs_control - chip select control for the coldfire qspi driver
+ * @setup: setup the control; allocate gpio's, etc. May be NULL.
+ * @teardown: finish with the control; free gpio's, etc. May be NULL.
+ * @select: output the signals to select the device.  Can not be NULL.
+ * @deselect: output the signals to deselect the device. Can not be NULL.
+ *
+ * The QSPI module has 4 hardware chip selects.  We don't use them.  Instead
+ * platforms are required to supply a mcfqspi_cs_control as a part of the
+ * platform data for each QSPI master controller.  Only the select and
+ * deselect functions are required.
+*/
+struct mcfqspi_cs_control {
+       int     (*setup)(struct mcfqspi_cs_control *);
+       void    (*teardown)(struct mcfqspi_cs_control *);
+       void    (*select)(struct mcfqspi_cs_control *, u8, bool);
+       void    (*deselect)(struct mcfqspi_cs_control *, u8, bool);
+};
+
+/**
+ * struct mcfqspi_platform_data - platform data for the coldfire qspi driver
+ * @bus_num: board specific identifier for this qspi driver.
+ * @num_chipselects: number of chip selects supported by this qspi driver.
+ * @cs_control: platform dependent chip select control.
+*/
+struct mcfqspi_platform_data {
+       s16     bus_num;
+       u16     num_chipselect;
+       struct mcfqspi_cs_control *cs_control;
+};
+
+#endif /* mcfqspi_h */
index 92614de..71d2ba4 100644 (file)
 #include <linux/param.h>
 #include <linux/init.h>
 #include <linux/io.h>
+#include <linux/spi/spi.h>
+#include <linux/gpio.h>
 #include <asm/machdep.h>
 #include <asm/coldfire.h>
 #include <asm/mcfsim.h>
 #include <asm/mcfuart.h>
+#include <asm/mcfqspi.h>
 
 /***************************************************************************/
 
@@ -74,9 +77,152 @@ static struct platform_device m520x_fec = {
        .resource               = m520x_fec_resources,
 };
 
+#if defined(CONFIG_SPI_COLDFIRE_QSPI) || defined(CONFIG_SPI_COLDFIRE_QSPI_MODULE)
+static struct resource m520x_qspi_resources[] = {
+       {
+               .start          = MCFQSPI_IOBASE,
+               .end            = MCFQSPI_IOBASE + MCFQSPI_IOSIZE - 1,
+               .flags          = IORESOURCE_MEM,
+       },
+       {
+               .start          = MCFINT_VECBASE + MCFINT_QSPI,
+               .end            = MCFINT_VECBASE + MCFINT_QSPI,
+               .flags          = IORESOURCE_IRQ,
+       },
+};
+
+#define MCFQSPI_CS0    62
+#define MCFQSPI_CS1    63
+#define MCFQSPI_CS2    44
+
+static int m520x_cs_setup(struct mcfqspi_cs_control *cs_control)
+{
+       int status;
+
+       status = gpio_request(MCFQSPI_CS0, "MCFQSPI_CS0");
+       if (status) {
+               pr_debug("gpio_request for MCFQSPI_CS0 failed\n");
+               goto fail0;
+       }
+       status = gpio_direction_output(MCFQSPI_CS0, 1);
+       if (status) {
+               pr_debug("gpio_direction_output for MCFQSPI_CS0 failed\n");
+               goto fail1;
+       }
+
+       status = gpio_request(MCFQSPI_CS1, "MCFQSPI_CS1");
+       if (status) {
+               pr_debug("gpio_request for MCFQSPI_CS1 failed\n");
+               goto fail1;
+       }
+       status = gpio_direction_output(MCFQSPI_CS1, 1);
+       if (status) {
+               pr_debug("gpio_direction_output for MCFQSPI_CS1 failed\n");
+               goto fail2;
+       }
+
+       status = gpio_request(MCFQSPI_CS2, "MCFQSPI_CS2");
+       if (status) {
+               pr_debug("gpio_request for MCFQSPI_CS2 failed\n");
+               goto fail2;
+       }
+       status = gpio_direction_output(MCFQSPI_CS2, 1);
+       if (status) {
+               pr_debug("gpio_direction_output for MCFQSPI_CS2 failed\n");
+               goto fail3;
+       }
+
+       return 0;
+
+fail3:
+       gpio_free(MCFQSPI_CS2);
+fail2:
+       gpio_free(MCFQSPI_CS1);
+fail1:
+       gpio_free(MCFQSPI_CS0);
+fail0:
+       return status;
+}
+
+static void m520x_cs_teardown(struct mcfqspi_cs_control *cs_control)
+{
+       gpio_free(MCFQSPI_CS2);
+       gpio_free(MCFQSPI_CS1);
+       gpio_free(MCFQSPI_CS0);
+}
+
+static void m520x_cs_select(struct mcfqspi_cs_control *cs_control,
+                           u8 chip_select, bool cs_high)
+{
+       switch (chip_select) {
+       case 0:
+               gpio_set_value(MCFQSPI_CS0, cs_high);
+               break;
+       case 1:
+               gpio_set_value(MCFQSPI_CS1, cs_high);
+               break;
+       case 2:
+               gpio_set_value(MCFQSPI_CS2, cs_high);
+               break;
+       }
+}
+
+static void m520x_cs_deselect(struct mcfqspi_cs_control *cs_control,
+                             u8 chip_select, bool cs_high)
+{
+       switch (chip_select) {
+       case 0:
+               gpio_set_value(MCFQSPI_CS0, !cs_high);
+               break;
+       case 1:
+               gpio_set_value(MCFQSPI_CS1, !cs_high);
+               break;
+       case 2:
+               gpio_set_value(MCFQSPI_CS2, !cs_high);
+               break;
+       }
+}
+
+static struct mcfqspi_cs_control m520x_cs_control = {
+       .setup                  = m520x_cs_setup,
+       .teardown               = m520x_cs_teardown,
+       .select                 = m520x_cs_select,
+       .deselect               = m520x_cs_deselect,
+};
+
+static struct mcfqspi_platform_data m520x_qspi_data = {
+       .bus_num                = 0,
+       .num_chipselect         = 3,
+       .cs_control             = &m520x_cs_control,
+};
+
+static struct platform_device m520x_qspi = {
+       .name                   = "mcfqspi",
+       .id                     = 0,
+       .num_resources          = ARRAY_SIZE(m520x_qspi_resources),
+       .resource               = m520x_qspi_resources,
+       .dev.platform_data      = &m520x_qspi_data,
+};
+
+static void __init m520x_qspi_init(void)
+{
+       u16 par;
+       /* setup Port QS for QSPI with gpio CS control */
+       writeb(0x3f, MCF_IPSBAR + MCF_GPIO_PAR_QSPI);
+       /* make U1CTS and U2RTS gpio for cs_control */
+       par = readw(MCF_IPSBAR + MCF_GPIO_PAR_UART);
+       par &= 0x00ff;
+       writew(par, MCF_IPSBAR + MCF_GPIO_PAR_UART);
+}
+#endif /* defined(CONFIG_SPI_COLDFIRE_QSPI) || defined(CONFIG_SPI_COLDFIRE_QSPI_MODULE) */
+
+
 static struct platform_device *m520x_devices[] __initdata = {
        &m520x_uart,
        &m520x_fec,
+#if defined(CONFIG_SPI_COLDFIRE_QSPI) || defined(CONFIG_SPI_COLDFIRE_QSPI_MODULE)
+       &m520x_qspi,
+#endif
 };
 
 /***************************************************************************/
@@ -147,6 +293,9 @@ void __init config_BSP(char *commandp, int size)
        mach_reset = m520x_cpu_reset;
        m520x_uarts_init();
        m520x_fec_init();
+#if defined(CONFIG_SPI_COLDFIRE_QSPI) || defined(CONFIG_SPI_COLDFIRE_QSPI_MODULE)
+       m520x_qspi_init();
+#endif
 }
 
 /***************************************************************************/
index 6ba84f2..8980f6d 100644 (file)
 #include <linux/param.h>
 #include <linux/init.h>
 #include <linux/io.h>
+#include <linux/spi/spi.h>
+#include <linux/gpio.h>
 #include <asm/machdep.h>
 #include <asm/coldfire.h>
 #include <asm/mcfsim.h>
 #include <asm/mcfuart.h>
+#include <asm/mcfqspi.h>
 
 /***************************************************************************/
 
@@ -75,9 +78,173 @@ static struct platform_device m523x_fec = {
        .resource               = m523x_fec_resources,
 };
 
+#if defined(CONFIG_SPI_COLDFIRE_QSPI) || defined(CONFIG_SPI_COLDFIRE_QSPI_MODULE)
+static struct resource m523x_qspi_resources[] = {
+       {
+               .start          = MCFQSPI_IOBASE,
+               .end            = MCFQSPI_IOBASE + MCFQSPI_IOSIZE - 1,
+               .flags          = IORESOURCE_MEM,
+       },
+       {
+               .start          = MCFINT_VECBASE + MCFINT_QSPI,
+               .end            = MCFINT_VECBASE + MCFINT_QSPI,
+               .flags          = IORESOURCE_IRQ,
+       },
+};
+
+#define MCFQSPI_CS0    91
+#define MCFQSPI_CS1    92
+#define MCFQSPI_CS2    103
+#define MCFQSPI_CS3    99
+
+static int m523x_cs_setup(struct mcfqspi_cs_control *cs_control)
+{
+       int status;
+
+       status = gpio_request(MCFQSPI_CS0, "MCFQSPI_CS0");
+       if (status) {
+               pr_debug("gpio_request for MCFQSPI_CS0 failed\n");
+               goto fail0;
+       }
+       status = gpio_direction_output(MCFQSPI_CS0, 1);
+       if (status) {
+               pr_debug("gpio_direction_output for MCFQSPI_CS0 failed\n");
+               goto fail1;
+       }
+
+       status = gpio_request(MCFQSPI_CS1, "MCFQSPI_CS1");
+       if (status) {
+               pr_debug("gpio_request for MCFQSPI_CS1 failed\n");
+               goto fail1;
+       }
+       status = gpio_direction_output(MCFQSPI_CS1, 1);
+       if (status) {
+               pr_debug("gpio_direction_output for MCFQSPI_CS1 failed\n");
+               goto fail2;
+       }
+
+       status = gpio_request(MCFQSPI_CS2, "MCFQSPI_CS2");
+       if (status) {
+               pr_debug("gpio_request for MCFQSPI_CS2 failed\n");
+               goto fail2;
+       }
+       status = gpio_direction_output(MCFQSPI_CS2, 1);
+       if (status) {
+               pr_debug("gpio_direction_output for MCFQSPI_CS2 failed\n");
+               goto fail3;
+       }
+
+       status = gpio_request(MCFQSPI_CS3, "MCFQSPI_CS3");
+       if (status) {
+               pr_debug("gpio_request for MCFQSPI_CS3 failed\n");
+               goto fail3;
+       }
+       status = gpio_direction_output(MCFQSPI_CS3, 1);
+       if (status) {
+               pr_debug("gpio_direction_output for MCFQSPI_CS3 failed\n");
+               goto fail4;
+       }
+
+       return 0;
+
+fail4:
+       gpio_free(MCFQSPI_CS3);
+fail3:
+       gpio_free(MCFQSPI_CS2);
+fail2:
+       gpio_free(MCFQSPI_CS1);
+fail1:
+       gpio_free(MCFQSPI_CS0);
+fail0:
+       return status;
+}
+
+static void m523x_cs_teardown(struct mcfqspi_cs_control *cs_control)
+{
+       gpio_free(MCFQSPI_CS3);
+       gpio_free(MCFQSPI_CS2);
+       gpio_free(MCFQSPI_CS1);
+       gpio_free(MCFQSPI_CS0);
+}
+
+static void m523x_cs_select(struct mcfqspi_cs_control *cs_control,
+                           u8 chip_select, bool cs_high)
+{
+       switch (chip_select) {
+       case 0:
+               gpio_set_value(MCFQSPI_CS0, cs_high);
+               break;
+       case 1:
+               gpio_set_value(MCFQSPI_CS1, cs_high);
+               break;
+       case 2:
+               gpio_set_value(MCFQSPI_CS2, cs_high);
+               break;
+       case 3:
+               gpio_set_value(MCFQSPI_CS3, cs_high);
+               break;
+       }
+}
+
+static void m523x_cs_deselect(struct mcfqspi_cs_control *cs_control,
+                             u8 chip_select, bool cs_high)
+{
+       switch (chip_select) {
+       case 0:
+               gpio_set_value(MCFQSPI_CS0, !cs_high);
+               break;
+       case 1:
+               gpio_set_value(MCFQSPI_CS1, !cs_high);
+               break;
+       case 2:
+               gpio_set_value(MCFQSPI_CS2, !cs_high);
+               break;
+       case 3:
+               gpio_set_value(MCFQSPI_CS3, !cs_high);
+               break;
+       }
+}
+
+static struct mcfqspi_cs_control m523x_cs_control = {
+       .setup                  = m523x_cs_setup,
+       .teardown               = m523x_cs_teardown,
+       .select                 = m523x_cs_select,
+       .deselect               = m523x_cs_deselect,
+};
+
+static struct mcfqspi_platform_data m523x_qspi_data = {
+       .bus_num                = 0,
+       .num_chipselect         = 4,
+       .cs_control             = &m523x_cs_control,
+};
+
+static struct platform_device m523x_qspi = {
+       .name                   = "mcfqspi",
+       .id                     = 0,
+       .num_resources          = ARRAY_SIZE(m523x_qspi_resources),
+       .resource               = m523x_qspi_resources,
+       .dev.platform_data      = &m523x_qspi_data,
+};
+
+static void __init m523x_qspi_init(void)
+{
+       u16 par;
+
+       /* setup QSPS pins for QSPI with gpio CS control */
+       writeb(0x1f, MCFGPIO_PAR_QSPI);
+       /* and CS2 & CS3 as gpio */
+       par = readw(MCFGPIO_PAR_TIMER);
+       par &= 0x3f3f;
+       writew(par, MCFGPIO_PAR_TIMER);
+}
+#endif /* defined(CONFIG_SPI_COLDFIRE_QSPI) || defined(CONFIG_SPI_COLDFIRE_QSPI_MODULE) */
+
 static struct platform_device *m523x_devices[] __initdata = {
        &m523x_uart,
        &m523x_fec,
+#if defined(CONFIG_SPI_COLDFIRE_QSPI) || defined(CONFIG_SPI_COLDFIRE_QSPI_MODULE)
+       &m523x_qspi,
+#endif
 };
 
 /***************************************************************************/
@@ -114,6 +281,9 @@ void __init config_BSP(char *commandp, int size)
 static int __init init_BSP(void)
 {
        m523x_fec_init();
+#if defined(CONFIG_SPI_COLDFIRE_QSPI) || defined(CONFIG_SPI_COLDFIRE_QSPI_MODULE)
+       m523x_qspi_init();
+#endif
        platform_add_devices(m523x_devices, ARRAY_SIZE(m523x_devices));
        return 0;
 }
index 646f5ba..72fc4ae 100644 (file)
 #include <linux/param.h>
 #include <linux/init.h>
 #include <linux/io.h>
+#include <linux/spi/spi.h>
+#include <linux/gpio.h>
 #include <asm/machdep.h>
 #include <asm/coldfire.h>
 #include <asm/mcfsim.h>
 #include <asm/mcfuart.h>
+#include <asm/mcfqspi.h>
 
 /***************************************************************************/
 
@@ -37,8 +40,169 @@ static struct platform_device m5249_uart = {
        .dev.platform_data      = m5249_uart_platform,
 };
 
+#if defined(CONFIG_SPI_COLDFIRE_QSPI) || defined(CONFIG_SPI_COLDFIRE_QSPI_MODULE)
+static struct resource m5249_qspi_resources[] = {
+       {
+               .start          = MCFQSPI_IOBASE,
+               .end            = MCFQSPI_IOBASE + MCFQSPI_IOSIZE - 1,
+               .flags          = IORESOURCE_MEM,
+       },
+       {
+               .start          = MCF_IRQ_QSPI,
+               .end            = MCF_IRQ_QSPI,
+               .flags          = IORESOURCE_IRQ,
+       },
+};
+
+#define MCFQSPI_CS0    29
+#define MCFQSPI_CS1    24
+#define MCFQSPI_CS2    21
+#define MCFQSPI_CS3    22
+
+static int m5249_cs_setup(struct mcfqspi_cs_control *cs_control)
+{
+       int status;
+
+       status = gpio_request(MCFQSPI_CS0, "MCFQSPI_CS0");
+       if (status) {
+               pr_debug("gpio_request for MCFQSPI_CS0 failed\n");
+               goto fail0;
+       }
+       status = gpio_direction_output(MCFQSPI_CS0, 1);
+       if (status) {
+               pr_debug("gpio_direction_output for MCFQSPI_CS0 failed\n");
+               goto fail1;
+       }
+
+       status = gpio_request(MCFQSPI_CS1, "MCFQSPI_CS1");
+       if (status) {
+               pr_debug("gpio_request for MCFQSPI_CS1 failed\n");
+               goto fail1;
+       }
+       status = gpio_direction_output(MCFQSPI_CS1, 1);
+       if (status) {
+               pr_debug("gpio_direction_output for MCFQSPI_CS1 failed\n");
+               goto fail2;
+       }
+
+       status = gpio_request(MCFQSPI_CS2, "MCFQSPI_CS2");
+       if (status) {
+               pr_debug("gpio_request for MCFQSPI_CS2 failed\n");
+               goto fail2;
+       }
+       status = gpio_direction_output(MCFQSPI_CS2, 1);
+       if (status) {
+               pr_debug("gpio_direction_output for MCFQSPI_CS2 failed\n");
+               goto fail3;
+       }
+
+       status = gpio_request(MCFQSPI_CS3, "MCFQSPI_CS3");
+       if (status) {
+               pr_debug("gpio_request for MCFQSPI_CS3 failed\n");
+               goto fail3;
+       }
+       status = gpio_direction_output(MCFQSPI_CS3, 1);
+       if (status) {
+               pr_debug("gpio_direction_output for MCFQSPI_CS3 failed\n");
+               goto fail4;
+       }
+
+       return 0;
+
+fail4:
+       gpio_free(MCFQSPI_CS3);
+fail3:
+       gpio_free(MCFQSPI_CS2);
+fail2:
+       gpio_free(MCFQSPI_CS1);
+fail1:
+       gpio_free(MCFQSPI_CS0);
+fail0:
+       return status;
+}
+
+static void m5249_cs_teardown(struct mcfqspi_cs_control *cs_control)
+{
+       gpio_free(MCFQSPI_CS3);
+       gpio_free(MCFQSPI_CS2);
+       gpio_free(MCFQSPI_CS1);
+       gpio_free(MCFQSPI_CS0);
+}
+
+static void m5249_cs_select(struct mcfqspi_cs_control *cs_control,
+                           u8 chip_select, bool cs_high)
+{
+       switch (chip_select) {
+       case 0:
+               gpio_set_value(MCFQSPI_CS0, cs_high);
+               break;
+       case 1:
+               gpio_set_value(MCFQSPI_CS1, cs_high);
+               break;
+       case 2:
+               gpio_set_value(MCFQSPI_CS2, cs_high);
+               break;
+       case 3:
+               gpio_set_value(MCFQSPI_CS3, cs_high);
+               break;
+       }
+}
+
+static void m5249_cs_deselect(struct mcfqspi_cs_control *cs_control,
+                             u8 chip_select, bool cs_high)
+{
+       switch (chip_select) {
+       case 0:
+               gpio_set_value(MCFQSPI_CS0, !cs_high);
+               break;
+       case 1:
+               gpio_set_value(MCFQSPI_CS1, !cs_high);
+               break;
+       case 2:
+               gpio_set_value(MCFQSPI_CS2, !cs_high);
+               break;
+       case 3:
+               gpio_set_value(MCFQSPI_CS3, !cs_high);
+               break;
+       }
+}
+
+static struct mcfqspi_cs_control m5249_cs_control = {
+       .setup                  = m5249_cs_setup,
+       .teardown               = m5249_cs_teardown,
+       .select                 = m5249_cs_select,
+       .deselect               = m5249_cs_deselect,
+};
+
+static struct mcfqspi_platform_data m5249_qspi_data = {
+       .bus_num                = 0,
+       .num_chipselect         = 4,
+       .cs_control             = &m5249_cs_control,
+};
+
+static struct platform_device m5249_qspi = {
+       .name                   = "mcfqspi",
+       .id                     = 0,
+       .num_resources          = ARRAY_SIZE(m5249_qspi_resources),
+       .resource               = m5249_qspi_resources,
+       .dev.platform_data      = &m5249_qspi_data,
+};
+
+static void __init m5249_qspi_init(void)
+{
+       /* QSPI irq setup */
+       writeb(MCFSIM_ICR_AUTOVEC | MCFSIM_ICR_LEVEL4 | MCFSIM_ICR_PRI0,
+              MCF_MBAR + MCFSIM_QSPIICR);
+       mcf_mapirq2imr(MCF_IRQ_QSPI, MCFINTC_QSPI);
+}
+#endif /* defined(CONFIG_SPI_COLDFIRE_QSPI) || defined(CONFIG_SPI_COLDFIRE_QSPI_MODULE) */
+
+
 static struct platform_device *m5249_devices[] __initdata = {
        &m5249_uart,
+#if defined(CONFIG_SPI_COLDFIRE_QSPI) || defined(CONFIG_SPI_COLDFIRE_QSPI_MODULE)
+       &m5249_qspi,
+#endif
 };
 
 /***************************************************************************/
@@ -100,6 +264,9 @@ void __init config_BSP(char *commandp, int size)
        mach_reset = m5249_cpu_reset;
        m5249_timers_init();
        m5249_uarts_init();
+#if defined(CONFIG_SPI_COLDFIRE_QSPI) || defined(CONFIG_SPI_COLDFIRE_QSPI_MODULE)
+       m5249_qspi_init();
+#endif
 }
 
 /***************************************************************************/
index fa51be1..3d9c35c 100644 (file)
 #include <linux/param.h>
 #include <linux/init.h>
 #include <linux/io.h>
+#include <linux/spi/spi.h>
+#include <linux/gpio.h>
 #include <asm/machdep.h>
 #include <asm/coldfire.h>
 #include <asm/mcfsim.h>
 #include <asm/mcfuart.h>
+#include <asm/mcfqspi.h>
 
 /***************************************************************************/
 
@@ -106,12 +109,188 @@ static struct platform_device m527x_fec[] = {
        },
 };
 
+#if defined(CONFIG_SPI_COLDFIRE_QSPI) || defined(CONFIG_SPI_COLDFIRE_QSPI_MODULE)
+static struct resource m527x_qspi_resources[] = {
+       {
+               .start          = MCFQSPI_IOBASE,
+               .end            = MCFQSPI_IOBASE + MCFQSPI_IOSIZE - 1,
+               .flags          = IORESOURCE_MEM,
+       },
+       {
+               .start          = MCFINT_VECBASE + MCFINT_QSPI,
+               .end            = MCFINT_VECBASE + MCFINT_QSPI,
+               .flags          = IORESOURCE_IRQ,
+       },
+};
+
+#if defined(CONFIG_M5271)
+#define MCFQSPI_CS0    91
+#define MCFQSPI_CS1    92
+#define MCFQSPI_CS2    99
+#define MCFQSPI_CS3    103
+#elif defined(CONFIG_M5275)
+#define MCFQSPI_CS0    59
+#define MCFQSPI_CS1    60
+#define MCFQSPI_CS2    61
+#define MCFQSPI_CS3    62
+#endif
+
+static int m527x_cs_setup(struct mcfqspi_cs_control *cs_control)
+{
+       int status;
+
+       status = gpio_request(MCFQSPI_CS0, "MCFQSPI_CS0");
+       if (status) {
+               pr_debug("gpio_request for MCFQSPI_CS0 failed\n");
+               goto fail0;
+       }
+       status = gpio_direction_output(MCFQSPI_CS0, 1);
+       if (status) {
+               pr_debug("gpio_direction_output for MCFQSPI_CS0 failed\n");
+               goto fail1;
+       }
+
+       status = gpio_request(MCFQSPI_CS1, "MCFQSPI_CS1");
+       if (status) {
+               pr_debug("gpio_request for MCFQSPI_CS1 failed\n");
+               goto fail1;
+       }
+       status = gpio_direction_output(MCFQSPI_CS1, 1);
+       if (status) {
+               pr_debug("gpio_direction_output for MCFQSPI_CS1 failed\n");
+               goto fail2;
+       }
+
+       status = gpio_request(MCFQSPI_CS2, "MCFQSPI_CS2");
+       if (status) {
+               pr_debug("gpio_request for MCFQSPI_CS2 failed\n");
+               goto fail2;
+       }
+       status = gpio_direction_output(MCFQSPI_CS2, 1);
+       if (status) {
+               pr_debug("gpio_direction_output for MCFQSPI_CS2 failed\n");
+               goto fail3;
+       }
+
+       status = gpio_request(MCFQSPI_CS3, "MCFQSPI_CS3");
+       if (status) {
+               pr_debug("gpio_request for MCFQSPI_CS3 failed\n");
+               goto fail3;
+       }
+       status = gpio_direction_output(MCFQSPI_CS3, 1);
+       if (status) {
+               pr_debug("gpio_direction_output for MCFQSPI_CS3 failed\n");
+               goto fail4;
+       }
+
+       return 0;
+
+fail4:
+       gpio_free(MCFQSPI_CS3);
+fail3:
+       gpio_free(MCFQSPI_CS2);
+fail2:
+       gpio_free(MCFQSPI_CS1);
+fail1:
+       gpio_free(MCFQSPI_CS0);
+fail0:
+       return status;
+}
+
+static void m527x_cs_teardown(struct mcfqspi_cs_control *cs_control)
+{
+       gpio_free(MCFQSPI_CS3);
+       gpio_free(MCFQSPI_CS2);
+       gpio_free(MCFQSPI_CS1);
+       gpio_free(MCFQSPI_CS0);
+}
+
+static void m527x_cs_select(struct mcfqspi_cs_control *cs_control,
+                           u8 chip_select, bool cs_high)
+{
+       switch (chip_select) {
+       case 0:
+               gpio_set_value(MCFQSPI_CS0, cs_high);
+               break;
+       case 1:
+               gpio_set_value(MCFQSPI_CS1, cs_high);
+               break;
+       case 2:
+               gpio_set_value(MCFQSPI_CS2, cs_high);
+               break;
+       case 3:
+               gpio_set_value(MCFQSPI_CS3, cs_high);
+               break;
+       }
+}
+
+static void m527x_cs_deselect(struct mcfqspi_cs_control *cs_control,
+                             u8 chip_select, bool cs_high)
+{
+       switch (chip_select) {
+       case 0:
+               gpio_set_value(MCFQSPI_CS0, !cs_high);
+               break;
+       case 1:
+               gpio_set_value(MCFQSPI_CS1, !cs_high);
+               break;
+       case 2:
+               gpio_set_value(MCFQSPI_CS2, !cs_high);
+               break;
+       case 3:
+               gpio_set_value(MCFQSPI_CS3, !cs_high);
+               break;
+       }
+}
+
+static struct mcfqspi_cs_control m527x_cs_control = {
+       .setup                  = m527x_cs_setup,
+       .teardown               = m527x_cs_teardown,
+       .select                 = m527x_cs_select,
+       .deselect               = m527x_cs_deselect,
+};
+
+static struct mcfqspi_platform_data m527x_qspi_data = {
+       .bus_num                = 0,
+       .num_chipselect         = 4,
+       .cs_control             = &m527x_cs_control,
+};
+
+static struct platform_device m527x_qspi = {
+       .name                   = "mcfqspi",
+       .id                     = 0,
+       .num_resources          = ARRAY_SIZE(m527x_qspi_resources),
+       .resource               = m527x_qspi_resources,
+       .dev.platform_data      = &m527x_qspi_data,
+};
+
+static void __init m527x_qspi_init(void)
+{
+#if defined(CONFIG_M5271)
+       u16 par;
+
+       /* setup QSPS pins for QSPI with gpio CS control */
+       writeb(0x1f, MCFGPIO_PAR_QSPI);
+       /* and CS2 & CS3 as gpio */
+       par = readw(MCFGPIO_PAR_TIMER);
+       par &= 0x3f3f;
+       writew(par, MCFGPIO_PAR_TIMER);
+#elif defined(CONFIG_M5275)
+       /* setup QSPS pins for QSPI with gpio CS control */
+       writew(0x003e, MCFGPIO_PAR_QSPI);
+#endif
+}
+#endif /* defined(CONFIG_SPI_COLDFIRE_QSPI) || defined(CONFIG_SPI_COLDFIRE_QSPI_MODULE) */
+
 static struct platform_device *m527x_devices[] __initdata = {
        &m527x_uart,
        &m527x_fec[0],
 #ifdef CONFIG_FEC2
        &m527x_fec[1],
 #endif
+#if defined(CONFIG_SPI_COLDFIRE_QSPI) || defined(CONFIG_SPI_COLDFIRE_QSPI_MODULE)
+       &m527x_qspi,
+#endif
 };
 
 /***************************************************************************/
@@ -187,6 +366,9 @@ void __init config_BSP(char *commandp, int size)
        mach_reset = m527x_cpu_reset;
        m527x_uarts_init();
        m527x_fec_init();
+#if defined(CONFIG_SPI_COLDFIRE_QSPI) || defined(CONFIG_SPI_COLDFIRE_QSPI_MODULE)
+       m527x_qspi_init();
+#endif
 }
 
 /***************************************************************************/
index 6e608d1..76b7433 100644 (file)
 #include <linux/init.h>
 #include <linux/platform_device.h>
 #include <linux/io.h>
+#include <linux/spi/spi.h>
+#include <linux/gpio.h>
 #include <asm/machdep.h>
 #include <asm/coldfire.h>
 #include <asm/mcfsim.h>
 #include <asm/mcfuart.h>
+#include <asm/mcfqspi.h>
 
 /***************************************************************************/
 
@@ -76,10 +79,141 @@ static struct platform_device m528x_fec = {
        .resource               = m528x_fec_resources,
 };
 
+#if defined(CONFIG_SPI_COLDFIRE_QSPI) || defined(CONFIG_SPI_COLDFIRE_QSPI_MODULE)
+static struct resource m528x_qspi_resources[] = {
+       {
+               .start          = MCFQSPI_IOBASE,
+               .end            = MCFQSPI_IOBASE + MCFQSPI_IOSIZE - 1,
+               .flags          = IORESOURCE_MEM,
+       },
+       {
+               .start          = MCFINT_VECBASE + MCFINT_QSPI,
+               .end            = MCFINT_VECBASE + MCFINT_QSPI,
+               .flags          = IORESOURCE_IRQ,
+       },
+};
+
+#define MCFQSPI_CS0    147
+#define MCFQSPI_CS1    148
+#define MCFQSPI_CS2    149
+#define MCFQSPI_CS3    150
+
+static int m528x_cs_setup(struct mcfqspi_cs_control *cs_control)
+{
+       int status;
+
+       status = gpio_request(MCFQSPI_CS0, "MCFQSPI_CS0");
+       if (status) {
+               pr_debug("gpio_request for MCFQSPI_CS0 failed\n");
+               goto fail0;
+       }
+       status = gpio_direction_output(MCFQSPI_CS0, 1);
+       if (status) {
+               pr_debug("gpio_direction_output for MCFQSPI_CS0 failed\n");
+               goto fail1;
+       }
+
+       status = gpio_request(MCFQSPI_CS1, "MCFQSPI_CS1");
+       if (status) {
+               pr_debug("gpio_request for MCFQSPI_CS1 failed\n");
+               goto fail1;
+       }
+       status = gpio_direction_output(MCFQSPI_CS1, 1);
+       if (status) {
+               pr_debug("gpio_direction_output for MCFQSPI_CS1 failed\n");
+               goto fail2;
+       }
+
+       status = gpio_request(MCFQSPI_CS2, "MCFQSPI_CS2");
+       if (status) {
+               pr_debug("gpio_request for MCFQSPI_CS2 failed\n");
+               goto fail2;
+       }
+       status = gpio_direction_output(MCFQSPI_CS2, 1);
+       if (status) {
+               pr_debug("gpio_direction_output for MCFQSPI_CS2 failed\n");
+               goto fail3;
+       }
+
+       status = gpio_request(MCFQSPI_CS3, "MCFQSPI_CS3");
+       if (status) {
+               pr_debug("gpio_request for MCFQSPI_CS3 failed\n");
+               goto fail3;
+       }
+       status = gpio_direction_output(MCFQSPI_CS3, 1);
+       if (status) {
+               pr_debug("gpio_direction_output for MCFQSPI_CS3 failed\n");
+               goto fail4;
+       }
+
+       return 0;
+
+fail4:
+       gpio_free(MCFQSPI_CS3);
+fail3:
+       gpio_free(MCFQSPI_CS2);
+fail2:
+       gpio_free(MCFQSPI_CS1);
+fail1:
+       gpio_free(MCFQSPI_CS0);
+fail0:
+       return status;
+}
+
+static void m528x_cs_teardown(struct mcfqspi_cs_control *cs_control)
+{
+       gpio_free(MCFQSPI_CS3);
+       gpio_free(MCFQSPI_CS2);
+       gpio_free(MCFQSPI_CS1);
+       gpio_free(MCFQSPI_CS0);
+}
+
+static void m528x_cs_select(struct mcfqspi_cs_control *cs_control,
+                           u8 chip_select, bool cs_high)
+{
+       gpio_set_value(MCFQSPI_CS0 + chip_select, cs_high);
+}
+
+static void m528x_cs_deselect(struct mcfqspi_cs_control *cs_control,
+                             u8 chip_select, bool cs_high)
+{
+       gpio_set_value(MCFQSPI_CS0 + chip_select, !cs_high);
+}
+
+static struct mcfqspi_cs_control m528x_cs_control = {
+       .setup                  = m528x_cs_setup,
+       .teardown               = m528x_cs_teardown,
+       .select                 = m528x_cs_select,
+       .deselect               = m528x_cs_deselect,
+};
+
+static struct mcfqspi_platform_data m528x_qspi_data = {
+       .bus_num                = 0,
+       .num_chipselect         = 4,
+       .cs_control             = &m528x_cs_control,
+};
+
+static struct platform_device m528x_qspi = {
+       .name                   = "mcfqspi",
+       .id                     = 0,
+       .num_resources          = ARRAY_SIZE(m528x_qspi_resources),
+       .resource               = m528x_qspi_resources,
+       .dev.platform_data      = &m528x_qspi_data,
+};
+
+static void __init m528x_qspi_init(void)
+{
+       /* setup Port QS for QSPI with gpio CS control */
+       __raw_writeb(0x07, MCFGPIO_PQSPAR);
+}
+#endif /* defined(CONFIG_SPI_COLDFIRE_QSPI) || defined(CONFIG_SPI_COLDFIRE_QSPI_MODULE) */
 
 static struct platform_device *m528x_devices[] __initdata = {
        &m528x_uart,
        &m528x_fec,
+#if defined(CONFIG_SPI_COLDFIRE_QSPI) || defined(CONFIG_SPI_COLDFIRE_QSPI_MODULE)
+       &m528x_qspi,
+#endif
 };
 
 /***************************************************************************/
@@ -174,6 +308,9 @@ static int __init init_BSP(void)
        mach_reset = m528x_cpu_reset;
        m528x_uarts_init();
        m528x_fec_init();
+#if defined(CONFIG_SPI_COLDFIRE_QSPI) || defined(CONFIG_SPI_COLDFIRE_QSPI_MODULE)
+       m528x_qspi_init();
+#endif
        platform_add_devices(m528x_devices, ARRAY_SIZE(m528x_devices));
        return 0;
 }
index d632948..ca51323 100644 (file)
 #include <linux/param.h>
 #include <linux/init.h>
 #include <linux/io.h>
+#include <linux/spi/spi.h>
+#include <linux/gpio.h>
 #include <asm/machdep.h>
 #include <asm/coldfire.h>
 #include <asm/mcfsim.h>
 #include <asm/mcfuart.h>
 #include <asm/mcfdma.h>
 #include <asm/mcfwdebug.h>
+#include <asm/mcfqspi.h>
 
 /***************************************************************************/
 
@@ -82,9 +85,127 @@ static struct platform_device m532x_fec = {
        .resource               = m532x_fec_resources,
 };
 
+#if defined(CONFIG_SPI_COLDFIRE_QSPI) || defined(CONFIG_SPI_COLDFIRE_QSPI_MODULE)
+static struct resource m532x_qspi_resources[] = {
+       {
+               .start          = MCFQSPI_IOBASE,
+               .end            = MCFQSPI_IOBASE + MCFQSPI_IOSIZE - 1,
+               .flags          = IORESOURCE_MEM,
+       },
+       {
+               .start          = MCFINT_VECBASE + MCFINT_QSPI,
+               .end            = MCFINT_VECBASE + MCFINT_QSPI,
+               .flags          = IORESOURCE_IRQ,
+       },
+};
+
+#define MCFQSPI_CS0    84
+#define MCFQSPI_CS1    85
+#define MCFQSPI_CS2    86
+
+static int m532x_cs_setup(struct mcfqspi_cs_control *cs_control)
+{
+       int status;
+
+       status = gpio_request(MCFQSPI_CS0, "MCFQSPI_CS0");
+       if (status) {
+               pr_debug("gpio_request for MCFQSPI_CS0 failed\n");
+               goto fail0;
+       }
+       status = gpio_direction_output(MCFQSPI_CS0, 1);
+       if (status) {
+               pr_debug("gpio_direction_output for MCFQSPI_CS0 failed\n");
+               goto fail1;
+       }
+
+       status = gpio_request(MCFQSPI_CS1, "MCFQSPI_CS1");
+       if (status) {
+               pr_debug("gpio_request for MCFQSPI_CS1 failed\n");
+               goto fail1;
+       }
+       status = gpio_direction_output(MCFQSPI_CS1, 1);
+       if (status) {
+               pr_debug("gpio_direction_output for MCFQSPI_CS1 failed\n");
+               goto fail2;
+       }
+
+       status = gpio_request(MCFQSPI_CS2, "MCFQSPI_CS2");
+       if (status) {
+               pr_debug("gpio_request for MCFQSPI_CS2 failed\n");
+               goto fail2;
+       }
+       status = gpio_direction_output(MCFQSPI_CS2, 1);
+       if (status) {
+               pr_debug("gpio_direction_output for MCFQSPI_CS2 failed\n");
+               goto fail3;
+       }
+
+       return 0;
+
+fail3:
+       gpio_free(MCFQSPI_CS2);
+fail2:
+       gpio_free(MCFQSPI_CS1);
+fail1:
+       gpio_free(MCFQSPI_CS0);
+fail0:
+       return status;
+}
+
+static void m532x_cs_teardown(struct mcfqspi_cs_control *cs_control)
+{
+       gpio_free(MCFQSPI_CS2);
+       gpio_free(MCFQSPI_CS1);
+       gpio_free(MCFQSPI_CS0);
+}
+
+static void m532x_cs_select(struct mcfqspi_cs_control *cs_control,
+                           u8 chip_select, bool cs_high)
+{
+       gpio_set_value(MCFQSPI_CS0 + chip_select, cs_high);
+}
+
+static void m532x_cs_deselect(struct mcfqspi_cs_control *cs_control,
+                             u8 chip_select, bool cs_high)
+{
+       gpio_set_value(MCFQSPI_CS0 + chip_select, !cs_high);
+}
+
+static struct mcfqspi_cs_control m532x_cs_control = {
+       .setup                  = m532x_cs_setup,
+       .teardown               = m532x_cs_teardown,
+       .select                 = m532x_cs_select,
+       .deselect               = m532x_cs_deselect,
+};
+
+static struct mcfqspi_platform_data m532x_qspi_data = {
+       .bus_num                = 0,
+       .num_chipselect         = 3,
+       .cs_control             = &m532x_cs_control,
+};
+
+static struct platform_device m532x_qspi = {
+       .name                   = "mcfqspi",
+       .id                     = 0,
+       .num_resources          = ARRAY_SIZE(m532x_qspi_resources),
+       .resource               = m532x_qspi_resources,
+       .dev.platform_data      = &m532x_qspi_data,
+};
+
+static void __init m532x_qspi_init(void)
+{
+       /* setup QSPS pins for QSPI with gpio CS control */
+       writew(0x01f0, MCF_GPIO_PAR_QSPI);
+}
+#endif /* defined(CONFIG_SPI_COLDFIRE_QSPI) || defined(CONFIG_SPI_COLDFIRE_QSPI_MODULE) */
+
+
 static struct platform_device *m532x_devices[] __initdata = {
        &m532x_uart,
        &m532x_fec,
+#if defined(CONFIG_SPI_COLDFIRE_QSPI) || defined(CONFIG_SPI_COLDFIRE_QSPI_MODULE)
+       &m532x_qspi,
+#endif
 };
 
 /***************************************************************************/
@@ -158,6 +279,9 @@ static int __init init_BSP(void)
 {
        m532x_uarts_init();
        m532x_fec_init();
+#if defined(CONFIG_SPI_COLDFIRE_QSPI) || defined(CONFIG_SPI_COLDFIRE_QSPI_MODULE)
+       m532x_qspi_init();
+#endif
        platform_add_devices(m532x_devices, ARRAY_SIZE(m532x_devices));
        return 0;
 }