Commit 960c0acaabf603e39b121ae5c0580aaca6f8aa7b

Authored by Marek Vasut
Committed by Eric Miao
1 parent a4257af5b0

ARM: pxa: Toradex Colibri PXA270 CF support

This driver also contains structures to eventually support PXA320. This is
planned to be added in a later patch.

Signed-off-by: Marek Vasut <marek.vasut@gmail.com>
Acked-by: Daniel Mack <daniel@caiaq.de>
Signed-off-by: Eric Miao <eric.y.miao@gmail.com>

Showing 4 changed files with 234 additions and 1 deletions Side-by-side Diff

arch/arm/mach-pxa/colibri-pxa270-evalboard.c
... ... @@ -51,6 +51,24 @@
51 51 GPIO89_USBH1_PEN,
52 52 GPIO119_USBH2_PWR,
53 53 GPIO120_USBH2_PEN,
  54 +
  55 + /* PCMCIA */
  56 + GPIO85_nPCE_1,
  57 + GPIO54_nPCE_2,
  58 + GPIO55_nPREG,
  59 + GPIO50_nPIOR,
  60 + GPIO51_nPIOW,
  61 + GPIO49_nPWE,
  62 + GPIO48_nPOE,
  63 + GPIO57_nIOIS16,
  64 + GPIO56_nPWAIT,
  65 + GPIO104_PSKTSEL,
  66 + GPIO53_GPIO, /* RESET */
  67 + GPIO83_GPIO, /* BVD1 */
  68 + GPIO82_GPIO, /* BVD2 */
  69 + GPIO1_GPIO, /* READY */
  70 + GPIO84_GPIO, /* DETECT */
  71 + GPIO107_GPIO, /* PPEN */
