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