palmtc-pcmcia.c (3858B)
1// SPDX-License-Identifier: GPL-2.0-only 2/* 3 * linux/drivers/pcmcia/pxa2xx_palmtc.c 4 * 5 * Driver for Palm Tungsten|C PCMCIA 6 * 7 * Copyright (C) 2008 Alex Osborne <ato@meshy.org> 8 * Copyright (C) 2009-2011 Marek Vasut <marek.vasut@gmail.com> 9 */ 10 11#include <linux/module.h> 12#include <linux/platform_device.h> 13#include <linux/gpio.h> 14#include <linux/delay.h> 15 16#include <asm/mach-types.h> 17#include "palmtc.h" 18#include <pcmcia/soc_common.h> 19 20static struct gpio palmtc_pcmcia_gpios[] = { 21 { GPIO_NR_PALMTC_PCMCIA_POWER1, GPIOF_INIT_LOW, "PCMCIA Power 1" }, 22 { GPIO_NR_PALMTC_PCMCIA_POWER2, GPIOF_INIT_LOW, "PCMCIA Power 2" }, 23 { GPIO_NR_PALMTC_PCMCIA_POWER3, GPIOF_INIT_LOW, "PCMCIA Power 3" }, 24 { GPIO_NR_PALMTC_PCMCIA_RESET, GPIOF_INIT_HIGH,"PCMCIA Reset" }, 25 { GPIO_NR_PALMTC_PCMCIA_PWRREADY, GPIOF_IN, "PCMCIA Power Ready" }, 26}; 27 28static int palmtc_pcmcia_hw_init(struct soc_pcmcia_socket *skt) 29{ 30 int ret; 31 32 ret = gpio_request_array(palmtc_pcmcia_gpios, 33 ARRAY_SIZE(palmtc_pcmcia_gpios)); 34 35 skt->stat[SOC_STAT_RDY].gpio = GPIO_NR_PALMTC_PCMCIA_READY; 36 skt->stat[SOC_STAT_RDY].name = "PCMCIA Ready"; 37 38 return ret; 39} 40 41static void palmtc_pcmcia_hw_shutdown(struct soc_pcmcia_socket *skt) 42{ 43 gpio_free_array(palmtc_pcmcia_gpios, ARRAY_SIZE(palmtc_pcmcia_gpios)); 44} 45 46static void palmtc_pcmcia_socket_state(struct soc_pcmcia_socket *skt, 47 struct pcmcia_state *state) 48{ 49 state->detect = 1; /* always inserted */ 50 state->vs_3v = 1; 51 state->vs_Xv = 0; 52} 53 54static int palmtc_wifi_powerdown(void) 55{ 56 gpio_set_value(GPIO_NR_PALMTC_PCMCIA_RESET, 1); 57 gpio_set_value(GPIO_NR_PALMTC_PCMCIA_POWER2, 0); 58 mdelay(40); 59 gpio_set_value(GPIO_NR_PALMTC_PCMCIA_POWER1, 0); 60 return 0; 61} 62 63static int palmtc_wifi_powerup(void) 64{ 65 int timeout = 50; 66 67 gpio_set_value(GPIO_NR_PALMTC_PCMCIA_POWER3, 1); 68 mdelay(50); 69 70 /* Power up the card, 1.8V first, after a while 3.3V */ 71 gpio_set_value(GPIO_NR_PALMTC_PCMCIA_POWER1, 1); 72 mdelay(100); 73 gpio_set_value(GPIO_NR_PALMTC_PCMCIA_POWER2, 1); 74 75 /* Wait till the card is ready */ 76 while (!gpio_get_value(GPIO_NR_PALMTC_PCMCIA_PWRREADY) && 77 timeout) { 78 mdelay(1); 79 timeout--; 80 } 81 82 /* Power down the WiFi in case of error */ 83 if (!timeout) { 84 palmtc_wifi_powerdown(); 85 return 1; 86 } 87 88 /* Reset the card */ 89 gpio_set_value(GPIO_NR_PALMTC_PCMCIA_RESET, 1); 90 mdelay(20); 91 gpio_set_value(GPIO_NR_PALMTC_PCMCIA_RESET, 0); 92 mdelay(25); 93 94 gpio_set_value(GPIO_NR_PALMTC_PCMCIA_POWER3, 0); 95 96 return 0; 97} 98 99static int palmtc_pcmcia_configure_socket(struct soc_pcmcia_socket *skt, 100 const socket_state_t *state) 101{ 102 int ret = 1; 103 104 if (state->Vcc == 0) 105 ret = palmtc_wifi_powerdown(); 106 else if (state->Vcc == 33) 107 ret = palmtc_wifi_powerup(); 108 109 return ret; 110} 111 112static struct pcmcia_low_level palmtc_pcmcia_ops = { 113 .owner = THIS_MODULE, 114 115 .first = 0, 116 .nr = 1, 117 118 .hw_init = palmtc_pcmcia_hw_init, 119 .hw_shutdown = palmtc_pcmcia_hw_shutdown, 120 121 .socket_state = palmtc_pcmcia_socket_state, 122 .configure_socket = palmtc_pcmcia_configure_socket, 123}; 124 125static struct platform_device *palmtc_pcmcia_device; 126 127static int __init palmtc_pcmcia_init(void) 128{ 129 int ret; 130 131 if (!machine_is_palmtc()) 132 return -ENODEV; 133 134 palmtc_pcmcia_device = platform_device_alloc("pxa2xx-pcmcia", -1); 135 if (!palmtc_pcmcia_device) 136 return -ENOMEM; 137 138 ret = platform_device_add_data(palmtc_pcmcia_device, &palmtc_pcmcia_ops, 139 sizeof(palmtc_pcmcia_ops)); 140 141 if (!ret) 142 ret = platform_device_add(palmtc_pcmcia_device); 143 144 if (ret) 145 platform_device_put(palmtc_pcmcia_device); 146 147 return ret; 148} 149 150static void __exit palmtc_pcmcia_exit(void) 151{ 152 platform_device_unregister(palmtc_pcmcia_device); 153} 154 155module_init(palmtc_pcmcia_init); 156module_exit(palmtc_pcmcia_exit); 157 158MODULE_AUTHOR("Alex Osborne <ato@meshy.org>," 159 " Marek Vasut <marek.vasut@gmail.com>"); 160MODULE_DESCRIPTION("PCMCIA support for Palm Tungsten|C"); 161MODULE_ALIAS("platform:pxa2xx-pcmcia"); 162MODULE_LICENSE("GPL");