ceph: update discussion list address in MAINTAINERS
[safe/jmp/linux-2.6] / arch / arm / mach-pxa / cm-x270.c
index 5929218..a9926bb 100644 (file)
 #include <linux/sysdev.h>
 #include <linux/irq.h>
 #include <linux/gpio.h>
+#include <linux/delay.h>
 
 #include <linux/rtc-v3020.h>
 #include <video/mbxfb.h>
 
+#include <linux/spi/spi.h>
+#include <linux/spi/libertas_spi.h>
+
 #include <mach/pxa27x.h>
 #include <mach/ohci.h>
 #include <mach/mmc.h>
+#include <mach/pxa2xx_spi.h>
 
 #include "generic.h"
 
 /* MMC power enable */
 #define GPIO105_MMC_POWER      (105)
 
+/* WLAN GPIOS */
+#define GPIO19_WLAN_STRAP      (19)
+#define GPIO102_WLAN_RST       (102)
+
 static unsigned long cmx270_pin_config[] = {
        /* AC'97 */
        GPIO28_AC97_BITCLK,
@@ -62,26 +71,7 @@ static unsigned long cmx270_pin_config[] = {
        GPIO111_MMC_DAT_3,
 
        /* LCD */
-       GPIO58_LCD_LDD_0,
-       GPIO59_LCD_LDD_1,
-       GPIO60_LCD_LDD_2,
-       GPIO61_LCD_LDD_3,
-       GPIO62_LCD_LDD_4,
-       GPIO63_LCD_LDD_5,
-       GPIO64_LCD_LDD_6,
-       GPIO65_LCD_LDD_7,
-       GPIO66_LCD_LDD_8,
-       GPIO67_LCD_LDD_9,
-       GPIO68_LCD_LDD_10,
-       GPIO69_LCD_LDD_11,
-       GPIO70_LCD_LDD_12,
-       GPIO71_LCD_LDD_13,
-       GPIO72_LCD_LDD_14,
-       GPIO73_LCD_LDD_15,
-       GPIO74_LCD_FCLK,
-       GPIO75_LCD_LCLK,
-       GPIO76_LCD_PCLK,
-       GPIO77_LCD_BIAS,
+       GPIOxx_LCD_TFT_16BPP,
 
        /* I2C */
        GPIO117_I2C_SCL,
@@ -94,8 +84,8 @@ static unsigned long cmx270_pin_config[] = {
        GPIO26_SSP1_RXD,
 
        /* SSP2 */
-       GPIO19_SSP2_SCLK,
-       GPIO14_SSP2_SFRM,
+       GPIO19_GPIO,    /* SSP2 clock is used as GPIO for Libertas pin-strap */
+       GPIO14_GPIO,
        GPIO87_SSP2_TXD,
        GPIO88_SSP2_RXD,
 
@@ -123,6 +113,7 @@ static unsigned long cmx270_pin_config[] = {
        GPIO0_GPIO      | WAKEUP_ON_EDGE_BOTH,
        GPIO105_GPIO    | MFP_LPM_DRIVE_HIGH,   /* MMC/SD power */
        GPIO53_GPIO,                            /* PC card reset */
+       GPIO102_GPIO,                           /* WLAN reset */
 
        /* NAND controls */
        GPIO11_GPIO     | MFP_LPM_DRIVE_HIGH,   /* NAND CE# */
@@ -131,6 +122,7 @@ static unsigned long cmx270_pin_config[] = {
        /* interrupts */
        GPIO10_GPIO,    /* DM9000 interrupt */
        GPIO83_GPIO,    /* MMC card detect */
+       GPIO95_GPIO,    /* WLAN interrupt */
 };
 
 /* V3020 RTC */
@@ -184,33 +176,57 @@ static struct resource cmx270_2700G_resource[] = {
        },
 };
 
-static unsigned long save_lcd_regs[10];
+static unsigned long cmx270_marathon_on[] = {
+       GPIO58_GPIO,
+       GPIO59_GPIO,
+       GPIO60_GPIO,
+       GPIO61_GPIO,
+       GPIO62_GPIO,
+       GPIO63_GPIO,
+       GPIO64_GPIO,
+       GPIO65_GPIO,
+       GPIO66_GPIO,
+       GPIO67_GPIO,
+       GPIO68_GPIO,
+       GPIO69_GPIO,
+       GPIO70_GPIO,
+       GPIO71_GPIO,
+       GPIO72_GPIO,
+       GPIO73_GPIO,
+       GPIO74_GPIO,
+       GPIO75_GPIO,
+       GPIO76_GPIO,
+       GPIO77_GPIO,
+};
+
+static unsigned long cmx270_marathon_off[] = {
+       GPIOxx_LCD_TFT_16BPP,
+};
 
 static int cmx270_marathon_probe(struct fb_info *fb)
 {
-       /* save PXA-270 pin settings before enabling 2700G */
-       save_lcd_regs[0] = GPDR1;
-       save_lcd_regs[1] = GPDR2;
-       save_lcd_regs[2] = GAFR1_U;
-       save_lcd_regs[3] = GAFR2_L;
-       save_lcd_regs[4] = GAFR2_U;
-
-       /* Disable PXA-270 on-chip controller driving pins */
-       GPDR1 &= ~(0xfc000000);
-       GPDR2 &= ~(0x00c03fff);
-       GAFR1_U &= ~(0xfff00000);
-       GAFR2_L &= ~(0x0fffffff);
-       GAFR2_U &= ~(0x0000f000);
+       int gpio, err;
+
+       for (gpio = 58; gpio <= 77; gpio++) {
+               err = gpio_request(gpio, "LCD");
+               if (err)
+                       return err;
+               gpio_direction_input(gpio);
+       }
+
+       pxa2xx_mfp_config(ARRAY_AND_SIZE(cmx270_marathon_on));
        return 0;
 }
 
 static int cmx270_marathon_remove(struct fb_info *fb)
 {
-       GPDR1 =   save_lcd_regs[0];
-       GPDR2 =   save_lcd_regs[1];
-       GAFR1_U = save_lcd_regs[2];
-       GAFR2_L = save_lcd_regs[3];
-       GAFR2_U = save_lcd_regs[4];
+       int gpio;
+
+       pxa2xx_mfp_config(ARRAY_AND_SIZE(cmx270_marathon_off));
+
+       for (gpio = 58; gpio <= 77; gpio++)
+               gpio_free(gpio);
+
        return 0;
 }
 
@@ -287,6 +303,100 @@ static void __init cmx270_init_mmc(void)
 static inline void cmx270_init_mmc(void) {}
 #endif
 
+#if defined(CONFIG_SPI_PXA2XX) || defined(CONFIG_SPI_PXA2XX_MODULE)
+static struct pxa2xx_spi_master cm_x270_spi_info = {
+       .num_chipselect = 1,
+       .enable_dma     = 1,
+};
+
+static struct pxa2xx_spi_chip cm_x270_libertas_chip = {
+       .rx_threshold   = 1,
+       .tx_threshold   = 1,
+       .timeout        = 1000,
+       .gpio_cs        = 14,
+};
+
+static unsigned long cm_x270_libertas_pin_config[] = {
+       /* SSP2 */
+       GPIO19_SSP2_SCLK,
+       GPIO14_GPIO,
+       GPIO87_SSP2_TXD,
+       GPIO88_SSP2_RXD,
+
+};
+
+static int cm_x270_libertas_setup(struct spi_device *spi)
+{
+       int err = gpio_request(GPIO19_WLAN_STRAP, "WLAN STRAP");
+       if (err)
+               return err;
+
+       err = gpio_request(GPIO102_WLAN_RST, "WLAN RST");
+       if (err)
+               goto err_free_strap;
+
+       err = gpio_direction_output(GPIO102_WLAN_RST, 0);
+       if (err)
+               goto err_free_strap;
+       msleep(100);
+
+       err = gpio_direction_output(GPIO19_WLAN_STRAP, 1);
+       if (err)
+               goto err_free_strap;
+       msleep(100);
+
+       pxa2xx_mfp_config(ARRAY_AND_SIZE(cm_x270_libertas_pin_config));
+
+       gpio_set_value(GPIO102_WLAN_RST, 1);
+       msleep(100);
+
+       spi->bits_per_word = 16;
+       spi_setup(spi);
+
+       return 0;
+
+err_free_strap:
+       gpio_free(GPIO19_WLAN_STRAP);
+
+       return err;
+}
+
+static int cm_x270_libertas_teardown(struct spi_device *spi)
+{
+       gpio_set_value(GPIO102_WLAN_RST, 0);
+       gpio_free(GPIO102_WLAN_RST);
+       gpio_free(GPIO19_WLAN_STRAP);
+
+       return 0;
+}
+
+struct libertas_spi_platform_data cm_x270_libertas_pdata = {
+       .use_dummy_writes       = 1,
+       .setup                  = cm_x270_libertas_setup,
+       .teardown               = cm_x270_libertas_teardown,
+};
+
+static struct spi_board_info cm_x270_spi_devices[] __initdata = {
+       {
+               .modalias               = "libertas_spi",
+               .max_speed_hz           = 13000000,
+               .bus_num                = 2,
+               .irq                    = gpio_to_irq(95),
+               .chip_select            = 0,
+               .controller_data        = &cm_x270_libertas_chip,
+               .platform_data          = &cm_x270_libertas_pdata,
+       },
+};
+
+static void __init cmx270_init_spi(void)
+{
+       pxa2xx_set_spi_info(2, &cm_x270_spi_info);
+       spi_register_board_info(ARRAY_AND_SIZE(cm_x270_spi_devices));
+}
+#else
+static inline void cmx270_init_spi(void) {}
+#endif
+
 void __init cmx270_init(void)
 {
        pxa2xx_mfp_config(ARRAY_AND_SIZE(cmx270_pin_config));
@@ -299,4 +409,5 @@ void __init cmx270_init(void)
        cmx270_init_mmc();
        cmx270_init_ohci();
        cmx270_init_2700G();
+       cmx270_init_spi();
 }