linux/drivers/pcmcia/pxa2xx_cm_x255.c
<<
>>
Prefs
   1/*
   2 * linux/drivers/pcmcia/pxa/pxa_cm_x255.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_SKTSEL      (54)
  23#define GPIO_PCMCIA_S0_CD_VALID (16)
  24#define GPIO_PCMCIA_S1_CD_VALID (17)
  25#define GPIO_PCMCIA_S0_RDYINT   (6)
  26#define GPIO_PCMCIA_S1_RDYINT   (8)
  27#define GPIO_PCMCIA_RESET       (9)
  28
  29#define PCMCIA_S0_CD_VALID      IRQ_GPIO(GPIO_PCMCIA_S0_CD_VALID)
  30#define PCMCIA_S1_CD_VALID      IRQ_GPIO(GPIO_PCMCIA_S1_CD_VALID)
  31#define PCMCIA_S0_RDYINT        IRQ_GPIO(GPIO_PCMCIA_S0_RDYINT)
  32#define PCMCIA_S1_RDYINT        IRQ_GPIO(GPIO_PCMCIA_S1_RDYINT)
  33
  34
  35static struct pcmcia_irqs irqs[] = {
  36        { 0, PCMCIA_S0_CD_VALID, "PCMCIA0 CD" },
  37        { 1, PCMCIA_S1_CD_VALID, "PCMCIA1 CD" },
  38};
  39
  40static int cmx255_pcmcia_hw_init(struct soc_pcmcia_socket *skt)
  41{
  42        int ret = gpio_request(GPIO_PCMCIA_RESET, "PCCard reset");
  43        if (ret)
  44                return ret;
  45        gpio_direction_output(GPIO_PCMCIA_RESET, 0);
  46
  47        skt->irq = skt->nr == 0 ? PCMCIA_S0_RDYINT : PCMCIA_S1_RDYINT;
  48        ret = soc_pcmcia_request_irqs(skt, irqs, ARRAY_SIZE(irqs));
  49        if (!ret)
  50                gpio_free(GPIO_PCMCIA_RESET);
  51
  52        return ret;
  53}
  54
  55static void cmx255_pcmcia_shutdown(struct soc_pcmcia_socket *skt)
  56{
  57        soc_pcmcia_free_irqs(skt, irqs, ARRAY_SIZE(irqs));
  58        gpio_free(GPIO_PCMCIA_RESET);
  59}
  60
  61
  62static void cmx255_pcmcia_socket_state(struct soc_pcmcia_socket *skt,
  63                                       struct pcmcia_state *state)
  64{
  65        int cd = skt->nr ? GPIO_PCMCIA_S1_CD_VALID : GPIO_PCMCIA_S0_CD_VALID;
  66        int rdy = skt->nr ? GPIO_PCMCIA_S1_RDYINT : GPIO_PCMCIA_S0_RDYINT;
  67
  68        state->detect = !gpio_get_value(cd);
  69        state->ready  = !!gpio_get_value(rdy);
  70        state->bvd1   = 1;
  71        state->bvd2   = 1;
  72        state->vs_3v  = 0;
  73        state->vs_Xv  = 0;
  74        state->wrprot = 0;  /* not available */
  75}
  76
  77
  78static int cmx255_pcmcia_configure_socket(struct soc_pcmcia_socket *skt,
  79                                          const socket_state_t *state)
  80{
  81        switch (skt->nr) {
  82        case 0:
  83                if (state->flags & SS_RESET) {
  84                        gpio_set_value(GPIO_PCMCIA_SKTSEL, 0);
  85                        udelay(1);
  86                        gpio_set_value(GPIO_PCMCIA_RESET, 1);
  87                        udelay(10);
  88                        gpio_set_value(GPIO_PCMCIA_RESET, 0);
  89                }
  90                break;
  91        case 1:
  92                if (state->flags & SS_RESET) {
  93                        gpio_set_value(GPIO_PCMCIA_SKTSEL, 1);
  94                        udelay(1);
  95                        gpio_set_value(GPIO_PCMCIA_RESET, 1);
  96                        udelay(10);
  97                        gpio_set_value(GPIO_PCMCIA_RESET, 0);
  98                }
  99                break;
 100        }
 101
 102        return 0;
 103}
 104
 105static void cmx255_pcmcia_socket_init(struct soc_pcmcia_socket *skt)
 106{
 107}
 108
 109static void cmx255_pcmcia_socket_suspend(struct soc_pcmcia_socket *skt)
 110{
 111}
 112
 113
 114static struct pcmcia_low_level cmx255_pcmcia_ops __initdata = {
 115        .owner                  = THIS_MODULE,
 116        .hw_init                = cmx255_pcmcia_hw_init,
 117        .hw_shutdown            = cmx255_pcmcia_shutdown,
 118        .socket_state           = cmx255_pcmcia_socket_state,
 119        .configure_socket       = cmx255_pcmcia_configure_socket,
 120        .socket_init            = cmx255_pcmcia_socket_init,
 121        .socket_suspend         = cmx255_pcmcia_socket_suspend,
 122        .nr                     = 1,
 123};
 124
 125static struct platform_device *cmx255_pcmcia_device;
 126
 127int __init cmx255_pcmcia_init(void)
 128{
 129        int ret;
 130
 131        cmx255_pcmcia_device = platform_device_alloc("pxa2xx-pcmcia", -1);
 132
 133        if (!cmx255_pcmcia_device)
 134                return -ENOMEM;
 135
 136        ret = platform_device_add_data(cmx255_pcmcia_device, &cmx255_pcmcia_ops,
 137                                       sizeof(cmx255_pcmcia_ops));
 138
 139        if (ret == 0) {
 140                printk(KERN_INFO "Registering cm-x255 PCMCIA interface.\n");
 141                ret = platform_device_add(cmx255_pcmcia_device);
 142        }
 143
 144        if (ret)
 145                platform_device_put(cmx255_pcmcia_device);
 146
 147        return ret;
 148}
 149
 150void __exit cmx255_pcmcia_exit(void)
 151{
 152        platform_device_unregister(cmx255_pcmcia_device);
 153}
 154