linux/drivers/pcmcia/pxa2xx_palmld.c
<<
>>
Prefs
   1/*
   2 * linux/drivers/pcmcia/pxa2xx_palmld.c
   3 *
   4 * Driver for Palm LifeDrive PCMCIA
   5 *
   6 * Copyright (C) 2006 Alex Osborne <ato@meshy.org>
   7 * Copyright (C) 2007-2008 Marek Vasut <marek.vasut@gmail.com>
   8 *
   9 * This program is free software; you can redistribute it and/or modify
  10 * it under the terms of the GNU General Public License version 2 as
  11 * published by the Free Software Foundation.
  12 *
  13 */
  14
  15#include <linux/module.h>
  16#include <linux/platform_device.h>
  17#include <linux/gpio.h>
  18
  19#include <asm/mach-types.h>
  20#include <mach/palmld.h>
  21#include "soc_common.h"
  22
  23static int palmld_pcmcia_hw_init(struct soc_pcmcia_socket *skt)
  24{
  25        int ret;
  26
  27        ret = gpio_request(GPIO_NR_PALMLD_PCMCIA_POWER, "PCMCIA PWR");
  28        if (ret)
  29                goto err1;
  30        ret = gpio_direction_output(GPIO_NR_PALMLD_PCMCIA_POWER, 0);
  31        if (ret)
  32                goto err2;
  33
  34        ret = gpio_request(GPIO_NR_PALMLD_PCMCIA_RESET, "PCMCIA RST");
  35        if (ret)
  36                goto err2;
  37        ret = gpio_direction_output(GPIO_NR_PALMLD_PCMCIA_RESET, 1);
  38        if (ret)
  39                goto err3;
  40
  41        ret = gpio_request(GPIO_NR_PALMLD_PCMCIA_READY, "PCMCIA RDY");
  42        if (ret)
  43                goto err3;
  44        ret = gpio_direction_input(GPIO_NR_PALMLD_PCMCIA_READY);
  45        if (ret)
  46                goto err4;
  47
  48        skt->irq = IRQ_GPIO(GPIO_NR_PALMLD_PCMCIA_READY);
  49        return 0;
  50
  51err4:
  52        gpio_free(GPIO_NR_PALMLD_PCMCIA_READY);
  53err3:
  54        gpio_free(GPIO_NR_PALMLD_PCMCIA_RESET);
  55err2:
  56        gpio_free(GPIO_NR_PALMLD_PCMCIA_POWER);
  57err1:
  58        return ret;
  59}
  60
  61static void palmld_pcmcia_hw_shutdown(struct soc_pcmcia_socket *skt)
  62{
  63        gpio_free(GPIO_NR_PALMLD_PCMCIA_READY);
  64        gpio_free(GPIO_NR_PALMLD_PCMCIA_RESET);
  65        gpio_free(GPIO_NR_PALMLD_PCMCIA_POWER);
  66}
  67
  68static void palmld_pcmcia_socket_state(struct soc_pcmcia_socket *skt,
  69                                        struct pcmcia_state *state)
  70{
  71        state->detect = 1; /* always inserted */
  72        state->ready  = !!gpio_get_value(GPIO_NR_PALMLD_PCMCIA_READY);
  73        state->bvd1   = 1;
  74        state->bvd2   = 1;
  75        state->wrprot = 0;
  76        state->vs_3v  = 1;
  77        state->vs_Xv  = 0;
  78}
  79
  80static int palmld_pcmcia_configure_socket(struct soc_pcmcia_socket *skt,
  81                                        const socket_state_t *state)
  82{
  83        gpio_set_value(GPIO_NR_PALMLD_PCMCIA_POWER, 1);
  84        gpio_set_value(GPIO_NR_PALMLD_PCMCIA_RESET,
  85                        !!(state->flags & SS_RESET));
  86
  87        return 0;
  88}
  89
  90static void palmld_pcmcia_socket_init(struct soc_pcmcia_socket *skt)
  91{
  92}
  93
  94static void palmld_pcmcia_socket_suspend(struct soc_pcmcia_socket *skt)
  95{
  96}
  97
  98static struct pcmcia_low_level palmld_pcmcia_ops = {
  99        .owner                  = THIS_MODULE,
 100
 101        .first                  = 0,
 102        .nr                     = 2,
 103
 104        .hw_init                = palmld_pcmcia_hw_init,
 105        .hw_shutdown            = palmld_pcmcia_hw_shutdown,
 106
 107        .socket_state           = palmld_pcmcia_socket_state,
 108        .configure_socket       = palmld_pcmcia_configure_socket,
 109
 110        .socket_init            = palmld_pcmcia_socket_init,
 111        .socket_suspend         = palmld_pcmcia_socket_suspend,
 112};
 113
 114static struct platform_device *palmld_pcmcia_device;
 115
 116static int __init palmld_pcmcia_init(void)
 117{
 118        int ret;
 119
 120        if (!machine_is_palmld())
 121                return -ENODEV;
 122
 123        palmld_pcmcia_device = platform_device_alloc("pxa2xx-pcmcia", -1);
 124        if (!palmld_pcmcia_device)
 125                return -ENOMEM;
 126
 127        ret = platform_device_add_data(palmld_pcmcia_device, &palmld_pcmcia_ops,
 128                                        sizeof(palmld_pcmcia_ops));
 129
 130        if (!ret)
 131                ret = platform_device_add(palmld_pcmcia_device);
 132
 133        if (ret)
 134                platform_device_put(palmld_pcmcia_device);
 135
 136        return ret;
 137}
 138
 139static void __exit palmld_pcmcia_exit(void)
 140{
 141        platform_device_unregister(palmld_pcmcia_device);
 142}
 143
 144module_init(palmld_pcmcia_init);
 145module_exit(palmld_pcmcia_exit);
 146
 147MODULE_AUTHOR("Alex Osborne <ato@meshy.org>,"
 148            " Marek Vasut <marek.vasut@gmail.com>");
 149MODULE_DESCRIPTION("PCMCIA support for Palm LifeDrive");
 150MODULE_ALIAS("platform:pxa2xx-pcmcia");
 151MODULE_LICENSE("GPL");
 152