[ARM] 2914/1: PXA Poodle: Add MMC and UDC support
[pandora-kernel.git] / arch / arm / mach-pxa / poodle.c
index 7c4a1ce..f256388 100644 (file)
@@ -30,6 +30,8 @@
 
 #include <asm/arch/pxa-regs.h>
 #include <asm/arch/irq.h>
+#include <asm/arch/mmc.h>
+#include <asm/arch/udc.h>
 #include <asm/arch/poodle.h>
 #include <asm/arch/pxafb.h>
 
@@ -93,6 +95,83 @@ static struct platform_device locomo_device = {
        .resource       = locomo_resources,
 };
 
+
+/*
+ * MMC/SD Device
+ *
+ * The card detect interrupt isn't debounced so we delay it by 250ms
+ * to give the card a chance to fully insert/eject.
+ */
+static struct pxamci_platform_data poodle_mci_platform_data;
+
+static int poodle_mci_init(struct device *dev, irqreturn_t (*poodle_detect_int)(int, void *, struct pt_regs *), void *data)
+{
+       int err;
+
+       /* setup GPIO for PXA25x MMC controller */
+       pxa_gpio_mode(GPIO6_MMCCLK_MD);
+       pxa_gpio_mode(GPIO8_MMCCS0_MD);
+       pxa_gpio_mode(POODLE_GPIO_nSD_DETECT | GPIO_IN);
+       pxa_gpio_mode(POODLE_GPIO_SD_PWR | GPIO_OUT);
+
+       poodle_mci_platform_data.detect_delay = msecs_to_jiffies(250);
+
+       err = request_irq(POODLE_IRQ_GPIO_nSD_DETECT, poodle_detect_int, SA_INTERRUPT,
+                            "MMC card detect", data);
+       if (err) {
+               printk(KERN_ERR "poodle_mci_init: MMC/SD: can't request MMC card detect IRQ\n");
+               return -1;
+       }
+
+       set_irq_type(POODLE_IRQ_GPIO_nSD_DETECT, IRQT_BOTHEDGE);
+
+       return 0;
+}
+
+static void poodle_mci_setpower(struct device *dev, unsigned int vdd)
+{
+       struct pxamci_platform_data* p_d = dev->platform_data;
+
+       if (( 1 << vdd) & p_d->ocr_mask)
+               GPSR1 = GPIO_bit(POODLE_GPIO_SD_PWR);
+       else
+               GPCR1 = GPIO_bit(POODLE_GPIO_SD_PWR);
+}
+
+static void poodle_mci_exit(struct device *dev, void *data)
+{
+       free_irq(POODLE_IRQ_GPIO_nSD_DETECT, data);
+}
+
+static struct pxamci_platform_data poodle_mci_platform_data = {
+       .ocr_mask       = MMC_VDD_32_33|MMC_VDD_33_34,
+       .init           = poodle_mci_init,
+       .setpower       = poodle_mci_setpower,
+       .exit           = poodle_mci_exit,
+};
+
+
+/*
+ * USB Device Controller
+ */
+static void poodle_udc_command(int cmd)
+{
+       switch(cmd)     {
+       case PXA2XX_UDC_CMD_CONNECT:
+               GPSR(POODLE_GPIO_USB_PULLUP) = GPIO_bit(POODLE_GPIO_USB_PULLUP);
+               break;
+       case PXA2XX_UDC_CMD_DISCONNECT:
+               GPCR(POODLE_GPIO_USB_PULLUP) = GPIO_bit(POODLE_GPIO_USB_PULLUP);
+               break;
+       }
+}
+
+static struct pxa2xx_udc_mach_info udc_info __initdata = {
+       /* no connect GPIO; poodle can't tell connection status */
+       .udc_command            = poodle_udc_command,
+};
+
+
 /* PXAFB device */
 static struct pxafb_mach_info poodle_fb_info __initdata = {
        .pixclock       = 144700,
@@ -164,6 +243,9 @@ static void __init poodle_init(void)
         GPSR2 = 0x00000000;
 
        set_pxa_fb_info(&poodle_fb_info);
+       pxa_gpio_mode(POODLE_GPIO_USB_PULLUP | GPIO_OUT);
+       pxa_set_udc_info(&udc_info);
+       pxa_set_mci_info(&poodle_mci_platform_data);
 
        scoop_num = 1;
        scoop_devs = &poodle_pcmcia_scoop[0];