54 72 };
55 73  
56 74 /******************************************************************************
drivers/pcmcia/Kconfig
... ... @@ -215,7 +215,7 @@
215 215 depends on (ARCH_LUBBOCK || MACH_MAINSTONE || PXA_SHARPSL \
216 216 || MACH_ARMCORE || ARCH_PXA_PALM || TRIZEPS_PCMCIA \
217 217 || ARCOM_PCMCIA || ARCH_PXA_ESERIES || MACH_STARGATE2 \
218   - || MACH_VPAC270 || MACH_BALLOON3)
  218 + || MACH_VPAC270 || MACH_BALLOON3 || MACH_COLIBRI)
219 219 select PCMCIA_SOC_COMMON
220 220 help
221 221 Say Y here to include support for the PXA2xx PCMCIA controller
drivers/pcmcia/Makefile
... ... @@ -70,6 +70,7 @@
70 70 pxa2xx-obj-$(CONFIG_MACH_STARGATE2) += pxa2xx_stargate2.o
71 71 pxa2xx-obj-$(CONFIG_MACH_VPAC270) += pxa2xx_vpac270.o
72 72 pxa2xx-obj-$(CONFIG_MACH_BALLOON3) += pxa2xx_balloon3.o
  73 +pxa2xx-obj-$(CONFIG_MACH_COLIBRI) += pxa2xx_colibri.o
73 74  
74 75 obj-$(CONFIG_PCMCIA_PXA2XX) += pxa2xx_base.o $(pxa2xx-obj-y)
75 76  
drivers/pcmcia/pxa2xx_colibri.c
  1 +/*
  2 + * linux/drivers/pcmcia/pxa2xx_colibri.c
  3 + *
  4 + * Driver for Toradex Colibri PXA270 CF socket
  5 + *
  6 + * Copyright (C) 2010 Marek Vasut <marek.vasut@gmail.com>
  7 + *
  8 + * This program is free software; you can redistribute it and/or modify
  9 + * it under the terms of the GNU General Public License version 2 as
  10 + * published by the Free Software Foundation.
  11 + *
  12 + */
  13 +
  14 +#include <linux/module.h>
  15 +#include <linux/platform_device.h>
  16 +#include <linux/delay.h>
  17 +#include <linux/gpio.h>
  18 +
  19 +#include <asm/mach-types.h>
  20 +
  21 +#include "soc_common.h"
  22 +
  23 +#define COLIBRI270_RESET_GPIO 53
  24 +#define COLIBRI270_PPEN_GPIO 107
  25 +#define COLIBRI270_BVD1_GPIO 83
  26 +#define COLIBRI270_BVD2_GPIO 82
  27 +#define COLIBRI270_DETECT_GPIO 84
  28 +#define COLIBRI270_READY_GPIO 1
  29 +
  30 +static struct {
  31 + int reset_gpio;
  32 + int ppen_gpio;
  33 + int bvd1_gpio;
  34 + int bvd2_gpio;
  35 + int detect_gpio;
  36 + int ready_gpio;
  37 +} colibri_pcmcia_gpio;
  38 +
  39 +static struct pcmcia_irqs colibri_irqs[] = {
  40 + {
  41 + .sock = 0,
  42 + .str = "PCMCIA CD"
  43 + },
  44 +};
  45 +
  46 +static int colibri_pcmcia_hw_init(struct soc_pcmcia_socket *skt)
  47 +{
  48 + int ret;
  49 +
  50 + ret = gpio_request(colibri_pcmcia_gpio.detect_gpio, "DETECT");
  51 + if (ret)
  52 + goto err1;
  53 + ret = gpio_direction_input(colibri_pcmcia_gpio.detect_gpio);
  54 + if (ret)
  55 + goto err2;
  56 +
  57 + ret = gpio_request(colibri_pcmcia_gpio.ready_gpio, "READY");
  58 + if (ret)
  59 + goto err2;
  60 + ret = gpio_direction_input(colibri_pcmcia_gpio.ready_gpio);
  61 + if (ret)
  62 + goto err3;
  63 +
  64 + ret = gpio_request(colibri_pcmcia_gpio.bvd1_gpio, "BVD1");
  65 + if (ret)
  66 + goto err3;
  67 + ret = gpio_direction_input(colibri_pcmcia_gpio.bvd1_gpio);
  68 + if (ret)
  69 + goto err4;
  70 +
  71 + ret = gpio_request(colibri_pcmcia_gpio.bvd2_gpio, "BVD2");
  72 + if (ret)
  73 + goto err4;
  74 + ret = gpio_direction_input(colibri_pcmcia_gpio.bvd2_gpio);
  75 + if (ret)
  76 + goto err5;
  77 +
  78 + ret = gpio_request(colibri_pcmcia_gpio.ppen_gpio, "PPEN");
  79 + if (ret)
  80 + goto err5;
  81 + ret = gpio_direction_output(colibri_pcmcia_gpio.ppen_gpio, 0);
  82 + if (ret)
  83 + goto err6;
  84 +
  85 + ret = gpio_request(colibri_pcmcia_gpio.reset_gpio, "RESET");
  86 + if (ret)
  87 + goto err6;
  88 + ret = gpio_direction_output(colibri_pcmcia_gpio.reset_gpio, 1);
  89 + if (ret)
  90 + goto err7;
  91 +
  92 + colibri_irqs[0].irq = gpio_to_irq(colibri_pcmcia_gpio.detect_gpio);
  93 + skt->socket.pci_irq = gpio_to_irq(colibri_pcmcia_gpio.ready_gpio);
  94 +
  95 + return soc_pcmcia_request_irqs(skt, colibri_irqs,
  96 + ARRAY_SIZE(colibri_irqs));
  97 +
  98 +err7:
  99 + gpio_free(colibri_pcmcia_gpio.detect_gpio);
  100 +err6:
  101 + gpio_free(colibri_pcmcia_gpio.ready_gpio);
  102 +err5:
  103 + gpio_free(colibri_pcmcia_gpio.bvd1_gpio);
  104 +err4:
  105 + gpio_free(colibri_pcmcia_gpio.bvd2_gpio);
  106 +err3:
  107 + gpio_free(colibri_pcmcia_gpio.reset_gpio);
  108 +err2:
  109 + gpio_free(colibri_pcmcia_gpio.ppen_gpio);
  110 +err1:
  111 + return ret;
  112 +}
  113 +
  114 +static void colibri_pcmcia_hw_shutdown(struct soc_pcmcia_socket *skt)
  115 +{
  116 + gpio_free(colibri_pcmcia_gpio.detect_gpio);
  117 + gpio_free(colibri_pcmcia_gpio.ready_gpio);
  118 + gpio_free(colibri_pcmcia_gpio.bvd1_gpio);
  119 + gpio_free(colibri_pcmcia_gpio.bvd2_gpio);
  120 + gpio_free(colibri_pcmcia_gpio.reset_gpio);
  121 + gpio_free(colibri_pcmcia_gpio.ppen_gpio);
  122 +}
  123 +
  124 +static void colibri_pcmcia_socket_state(struct soc_pcmcia_socket *skt,
  125 + struct pcmcia_state *state)
  126 +{
  127 +
  128 + state->detect = !!gpio_get_value(colibri_pcmcia_gpio.detect_gpio);
  129 + state->ready = !!gpio_get_value(colibri_pcmcia_gpio.ready_gpio);
  130 + state->bvd1 = !!gpio_get_value(colibri_pcmcia_gpio.bvd1_gpio);
  131 + state->bvd2 = !!gpio_get_value(colibri_pcmcia_gpio.bvd2_gpio);
  132 + state->wrprot = 0;
  133 + state->vs_3v = 1;
  134 + state->vs_Xv = 0;
  135 +}
  136 +
  137 +static int
  138 +colibri_pcmcia_configure_socket(struct soc_pcmcia_socket *skt,
  139 + const socket_state_t *state)
  140 +{
  141 + gpio_set_value(colibri_pcmcia_gpio.ppen_gpio,
  142 + !(state->Vcc == 33 && state->Vpp < 50));
  143 + gpio_set_value(colibri_pcmcia_gpio.reset_gpio, state->flags & SS_RESET);
  144 + return 0;
  145 +}
  146 +
  147 +static void colibri_pcmcia_socket_init(struct soc_pcmcia_socket *skt)
  148 +{
  149 +}
  150 +
  151 +static void colibri_pcmcia_socket_suspend(struct soc_pcmcia_socket *skt)
  152 +{
  153 +}
  154 +
  155 +static struct pcmcia_low_level colibri_pcmcia_ops = {
  156 + .owner = THIS_MODULE,
  157 +
  158 + .first = 0,
  159 + .nr = 1,
  160 +
  161 + .hw_init = colibri_pcmcia_hw_init,
  162 + .hw_shutdown = colibri_pcmcia_hw_shutdown,
  163 +
  164 + .socket_state = colibri_pcmcia_socket_state,
  165 + .configure_socket = colibri_pcmcia_configure_socket,
  166 +
  167 + .socket_init = colibri_pcmcia_socket_init,
  168 + .socket_suspend = colibri_pcmcia_socket_suspend,
  169 +};
  170 +
  171 +static struct platform_device *colibri_pcmcia_device;
  172 +
  173 +static int __init colibri_pcmcia_init(void)
  174 +{
  175 + int ret;
  176 +
  177 + colibri_pcmcia_device = platform_device_alloc("pxa2xx-pcmcia", -1);
  178 + if (!colibri_pcmcia_device)
  179 + return -ENOMEM;
  180 +
  181 + /* Colibri PXA270 */
  182 + if (machine_is_colibri()) {
  183 + colibri_pcmcia_gpio.reset_gpio = COLIBRI270_RESET_GPIO;
  184 + colibri_pcmcia_gpio.ppen_gpio = COLIBRI270_PPEN_GPIO;
  185 + colibri_pcmcia_gpio.bvd1_gpio = COLIBRI270_BVD1_GPIO;
  186 + colibri_pcmcia_gpio.bvd2_gpio = COLIBRI270_BVD2_GPIO;
  187 + colibri_pcmcia_gpio.detect_gpio = COLIBRI270_DETECT_GPIO;
  188 + colibri_pcmcia_gpio.ready_gpio = COLIBRI270_READY_GPIO;
  189 + }
  190 +
  191 + ret = platform_device_add_data(colibri_pcmcia_device,
  192 + &colibri_pcmcia_ops, sizeof(colibri_pcmcia_ops));
  193 +
  194 + if (!ret)
  195 + ret = platform_device_add(colibri_pcmcia_device);
  196 +
  197 + if (ret)
  198 + platform_device_put(colibri_pcmcia_device);
  199 +
  200 + return ret;
  201 +}
  202 +
  203 +static void __exit colibri_pcmcia_exit(void)
  204 +{
  205 + platform_device_unregister(colibri_pcmcia_device);
  206 +}
  207 +
  208 +module_init(colibri_pcmcia_init);
  209 +module_exit(colibri_pcmcia_exit);
  210 +
  211 +MODULE_AUTHOR("Marek Vasut <marek.vasut@gmail.com>");
  212 +MODULE_DESCRIPTION("PCMCIA support for Toradex Colibri PXA270");
  213 +MODULE_ALIAS("platform:pxa2xx-pcmcia");
  214 +MODULE_LICENSE("GPL");