linux/drivers/pcmcia/pxa2xx_cm_x270.c
<<
>>
Prefs
   1/*
   2 * linux/drivers/pcmcia/pxa/pxa_cm_x270.c
   3 *
   4 * This program is free software; you can redistribute it and/or modify
   5 * it under the terms of the GNU General Public License version 2 as
   6 * published by the Free Software Foundation.
   7 *
   8 * Compulab Ltd., 2003, 2007, 2008
   9 * Mike Rapoport <mike@compulab.co.il>
  10 *
  11 */
  12
  13#include <linux/platform_device.h>
  14#include <linux/irq.h>
  15#include <linux/delay.h>
  16#include <linux/gpio.h>
  17
  18#include <asm/mach-types.h>
  19
  20#include "soc_common.h"
  21
  22#define GPIO_PCMCIA_S0_CD_VALID (84)
  23#define GPIO_PCMCIA_S0_RDYINT   (82)
  24#define GPIO_PCMCIA_RESET       (53)
  25
  26#define PCMCIA_S0_CD_VALID      IRQ_GPIO(GPIO_PCMCIA_S0_CD_VALID)
  27#define PCMCIA_S0_RDYINT        IRQ_GPIO(GPIO_PCMCIA_S0_RDYINT)
  28
  29
  30static struct pcmcia_irqs irqs[] = {
  31        { 0, PCMCIA_S0_CD_VALID, "PCMCIA0 CD" },
  32};
  33
  34static int cmx270_pcmcia_hw_init(struct soc_pcmcia_socket *skt)
  35{
  36        int ret = gpio_request(GPIO_PCMCIA_RESET, "PCCard reset");
  37        if (ret)
  38                return ret;
  39        gpio_direction_output(GPIO_PCMCIA_RESET, 0);
  40
  41        skt->socket.pci_irq = PCMCIA_S0_RDYINT;
  42        ret = soc_pcmcia_request_irqs(skt, irqs, ARRAY_SIZE(irqs));
  43        if (!ret)
  44                gpio_free(GPIO_PCMCIA_RESET);
  45
  46        return ret;
  47}
  48
  49static void cmx270_pcmcia_shutdown(struct soc_pcmcia_socket *skt)
  50{
  51        soc_pcmcia_free_irqs(skt, irqs, ARRAY_SIZE(irqs));
  52        gpio_free(GPIO_PCMCIA_RESET);
  53}
  54
  55
  56static void cmx270_pcmcia_socket_state(struct soc_pcmcia_socket *skt,
  57                                       struct pcmcia_state *state)
  58{
  59        state->detect = (gpio_get_value(GPIO_PCMCIA_S0_CD_VALID) == 0) ? 1 : 0;
  60        state->ready  = (gpio_get_value(GPIO_PCMCIA_S0_RDYINT) == 0) ? 0 : 1;
  61        state->bvd1   = 1;
  62        state->bvd2   = 1;
  63        state->vs_3v  = 0;
  64        state->vs_Xv  = 0;
  65        state->wrprot = 0;  /* not available */
  66}
  67
  68
  69static int cmx270_pcmcia_configure_socket(struct soc_pcmcia_socket *skt,
  70                                          const socket_state_t *state)
  71{
  72        switch (skt->nr) {
  73        case 0:
  74                if (state->flags & SS_RESET) {
  75                        gpio_set_value(GPIO_PCMCIA_RESET, 1);
  76                        udelay(10);
  77                        gpio_set_value(GPIO_PCMCIA_RESET, 0);
  78                }
  79                break;
  80        }
  81
  82        return 0;
  83}
  84
  85static void cmx270_pcmcia_socket_init(struct soc_pcmcia_socket *skt)
  86{
  87}
  88
  89static void cmx270_pcmcia_socket_suspend(struct soc_pcmcia_socket *skt)
  90{
  91}
  92
  93
  94static struct pcmcia_low_level cmx270_pcmcia_ops __initdata = {
  95        .owner                  = THIS_MODULE,
  96        .hw_init                = cmx270_pcmcia_hw_init,
  97        .hw_shutdown            = cmx270_pcmcia_shutdown,
  98        .socket_state           = cmx270_pcmcia_socket_state,
  99        .configure_socket       = cmx270_pcmcia_configure_socket,
 100        .socket_init            = cmx270_pcmcia_socket_init,
 101        .socket_suspend         = cmx270_pcmcia_socket_suspend,
 102        .nr                     = 1,
 103};
 104
 105static struct platform_device *cmx270_pcmcia_device;
 106
 107int __init cmx270_pcmcia_init(void)
 108{
 109        int ret;
 110
 111        cmx270_pcmcia_device = platform_device_alloc("pxa2xx-pcmcia", -1);
 112
 113        if (!cmx270_pcmcia_device)
 114                return -ENOMEM;
 115
 116        ret = platform_device_add_data(cmx270_pcmcia_device, &cmx270_pcmcia_ops,
 117                                       sizeof(cmx270_pcmcia_ops));
 118
 119        if (ret == 0) {
 120                printk(KERN_INFO "Registering cm-x270 PCMCIA interface.\n");
 121                ret = platform_device_add(cmx270_pcmcia_device);
 122        }
 123
 124        if (ret)
 125                platform_device_put(cmx270_pcmcia_device);
 126
 127        return ret;
 128}
 129
 130void __exit cmx270_pcmcia_exit(void)
 131{
 132        platform_device_unregister(cmx270_pcmcia_device);
 133}
 134