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#include <mach/pxa-regs.h>
  20
  21#include "soc_common.h"
  22
  23#define GPIO_PCMCIA_S0_CD_VALID (84)
  24#define GPIO_PCMCIA_S0_RDYINT   (82)
  25#define GPIO_PCMCIA_RESET       (53)
  26
  27#define PCMCIA_S0_CD_VALID      IRQ_GPIO(GPIO_PCMCIA_S0_CD_VALID)
  28#define PCMCIA_S0_RDYINT        IRQ_GPIO(GPIO_PCMCIA_S0_RDYINT)
  29
  30
  31static struct pcmcia_irqs irqs[] = {
  32        { 0, PCMCIA_S0_CD_VALID, "PCMCIA0 CD" },
  33};
  34
  35static int cmx270_pcmcia_hw_init(struct soc_pcmcia_socket *skt)
  36{
  37        int ret = gpio_request(GPIO_PCMCIA_RESET, "PCCard reset");
  38        if (ret)
  39                return ret;
  40        gpio_direction_output(GPIO_PCMCIA_RESET, 0);
  41
  42        skt->irq = PCMCIA_S0_RDYINT;
  43        ret = soc_pcmcia_request_irqs(skt, irqs, ARRAY_SIZE(irqs));
  44        if (!ret)
  45                gpio_free(GPIO_PCMCIA_RESET);
  46
  47        return ret;
  48}
  49
  50static void cmx270_pcmcia_shutdown(struct soc_pcmcia_socket *skt)
  51{
  52        soc_pcmcia_free_irqs(skt, irqs, ARRAY_SIZE(irqs));
  53        gpio_free(GPIO_PCMCIA_RESET);
  54}
  55
  56
  57static void cmx270_pcmcia_socket_state(struct soc_pcmcia_socket *skt,
  58                                       struct pcmcia_state *state)
  59{
  60        state->detect = (gpio_get_value(GPIO_PCMCIA_S0_CD_VALID) == 0) ? 1 : 0;
  61        state->ready  = (gpio_get_value(GPIO_PCMCIA_S0_RDYINT) == 0) ? 0 : 1;
  62        state->bvd1   = 1;
  63        state->bvd2   = 1;
  64        state->vs_3v  = 0;
  65        state->vs_Xv  = 0;
  66        state->wrprot = 0;  /* not available */
  67}
  68
  69
  70static int cmx270_pcmcia_configure_socket(struct soc_pcmcia_socket *skt,
  71                                          const socket_state_t *state)
  72{
  73        switch (skt->nr) {
  74        case 0:
  75                if (state->flags & SS_RESET) {
  76                        gpio_set_value(GPIO_PCMCIA_RESET, 1);
  77                        udelay(10);
  78                        gpio_set_value(GPIO_PCMCIA_RESET, 0);
  79                }
  80                break;
  81        }
  82
  83        return 0;
  84}
  85
  86static void cmx270_pcmcia_socket_init(struct soc_pcmcia_socket *skt)
  87{
  88}
  89
  90static void cmx270_pcmcia_socket_suspend(struct soc_pcmcia_socket *skt)
  91{
  92}
  93
  94
  95static struct pcmcia_low_level cmx270_pcmcia_ops __initdata = {
  96        .owner                  = THIS_MODULE,
  97        .hw_init                = cmx270_pcmcia_hw_init,
  98        .hw_shutdown            = cmx270_pcmcia_shutdown,
  99        .socket_state           = cmx270_pcmcia_socket_state,
 100        .configure_socket       = cmx270_pcmcia_configure_socket,
 101        .socket_init            = cmx270_pcmcia_socket_init,
 102        .socket_suspend         = cmx270_pcmcia_socket_suspend,
 103        .nr                     = 1,
 104};
 105
 106static struct platform_device *cmx270_pcmcia_device;
 107
 108int __init cmx270_pcmcia_init(void)
 109{
 110        int ret;
 111
 112        cmx270_pcmcia_device = platform_device_alloc("pxa2xx-pcmcia", -1);
 113
 114        if (!cmx270_pcmcia_device)
 115                return -ENOMEM;
 116
 117        ret = platform_device_add_data(cmx270_pcmcia_device, &cmx270_pcmcia_ops,
 118                                       sizeof(cmx270_pcmcia_ops));
 119
 120        if (ret == 0) {
 121                printk(KERN_INFO "Registering cm-x270 PCMCIA interface.\n");
 122                ret = platform_device_add(cmx270_pcmcia_device);
 123        }
 124
 125        if (ret)
 126                platform_device_put(cmx270_pcmcia_device);
 127
 128        return ret;
 129}
 130
 131void __exit cmx270_pcmcia_exit(void)
 132{
 133        platform_device_unregister(cmx270_pcmcia_device);
 134}
 135