1// SPDX-License-Identifier: GPL-2.0-only 2/* 3 * linux/drivers/pcmcia/pxa2xx_stargate2.c 4 * 5 * Stargate 2 PCMCIA specific routines. 6 * 7 * Created: December 6, 2005 8 * Author: Ed C. Epp 9 * Copyright: Intel Corp 2005 10 * Jonathan Cameron <jic23@cam.ac.uk> 2009 11 */ 12 13#include <linux/module.h> 14#include <linux/init.h> 15#include <linux/kernel.h> 16#include <linux/interrupt.h> 17#include <linux/delay.h> 18#include <linux/platform_device.h> 19#include <linux/gpio.h> 20 21#include <pcmcia/ss.h> 22 23#include <asm/irq.h> 24#include <asm/mach-types.h> 25 26#include "soc_common.h" 27 28#define SG2_S0_POWER_CTL 108 29#define SG2_S0_GPIO_RESET 82 30#define SG2_S0_GPIO_DETECT 53 31#define SG2_S0_GPIO_READY 81 32 33static struct gpio sg2_pcmcia_gpios[] = { 34 { SG2_S0_GPIO_RESET, GPIOF_OUT_INIT_HIGH, "PCMCIA Reset" }, 35 { SG2_S0_POWER_CTL, GPIOF_OUT_INIT_HIGH, "PCMCIA Power Ctrl" }, 36}; 37 38static int sg2_pcmcia_hw_init(struct soc_pcmcia_socket *skt) 39{ 40 skt->stat[SOC_STAT_CD].gpio = SG2_S0_GPIO_DETECT; 41 skt->stat[SOC_STAT_CD].name = "PCMCIA0 CD"; 42 skt->stat[SOC_STAT_RDY].gpio = SG2_S0_GPIO_READY; 43 skt->stat[SOC_STAT_RDY].name = "PCMCIA0 RDY"; 44 return 0; 45} 46 47static void sg2_pcmcia_socket_state(struct soc_pcmcia_socket *skt, 48 struct pcmcia_state *state) 49{ 50 state->bvd1 = 0; /* not available - battery detect on card */ 51 state->bvd2 = 0; /* not available */ 52 state->vs_3v = 1; /* not available - voltage detect for card */ 53 state->vs_Xv = 0; /* not available */ 54} 55 56static int sg2_pcmcia_configure_socket(struct soc_pcmcia_socket *skt, 57 const socket_state_t *state) 58{ 59 /* Enable card power */ 60 switch (state->Vcc) { 61 case 0: 62 /* sets power ctl register high */ 63 gpio_set_value(SG2_S0_POWER_CTL, 1); 64 break; 65 case 33: 66 case 50: 67 /* sets power control register low (clear) */ 68 gpio_set_value(SG2_S0_POWER_CTL, 0); 69 msleep(100); 70 break; 71 default: 72 pr_err("%s(): bad Vcc %u\n", 73 __func__, state->Vcc); 74 return -1; 75 } 76 77 /* reset */ 78 gpio_set_value(SG2_S0_GPIO_RESET, !!(state->flags & SS_RESET)); 79 80 return 0; 81} 82 83static struct pcmcia_low_level sg2_pcmcia_ops __initdata = { 84 .owner = THIS_MODULE, 85 .hw_init = sg2_pcmcia_hw_init, 86 .socket_state = sg2_pcmcia_socket_state, 87 .configure_socket = sg2_pcmcia_configure_socket, 88 .nr = 1, 89}; 90 91static struct platform_device *sg2_pcmcia_device; 92 93static int __init sg2_pcmcia_init(void) 94{ 95 int ret; 96 97 if (!machine_is_stargate2()) 98 return -ENODEV; 99 100 sg2_pcmcia_device = platform_device_alloc("pxa2xx-pcmcia", -1); 101 if (!sg2_pcmcia_device) 102 return -ENOMEM; 103 104 ret = gpio_request_array(sg2_pcmcia_gpios, ARRAY_SIZE(sg2_pcmcia_gpios)); 105 if (ret) 106 goto error_put_platform_device; 107 108 ret = platform_device_add_data(sg2_pcmcia_device, 109 &sg2_pcmcia_ops, 110 sizeof(sg2_pcmcia_ops)); 111 if (ret) 112 goto error_free_gpios; 113 114 ret = platform_device_add(sg2_pcmcia_device); 115 if (ret) 116 goto error_free_gpios; 117 118 return 0; 119error_free_gpios: 120 gpio_free_array(sg2_pcmcia_gpios, ARRAY_SIZE(sg2_pcmcia_gpios)); 121error_put_platform_device: 122 platform_device_put(sg2_pcmcia_device); 123 124 return ret; 125} 126 127static void __exit sg2_pcmcia_exit(void) 128{ 129 platform_device_unregister(sg2_pcmcia_device); 130 gpio_free_array(sg2_pcmcia_gpios, ARRAY_SIZE(sg2_pcmcia_gpios)); 131} 132 133fs_initcall(sg2_pcmcia_init); 134module_exit(sg2_pcmcia_exit); 135 136MODULE_LICENSE("GPL"); 137MODULE_ALIAS("platform:pxa2xx-pcmcia"); 138