1/* 2 * linux/drivers/pcmcia/pxa2xx_vpac270.c 3 * 4 * Driver for Voipac PXA270 PCMCIA and CF sockets 5 * 6 * Copyright (C) 2010-2011 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/gpio.h> 15#include <linux/module.h> 16#include <linux/platform_device.h> 17 18#include <asm/mach-types.h> 19 20#include <asm/gpio.h> 21#include <mach/vpac270.h> 22 23#include "soc_common.h" 24 25static struct gpio vpac270_pcmcia_gpios[] = { 26 { GPIO107_VPAC270_PCMCIA_PPEN, GPIOF_INIT_LOW, "PCMCIA PPEN" }, 27 { GPIO11_VPAC270_PCMCIA_RESET, GPIOF_INIT_LOW, "PCMCIA Reset" }, 28}; 29 30static struct gpio vpac270_cf_gpios[] = { 31 { GPIO16_VPAC270_CF_RESET, GPIOF_INIT_LOW, "CF Reset" }, 32}; 33 34static int vpac270_pcmcia_hw_init(struct soc_pcmcia_socket *skt) 35{ 36 int ret; 37 38 if (skt->nr == 0) { 39 ret = gpio_request_array(vpac270_pcmcia_gpios, 40 ARRAY_SIZE(vpac270_pcmcia_gpios)); 41 42 skt->stat[SOC_STAT_CD].gpio = GPIO84_VPAC270_PCMCIA_CD; 43 skt->stat[SOC_STAT_CD].name = "PCMCIA CD"; 44 skt->stat[SOC_STAT_RDY].gpio = GPIO35_VPAC270_PCMCIA_RDY; 45 skt->stat[SOC_STAT_RDY].name = "PCMCIA Ready"; 46 } else { 47 ret = gpio_request_array(vpac270_cf_gpios, 48 ARRAY_SIZE(vpac270_cf_gpios)); 49 50 skt->stat[SOC_STAT_CD].gpio = GPIO17_VPAC270_CF_CD; 51 skt->stat[SOC_STAT_CD].name = "CF CD"; 52 skt->stat[SOC_STAT_RDY].gpio = GPIO12_VPAC270_CF_RDY; 53 skt->stat[SOC_STAT_RDY].name = "CF Ready"; 54 } 55 56 return ret; 57} 58 59static void vpac270_pcmcia_hw_shutdown(struct soc_pcmcia_socket *skt) 60{ 61 if (skt->nr == 0) 62 gpio_free_array(vpac270_pcmcia_gpios, 63 ARRAY_SIZE(vpac270_pcmcia_gpios)); 64 else 65 gpio_free_array(vpac270_cf_gpios, 66 ARRAY_SIZE(vpac270_cf_gpios)); 67} 68 69static void vpac270_pcmcia_socket_state(struct soc_pcmcia_socket *skt, 70 struct pcmcia_state *state) 71{ 72 state->vs_3v = 1; 73 state->vs_Xv = 0; 74} 75 76static int 77vpac270_pcmcia_configure_socket(struct soc_pcmcia_socket *skt, 78 const socket_state_t *state) 79{ 80 if (skt->nr == 0) { 81 gpio_set_value(GPIO11_VPAC270_PCMCIA_RESET, 82 (state->flags & SS_RESET)); 83 gpio_set_value(GPIO107_VPAC270_PCMCIA_PPEN, 84 !(state->Vcc == 33 || state->Vcc == 50)); 85 } else { 86 gpio_set_value(GPIO16_VPAC270_CF_RESET, 87 (state->flags & SS_RESET)); 88 } 89 90 return 0; 91} 92 93static struct pcmcia_low_level vpac270_pcmcia_ops = { 94 .owner = THIS_MODULE, 95 96 .first = 0, 97 .nr = 2, 98 99 .hw_init = vpac270_pcmcia_hw_init, 100 .hw_shutdown = vpac270_pcmcia_hw_shutdown, 101 102 .socket_state = vpac270_pcmcia_socket_state, 103 .configure_socket = vpac270_pcmcia_configure_socket, 104}; 105 106static struct platform_device *vpac270_pcmcia_device; 107 108static int __init vpac270_pcmcia_init(void) 109{ 110 int ret; 111 112 if (!machine_is_vpac270()) 113 return -ENODEV; 114 115 vpac270_pcmcia_device = platform_device_alloc("pxa2xx-pcmcia", -1); 116 if (!vpac270_pcmcia_device) 117 return -ENOMEM; 118 119 ret = platform_device_add_data(vpac270_pcmcia_device, 120 &vpac270_pcmcia_ops, sizeof(vpac270_pcmcia_ops)); 121 122 if (!ret) 123 ret = platform_device_add(vpac270_pcmcia_device); 124 125 if (ret) 126 platform_device_put(vpac270_pcmcia_device); 127 128 return ret; 129} 130 131static void __exit vpac270_pcmcia_exit(void) 132{ 133 platform_device_unregister(vpac270_pcmcia_device); 134} 135 136module_init(vpac270_pcmcia_init); 137module_exit(vpac270_pcmcia_exit); 138 139MODULE_AUTHOR("Marek Vasut <marek.vasut@gmail.com>"); 140MODULE_DESCRIPTION("PCMCIA support for Voipac PXA270"); 141MODULE_ALIAS("platform:pxa2xx-pcmcia"); 142MODULE_LICENSE("GPL"); 143