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#include <linux/export.h> 18 19#include "soc_common.h" 20 21#define GPIO_PCMCIA_SKTSEL (54) 22#define GPIO_PCMCIA_S0_CD_VALID (16) 23#define GPIO_PCMCIA_S1_CD_VALID (17) 24#define GPIO_PCMCIA_S0_RDYINT (6) 25#define GPIO_PCMCIA_S1_RDYINT (8) 26#define GPIO_PCMCIA_RESET (9) 27 28static int cmx255_pcmcia_hw_init(struct soc_pcmcia_socket *skt) 29{ 30 int ret = gpio_request(GPIO_PCMCIA_RESET, "PCCard reset"); 31 if (ret) 32 return ret; 33 gpio_direction_output(GPIO_PCMCIA_RESET, 0); 34 35 if (skt->nr == 0) { 36 skt->stat[SOC_STAT_CD].gpio = GPIO_PCMCIA_S0_CD_VALID; 37 skt->stat[SOC_STAT_CD].name = "PCMCIA0 CD"; 38 skt->stat[SOC_STAT_RDY].gpio = GPIO_PCMCIA_S0_RDYINT; 39 skt->stat[SOC_STAT_RDY].name = "PCMCIA0 RDY"; 40 } else { 41 skt->stat[SOC_STAT_CD].gpio = GPIO_PCMCIA_S1_CD_VALID; 42 skt->stat[SOC_STAT_CD].name = "PCMCIA1 CD"; 43 skt->stat[SOC_STAT_RDY].gpio = GPIO_PCMCIA_S1_RDYINT; 44 skt->stat[SOC_STAT_RDY].name = "PCMCIA1 RDY"; 45 } 46 47 return 0; 48} 49 50static void cmx255_pcmcia_shutdown(struct soc_pcmcia_socket *skt) 51{ 52 gpio_free(GPIO_PCMCIA_RESET); 53} 54 55 56static void cmx255_pcmcia_socket_state(struct soc_pcmcia_socket *skt, 57 struct pcmcia_state *state) 58{ 59 state->vs_3v = 0; 60 state->vs_Xv = 0; 61} 62 63 64static int cmx255_pcmcia_configure_socket(struct soc_pcmcia_socket *skt, 65 const socket_state_t *state) 66{ 67 switch (skt->nr) { 68 case 0: 69 if (state->flags & SS_RESET) { 70 gpio_set_value(GPIO_PCMCIA_SKTSEL, 0); 71 udelay(1); 72 gpio_set_value(GPIO_PCMCIA_RESET, 1); 73 udelay(10); 74 gpio_set_value(GPIO_PCMCIA_RESET, 0); 75 } 76 break; 77 case 1: 78 if (state->flags & SS_RESET) { 79 gpio_set_value(GPIO_PCMCIA_SKTSEL, 1); 80 udelay(1); 81 gpio_set_value(GPIO_PCMCIA_RESET, 1); 82 udelay(10); 83 gpio_set_value(GPIO_PCMCIA_RESET, 0); 84 } 85 break; 86 } 87 88 return 0; 89} 90 91static struct pcmcia_low_level cmx255_pcmcia_ops __initdata = { 92 .owner = THIS_MODULE, 93 .hw_init = cmx255_pcmcia_hw_init, 94 .hw_shutdown = cmx255_pcmcia_shutdown, 95 .socket_state = cmx255_pcmcia_socket_state, 96 .configure_socket = cmx255_pcmcia_configure_socket, 97 .nr = 1, 98}; 99 100static struct platform_device *cmx255_pcmcia_device; 101 102int __init cmx255_pcmcia_init(void) 103{ 104 int ret; 105 106 cmx255_pcmcia_device = platform_device_alloc("pxa2xx-pcmcia", -1); 107 108 if (!cmx255_pcmcia_device) 109 return -ENOMEM; 110 111 ret = platform_device_add_data(cmx255_pcmcia_device, &cmx255_pcmcia_ops, 112 sizeof(cmx255_pcmcia_ops)); 113 114 if (ret == 0) { 115 printk(KERN_INFO "Registering cm-x255 PCMCIA interface.\n"); 116 ret = platform_device_add(cmx255_pcmcia_device); 117 } 118 119 if (ret) 120 platform_device_put(cmx255_pcmcia_device); 121 122 return ret; 123} 124 125void __exit cmx255_pcmcia_exit(void) 126{ 127 platform_device_unregister(cmx255_pcmcia_device); 128} 129