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