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->socket.pci_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 = 1, 102 .nr = 1, 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