linux/drivers/pcmcia/pxa2xx_palmtx.c
<<
>>
Prefs
   1/*
   2 * linux/drivers/pcmcia/pxa2xx_palmtx.c
   3 *
   4 * Driver for Palm T|X PCMCIA
   5 *
   6 * Copyright (C) 2007-2008 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
  17#include <asm/mach-types.h>
  18
  19#include <mach/gpio.h>
  20#include <mach/palmtx.h>
  21
  22#include "soc_common.h"
  23
  24static int palmtx_pcmcia_hw_init(struct soc_pcmcia_socket *skt)
  25{
  26        int ret;
  27
  28        ret = gpio_request(GPIO_NR_PALMTX_PCMCIA_POWER1, "PCMCIA PWR1");
  29        if (ret)
  30                goto err1;
  31        ret = gpio_direction_output(GPIO_NR_PALMTX_PCMCIA_POWER1, 0);
  32        if (ret)
  33                goto err2;
  34
  35        ret = gpio_request(GPIO_NR_PALMTX_PCMCIA_POWER2, "PCMCIA PWR2");
  36        if (ret)
  37                goto err2;
  38        ret = gpio_direction_output(GPIO_NR_PALMTX_PCMCIA_POWER2, 0);
  39        if (ret)
  40                goto err3;
  41
  42        ret = gpio_request(GPIO_NR_PALMTX_PCMCIA_RESET, "PCMCIA RST");
  43        if (ret)
  44                goto err3;
  45        ret = gpio_direction_output(GPIO_NR_PALMTX_PCMCIA_RESET, 1);
  46        if (ret)
  47                goto err4;
  48
  49        ret = gpio_request(GPIO_NR_PALMTX_PCMCIA_READY, "PCMCIA RDY");
  50        if (ret)
  51                goto err4;
  52        ret = gpio_direction_input(GPIO_NR_PALMTX_PCMCIA_READY);
  53        if (ret)
  54                goto err5;
  55
  56        skt->irq = gpio_to_irq(GPIO_NR_PALMTX_PCMCIA_READY);
  57        return 0;
  58
  59err5:
  60        gpio_free(GPIO_NR_PALMTX_PCMCIA_READY);
  61err4:
  62        gpio_free(GPIO_NR_PALMTX_PCMCIA_RESET);
  63err3:
  64        gpio_free(GPIO_NR_PALMTX_PCMCIA_POWER2);
  65err2:
  66        gpio_free(GPIO_NR_PALMTX_PCMCIA_POWER1);
  67err1:
  68        return ret;
  69}
  70
  71static void palmtx_pcmcia_hw_shutdown(struct soc_pcmcia_socket *skt)
  72{
  73        gpio_free(GPIO_NR_PALMTX_PCMCIA_READY);
  74        gpio_free(GPIO_NR_PALMTX_PCMCIA_RESET);
  75        gpio_free(GPIO_NR_PALMTX_PCMCIA_POWER2);
  76        gpio_free(GPIO_NR_PALMTX_PCMCIA_POWER1);
  77}
  78
  79static void palmtx_pcmcia_socket_state(struct soc_pcmcia_socket *skt,
  80                                        struct pcmcia_state *state)
  81{
  82        state->detect = 1; /* always inserted */
  83        state->ready  = !!gpio_get_value(GPIO_NR_PALMTX_PCMCIA_READY);
  84        state->bvd1   = 1;
  85        state->bvd2   = 1;
  86        state->wrprot = 0;
  87        state->vs_3v  = 1;
  88        state->vs_Xv  = 0;
  89}
  90
  91static int
  92palmtx_pcmcia_configure_socket(struct soc_pcmcia_socket *skt,
  93                                const socket_state_t *state)
  94{
  95        gpio_set_value(GPIO_NR_PALMTX_PCMCIA_POWER1, 1);
  96        gpio_set_value(GPIO_NR_PALMTX_PCMCIA_POWER2, 1);
  97        gpio_set_value(GPIO_NR_PALMTX_PCMCIA_RESET,
  98                        !!(state->flags & SS_RESET));
  99
 100        return 0;
 101}
 102
 103static void palmtx_pcmcia_socket_init(struct soc_pcmcia_socket *skt)
 104{
 105}
 106
 107static void palmtx_pcmcia_socket_suspend(struct soc_pcmcia_socket *skt)
 108{
 109}
 110
 111static struct pcmcia_low_level palmtx_pcmcia_ops = {
 112        .owner                  = THIS_MODULE,
 113
 114        .first                  = 0,
 115        .nr                     = 1,
 116
 117        .hw_init                = palmtx_pcmcia_hw_init,
 118        .hw_shutdown            = palmtx_pcmcia_hw_shutdown,
 119
 120        .socket_state           = palmtx_pcmcia_socket_state,
 121        .configure_socket       = palmtx_pcmcia_configure_socket,
 122
 123        .socket_init            = palmtx_pcmcia_socket_init,
 124        .socket_suspend         = palmtx_pcmcia_socket_suspend,
 125};
 126
 127static struct platform_device *palmtx_pcmcia_device;
 128
 129static int __init palmtx_pcmcia_init(void)
 130{
 131        int ret;
 132
 133        if (!machine_is_palmtx())
 134                return -ENODEV;
 135
 136        palmtx_pcmcia_device = platform_device_alloc("pxa2xx-pcmcia", -1);
 137        if (!palmtx_pcmcia_device)
 138                return -ENOMEM;
 139
 140        ret = platform_device_add_data(palmtx_pcmcia_device, &palmtx_pcmcia_ops,
 141                                        sizeof(palmtx_pcmcia_ops));
 142
 143        if (!ret)
 144                ret = platform_device_add(palmtx_pcmcia_device);
 145
 146        if (ret)
 147                platform_device_put(palmtx_pcmcia_device);
 148
 149        return ret;
 150}
 151
 152static void __exit palmtx_pcmcia_exit(void)
 153{
 154        platform_device_unregister(palmtx_pcmcia_device);
 155}
 156
 157module_init(palmtx_pcmcia_init);
 158module_exit(palmtx_pcmcia_exit);
 159
 160MODULE_AUTHOR("Marek Vasut <marek.vasut@gmail.com>");
 161MODULE_DESCRIPTION("PCMCIA support for Palm T|X");
 162MODULE_ALIAS("platform:pxa2xx-pcmcia");
 163MODULE_LICENSE("GPL");
 164