1*1da177e4SLinus Torvalds /*====================================================================== 2*1da177e4SLinus Torvalds 3*1da177e4SLinus Torvalds Common support code for the PCMCIA control functionality of 4*1da177e4SLinus Torvalds integrated SOCs like the SA-11x0 and PXA2xx microprocessors. 5*1da177e4SLinus Torvalds 6*1da177e4SLinus Torvalds The contents of this file are subject to the Mozilla Public 7*1da177e4SLinus Torvalds License Version 1.1 (the "License"); you may not use this file 8*1da177e4SLinus Torvalds except in compliance with the License. You may obtain a copy of 9*1da177e4SLinus Torvalds the License at http://www.mozilla.org/MPL/ 10*1da177e4SLinus Torvalds 11*1da177e4SLinus Torvalds Software distributed under the License is distributed on an "AS 12*1da177e4SLinus Torvalds IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or 13*1da177e4SLinus Torvalds implied. See the License for the specific language governing 14*1da177e4SLinus Torvalds rights and limitations under the License. 15*1da177e4SLinus Torvalds 16*1da177e4SLinus Torvalds The initial developer of the original code is John G. Dorsey 17*1da177e4SLinus Torvalds <john+@cs.cmu.edu>. Portions created by John G. Dorsey are 18*1da177e4SLinus Torvalds Copyright (C) 1999 John G. Dorsey. All Rights Reserved. 19*1da177e4SLinus Torvalds 20*1da177e4SLinus Torvalds Alternatively, the contents of this file may be used under the 21*1da177e4SLinus Torvalds terms of the GNU Public License version 2 (the "GPL"), in which 22*1da177e4SLinus Torvalds case the provisions of the GPL are applicable instead of the 23*1da177e4SLinus Torvalds above. If you wish to allow the use of your version of this file 24*1da177e4SLinus Torvalds only under the terms of the GPL and not to allow others to use 25*1da177e4SLinus Torvalds your version of this file under the MPL, indicate your decision 26*1da177e4SLinus Torvalds by deleting the provisions above and replace them with the notice 27*1da177e4SLinus Torvalds and other provisions required by the GPL. If you do not delete 28*1da177e4SLinus Torvalds the provisions above, a recipient may use your version of this 29*1da177e4SLinus Torvalds file under either the MPL or the GPL. 30*1da177e4SLinus Torvalds 31*1da177e4SLinus Torvalds ======================================================================*/ 32*1da177e4SLinus Torvalds 33*1da177e4SLinus Torvalds 34*1da177e4SLinus Torvalds #include <linux/config.h> 35*1da177e4SLinus Torvalds #include <linux/module.h> 36*1da177e4SLinus Torvalds #include <linux/moduleparam.h> 37*1da177e4SLinus Torvalds #include <linux/init.h> 38*1da177e4SLinus Torvalds #include <linux/kernel.h> 39*1da177e4SLinus Torvalds #include <linux/timer.h> 40*1da177e4SLinus Torvalds #include <linux/mm.h> 41*1da177e4SLinus Torvalds #include <linux/interrupt.h> 42*1da177e4SLinus Torvalds #include <linux/spinlock.h> 43*1da177e4SLinus Torvalds #include <linux/cpufreq.h> 44*1da177e4SLinus Torvalds 45*1da177e4SLinus Torvalds #include <asm/hardware.h> 46*1da177e4SLinus Torvalds #include <asm/io.h> 47*1da177e4SLinus Torvalds #include <asm/irq.h> 48*1da177e4SLinus Torvalds #include <asm/system.h> 49*1da177e4SLinus Torvalds 50*1da177e4SLinus Torvalds #include "soc_common.h" 51*1da177e4SLinus Torvalds 52*1da177e4SLinus Torvalds /* FIXME: platform dependent resource declaration has to move out of this file */ 53*1da177e4SLinus Torvalds #ifdef CONFIG_ARCH_PXA 54*1da177e4SLinus Torvalds #include <asm/arch/pxa-regs.h> 55*1da177e4SLinus Torvalds #endif 56*1da177e4SLinus Torvalds 57*1da177e4SLinus Torvalds #ifdef DEBUG 58*1da177e4SLinus Torvalds 59*1da177e4SLinus Torvalds static int pc_debug; 60*1da177e4SLinus Torvalds module_param(pc_debug, int, 0644); 61*1da177e4SLinus Torvalds 62*1da177e4SLinus Torvalds void soc_pcmcia_debug(struct soc_pcmcia_socket *skt, const char *func, 63*1da177e4SLinus Torvalds int lvl, const char *fmt, ...) 64*1da177e4SLinus Torvalds { 65*1da177e4SLinus Torvalds va_list args; 66*1da177e4SLinus Torvalds if (pc_debug > lvl) { 67*1da177e4SLinus Torvalds printk(KERN_DEBUG "skt%u: %s: ", skt->nr, func); 68*1da177e4SLinus Torvalds va_start(args, fmt); 69*1da177e4SLinus Torvalds printk(fmt, args); 70*1da177e4SLinus Torvalds va_end(args); 71*1da177e4SLinus Torvalds } 72*1da177e4SLinus Torvalds } 73*1da177e4SLinus Torvalds 74*1da177e4SLinus Torvalds #endif 75*1da177e4SLinus Torvalds 76*1da177e4SLinus Torvalds #define to_soc_pcmcia_socket(x) container_of(x, struct soc_pcmcia_socket, socket) 77*1da177e4SLinus Torvalds 78*1da177e4SLinus Torvalds static unsigned short 79*1da177e4SLinus Torvalds calc_speed(unsigned short *spds, int num, unsigned short dflt) 80*1da177e4SLinus Torvalds { 81*1da177e4SLinus Torvalds unsigned short speed = 0; 82*1da177e4SLinus Torvalds int i; 83*1da177e4SLinus Torvalds 84*1da177e4SLinus Torvalds for (i = 0; i < num; i++) 85*1da177e4SLinus Torvalds if (speed < spds[i]) 86*1da177e4SLinus Torvalds speed = spds[i]; 87*1da177e4SLinus Torvalds if (speed == 0) 88*1da177e4SLinus Torvalds speed = dflt; 89*1da177e4SLinus Torvalds 90*1da177e4SLinus Torvalds return speed; 91*1da177e4SLinus Torvalds } 92*1da177e4SLinus Torvalds 93*1da177e4SLinus Torvalds void soc_common_pcmcia_get_timing(struct soc_pcmcia_socket *skt, struct soc_pcmcia_timing *timing) 94*1da177e4SLinus Torvalds { 95*1da177e4SLinus Torvalds timing->io = calc_speed(skt->spd_io, MAX_IO_WIN, SOC_PCMCIA_IO_ACCESS); 96*1da177e4SLinus Torvalds timing->mem = calc_speed(skt->spd_mem, MAX_WIN, SOC_PCMCIA_3V_MEM_ACCESS); 97*1da177e4SLinus Torvalds timing->attr = calc_speed(skt->spd_attr, MAX_WIN, SOC_PCMCIA_3V_MEM_ACCESS); 98*1da177e4SLinus Torvalds } 99*1da177e4SLinus Torvalds EXPORT_SYMBOL(soc_common_pcmcia_get_timing); 100*1da177e4SLinus Torvalds 101*1da177e4SLinus Torvalds static unsigned int soc_common_pcmcia_skt_state(struct soc_pcmcia_socket *skt) 102*1da177e4SLinus Torvalds { 103*1da177e4SLinus Torvalds struct pcmcia_state state; 104*1da177e4SLinus Torvalds unsigned int stat; 105*1da177e4SLinus Torvalds 106*1da177e4SLinus Torvalds memset(&state, 0, sizeof(struct pcmcia_state)); 107*1da177e4SLinus Torvalds 108*1da177e4SLinus Torvalds skt->ops->socket_state(skt, &state); 109*1da177e4SLinus Torvalds 110*1da177e4SLinus Torvalds stat = state.detect ? SS_DETECT : 0; 111*1da177e4SLinus Torvalds stat |= state.ready ? SS_READY : 0; 112*1da177e4SLinus Torvalds stat |= state.wrprot ? SS_WRPROT : 0; 113*1da177e4SLinus Torvalds stat |= state.vs_3v ? SS_3VCARD : 0; 114*1da177e4SLinus Torvalds stat |= state.vs_Xv ? SS_XVCARD : 0; 115*1da177e4SLinus Torvalds 116*1da177e4SLinus Torvalds /* The power status of individual sockets is not available 117*1da177e4SLinus Torvalds * explicitly from the hardware, so we just remember the state 118*1da177e4SLinus Torvalds * and regurgitate it upon request: 119*1da177e4SLinus Torvalds */ 120*1da177e4SLinus Torvalds stat |= skt->cs_state.Vcc ? SS_POWERON : 0; 121*1da177e4SLinus Torvalds 122*1da177e4SLinus Torvalds if (skt->cs_state.flags & SS_IOCARD) 123*1da177e4SLinus Torvalds stat |= state.bvd1 ? SS_STSCHG : 0; 124*1da177e4SLinus Torvalds else { 125*1da177e4SLinus Torvalds if (state.bvd1 == 0) 126*1da177e4SLinus Torvalds stat |= SS_BATDEAD; 127*1da177e4SLinus Torvalds else if (state.bvd2 == 0) 128*1da177e4SLinus Torvalds stat |= SS_BATWARN; 129*1da177e4SLinus Torvalds } 130*1da177e4SLinus Torvalds return stat; 131*1da177e4SLinus Torvalds } 132*1da177e4SLinus Torvalds 133*1da177e4SLinus Torvalds /* 134*1da177e4SLinus Torvalds * soc_common_pcmcia_config_skt 135*1da177e4SLinus Torvalds * ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 136*1da177e4SLinus Torvalds * 137*1da177e4SLinus Torvalds * Convert PCMCIA socket state to our socket configure structure. 138*1da177e4SLinus Torvalds */ 139*1da177e4SLinus Torvalds static int 140*1da177e4SLinus Torvalds soc_common_pcmcia_config_skt(struct soc_pcmcia_socket *skt, socket_state_t *state) 141*1da177e4SLinus Torvalds { 142*1da177e4SLinus Torvalds int ret; 143*1da177e4SLinus Torvalds 144*1da177e4SLinus Torvalds ret = skt->ops->configure_socket(skt, state); 145*1da177e4SLinus Torvalds if (ret == 0) { 146*1da177e4SLinus Torvalds /* 147*1da177e4SLinus Torvalds * This really needs a better solution. The IRQ 148*1da177e4SLinus Torvalds * may or may not be claimed by the driver. 149*1da177e4SLinus Torvalds */ 150*1da177e4SLinus Torvalds if (skt->irq_state != 1 && state->io_irq) { 151*1da177e4SLinus Torvalds skt->irq_state = 1; 152*1da177e4SLinus Torvalds set_irq_type(skt->irq, IRQT_FALLING); 153*1da177e4SLinus Torvalds } else if (skt->irq_state == 1 && state->io_irq == 0) { 154*1da177e4SLinus Torvalds skt->irq_state = 0; 155*1da177e4SLinus Torvalds set_irq_type(skt->irq, IRQT_NOEDGE); 156*1da177e4SLinus Torvalds } 157*1da177e4SLinus Torvalds 158*1da177e4SLinus Torvalds skt->cs_state = *state; 159*1da177e4SLinus Torvalds } 160*1da177e4SLinus Torvalds 161*1da177e4SLinus Torvalds if (ret < 0) 162*1da177e4SLinus Torvalds printk(KERN_ERR "soc_common_pcmcia: unable to configure " 163*1da177e4SLinus Torvalds "socket %d\n", skt->nr); 164*1da177e4SLinus Torvalds 165*1da177e4SLinus Torvalds return ret; 166*1da177e4SLinus Torvalds } 167*1da177e4SLinus Torvalds 168*1da177e4SLinus Torvalds /* soc_common_pcmcia_sock_init() 169*1da177e4SLinus Torvalds * ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 170*1da177e4SLinus Torvalds * 171*1da177e4SLinus Torvalds * (Re-)Initialise the socket, turning on status interrupts 172*1da177e4SLinus Torvalds * and PCMCIA bus. This must wait for power to stabilise 173*1da177e4SLinus Torvalds * so that the card status signals report correctly. 174*1da177e4SLinus Torvalds * 175*1da177e4SLinus Torvalds * Returns: 0 176*1da177e4SLinus Torvalds */ 177*1da177e4SLinus Torvalds static int soc_common_pcmcia_sock_init(struct pcmcia_socket *sock) 178*1da177e4SLinus Torvalds { 179*1da177e4SLinus Torvalds struct soc_pcmcia_socket *skt = to_soc_pcmcia_socket(sock); 180*1da177e4SLinus Torvalds 181*1da177e4SLinus Torvalds debug(skt, 2, "initializing socket\n"); 182*1da177e4SLinus Torvalds 183*1da177e4SLinus Torvalds skt->ops->socket_init(skt); 184*1da177e4SLinus Torvalds return 0; 185*1da177e4SLinus Torvalds } 186*1da177e4SLinus Torvalds 187*1da177e4SLinus Torvalds 188*1da177e4SLinus Torvalds /* 189*1da177e4SLinus Torvalds * soc_common_pcmcia_suspend() 190*1da177e4SLinus Torvalds * ^^^^^^^^^^^^^^^^^^^^^^^^^^^ 191*1da177e4SLinus Torvalds * 192*1da177e4SLinus Torvalds * Remove power on the socket, disable IRQs from the card. 193*1da177e4SLinus Torvalds * Turn off status interrupts, and disable the PCMCIA bus. 194*1da177e4SLinus Torvalds * 195*1da177e4SLinus Torvalds * Returns: 0 196*1da177e4SLinus Torvalds */ 197*1da177e4SLinus Torvalds static int soc_common_pcmcia_suspend(struct pcmcia_socket *sock) 198*1da177e4SLinus Torvalds { 199*1da177e4SLinus Torvalds struct soc_pcmcia_socket *skt = to_soc_pcmcia_socket(sock); 200*1da177e4SLinus Torvalds 201*1da177e4SLinus Torvalds debug(skt, 2, "suspending socket\n"); 202*1da177e4SLinus Torvalds 203*1da177e4SLinus Torvalds skt->ops->socket_suspend(skt); 204*1da177e4SLinus Torvalds 205*1da177e4SLinus Torvalds return 0; 206*1da177e4SLinus Torvalds } 207*1da177e4SLinus Torvalds 208*1da177e4SLinus Torvalds static DEFINE_SPINLOCK(status_lock); 209*1da177e4SLinus Torvalds 210*1da177e4SLinus Torvalds static void soc_common_check_status(struct soc_pcmcia_socket *skt) 211*1da177e4SLinus Torvalds { 212*1da177e4SLinus Torvalds unsigned int events; 213*1da177e4SLinus Torvalds 214*1da177e4SLinus Torvalds debug(skt, 4, "entering PCMCIA monitoring thread\n"); 215*1da177e4SLinus Torvalds 216*1da177e4SLinus Torvalds do { 217*1da177e4SLinus Torvalds unsigned int status; 218*1da177e4SLinus Torvalds unsigned long flags; 219*1da177e4SLinus Torvalds 220*1da177e4SLinus Torvalds status = soc_common_pcmcia_skt_state(skt); 221*1da177e4SLinus Torvalds 222*1da177e4SLinus Torvalds spin_lock_irqsave(&status_lock, flags); 223*1da177e4SLinus Torvalds events = (status ^ skt->status) & skt->cs_state.csc_mask; 224*1da177e4SLinus Torvalds skt->status = status; 225*1da177e4SLinus Torvalds spin_unlock_irqrestore(&status_lock, flags); 226*1da177e4SLinus Torvalds 227*1da177e4SLinus Torvalds debug(skt, 4, "events: %s%s%s%s%s%s\n", 228*1da177e4SLinus Torvalds events == 0 ? "<NONE>" : "", 229*1da177e4SLinus Torvalds events & SS_DETECT ? "DETECT " : "", 230*1da177e4SLinus Torvalds events & SS_READY ? "READY " : "", 231*1da177e4SLinus Torvalds events & SS_BATDEAD ? "BATDEAD " : "", 232*1da177e4SLinus Torvalds events & SS_BATWARN ? "BATWARN " : "", 233*1da177e4SLinus Torvalds events & SS_STSCHG ? "STSCHG " : ""); 234*1da177e4SLinus Torvalds 235*1da177e4SLinus Torvalds if (events) 236*1da177e4SLinus Torvalds pcmcia_parse_events(&skt->socket, events); 237*1da177e4SLinus Torvalds } while (events); 238*1da177e4SLinus Torvalds } 239*1da177e4SLinus Torvalds 240*1da177e4SLinus Torvalds /* Let's poll for events in addition to IRQs since IRQ only is unreliable... */ 241*1da177e4SLinus Torvalds static void soc_common_pcmcia_poll_event(unsigned long dummy) 242*1da177e4SLinus Torvalds { 243*1da177e4SLinus Torvalds struct soc_pcmcia_socket *skt = (struct soc_pcmcia_socket *)dummy; 244*1da177e4SLinus Torvalds debug(skt, 4, "polling for events\n"); 245*1da177e4SLinus Torvalds 246*1da177e4SLinus Torvalds mod_timer(&skt->poll_timer, jiffies + SOC_PCMCIA_POLL_PERIOD); 247*1da177e4SLinus Torvalds 248*1da177e4SLinus Torvalds soc_common_check_status(skt); 249*1da177e4SLinus Torvalds } 250*1da177e4SLinus Torvalds 251*1da177e4SLinus Torvalds 252*1da177e4SLinus Torvalds /* 253*1da177e4SLinus Torvalds * Service routine for socket driver interrupts (requested by the 254*1da177e4SLinus Torvalds * low-level PCMCIA init() operation via soc_common_pcmcia_thread()). 255*1da177e4SLinus Torvalds * The actual interrupt-servicing work is performed by 256*1da177e4SLinus Torvalds * soc_common_pcmcia_thread(), largely because the Card Services event- 257*1da177e4SLinus Torvalds * handling code performs scheduling operations which cannot be 258*1da177e4SLinus Torvalds * executed from within an interrupt context. 259*1da177e4SLinus Torvalds */ 260*1da177e4SLinus Torvalds static irqreturn_t soc_common_pcmcia_interrupt(int irq, void *dev, struct pt_regs *regs) 261*1da177e4SLinus Torvalds { 262*1da177e4SLinus Torvalds struct soc_pcmcia_socket *skt = dev; 263*1da177e4SLinus Torvalds 264*1da177e4SLinus Torvalds debug(skt, 3, "servicing IRQ %d\n", irq); 265*1da177e4SLinus Torvalds 266*1da177e4SLinus Torvalds soc_common_check_status(skt); 267*1da177e4SLinus Torvalds 268*1da177e4SLinus Torvalds return IRQ_HANDLED; 269*1da177e4SLinus Torvalds } 270*1da177e4SLinus Torvalds 271*1da177e4SLinus Torvalds 272*1da177e4SLinus Torvalds /* 273*1da177e4SLinus Torvalds * Implements the get_status() operation for the in-kernel PCMCIA 274*1da177e4SLinus Torvalds * service (formerly SS_GetStatus in Card Services). Essentially just 275*1da177e4SLinus Torvalds * fills in bits in `status' according to internal driver state or 276*1da177e4SLinus Torvalds * the value of the voltage detect chipselect register. 277*1da177e4SLinus Torvalds * 278*1da177e4SLinus Torvalds * As a debugging note, during card startup, the PCMCIA core issues 279*1da177e4SLinus Torvalds * three set_socket() commands in a row the first with RESET deasserted, 280*1da177e4SLinus Torvalds * the second with RESET asserted, and the last with RESET deasserted 281*1da177e4SLinus Torvalds * again. Following the third set_socket(), a get_status() command will 282*1da177e4SLinus Torvalds * be issued. The kernel is looking for the SS_READY flag (see 283*1da177e4SLinus Torvalds * setup_socket(), reset_socket(), and unreset_socket() in cs.c). 284*1da177e4SLinus Torvalds * 285*1da177e4SLinus Torvalds * Returns: 0 286*1da177e4SLinus Torvalds */ 287*1da177e4SLinus Torvalds static int 288*1da177e4SLinus Torvalds soc_common_pcmcia_get_status(struct pcmcia_socket *sock, unsigned int *status) 289*1da177e4SLinus Torvalds { 290*1da177e4SLinus Torvalds struct soc_pcmcia_socket *skt = to_soc_pcmcia_socket(sock); 291*1da177e4SLinus Torvalds 292*1da177e4SLinus Torvalds skt->status = soc_common_pcmcia_skt_state(skt); 293*1da177e4SLinus Torvalds *status = skt->status; 294*1da177e4SLinus Torvalds 295*1da177e4SLinus Torvalds return 0; 296*1da177e4SLinus Torvalds } 297*1da177e4SLinus Torvalds 298*1da177e4SLinus Torvalds 299*1da177e4SLinus Torvalds /* 300*1da177e4SLinus Torvalds * Implements the get_socket() operation for the in-kernel PCMCIA 301*1da177e4SLinus Torvalds * service (formerly SS_GetSocket in Card Services). Not a very 302*1da177e4SLinus Torvalds * exciting routine. 303*1da177e4SLinus Torvalds * 304*1da177e4SLinus Torvalds * Returns: 0 305*1da177e4SLinus Torvalds */ 306*1da177e4SLinus Torvalds static int 307*1da177e4SLinus Torvalds soc_common_pcmcia_get_socket(struct pcmcia_socket *sock, socket_state_t *state) 308*1da177e4SLinus Torvalds { 309*1da177e4SLinus Torvalds struct soc_pcmcia_socket *skt = to_soc_pcmcia_socket(sock); 310*1da177e4SLinus Torvalds 311*1da177e4SLinus Torvalds debug(skt, 2, "\n"); 312*1da177e4SLinus Torvalds 313*1da177e4SLinus Torvalds *state = skt->cs_state; 314*1da177e4SLinus Torvalds 315*1da177e4SLinus Torvalds return 0; 316*1da177e4SLinus Torvalds } 317*1da177e4SLinus Torvalds 318*1da177e4SLinus Torvalds /* 319*1da177e4SLinus Torvalds * Implements the set_socket() operation for the in-kernel PCMCIA 320*1da177e4SLinus Torvalds * service (formerly SS_SetSocket in Card Services). We more or 321*1da177e4SLinus Torvalds * less punt all of this work and let the kernel handle the details 322*1da177e4SLinus Torvalds * of power configuration, reset, &c. We also record the value of 323*1da177e4SLinus Torvalds * `state' in order to regurgitate it to the PCMCIA core later. 324*1da177e4SLinus Torvalds * 325*1da177e4SLinus Torvalds * Returns: 0 326*1da177e4SLinus Torvalds */ 327*1da177e4SLinus Torvalds static int 328*1da177e4SLinus Torvalds soc_common_pcmcia_set_socket(struct pcmcia_socket *sock, socket_state_t *state) 329*1da177e4SLinus Torvalds { 330*1da177e4SLinus Torvalds struct soc_pcmcia_socket *skt = to_soc_pcmcia_socket(sock); 331*1da177e4SLinus Torvalds 332*1da177e4SLinus Torvalds debug(skt, 2, "mask: %s%s%s%s%s%sflags: %s%s%s%s%s%sVcc %d Vpp %d irq %d\n", 333*1da177e4SLinus Torvalds (state->csc_mask==0)?"<NONE> ":"", 334*1da177e4SLinus Torvalds (state->csc_mask&SS_DETECT)?"DETECT ":"", 335*1da177e4SLinus Torvalds (state->csc_mask&SS_READY)?"READY ":"", 336*1da177e4SLinus Torvalds (state->csc_mask&SS_BATDEAD)?"BATDEAD ":"", 337*1da177e4SLinus Torvalds (state->csc_mask&SS_BATWARN)?"BATWARN ":"", 338*1da177e4SLinus Torvalds (state->csc_mask&SS_STSCHG)?"STSCHG ":"", 339*1da177e4SLinus Torvalds (state->flags==0)?"<NONE> ":"", 340*1da177e4SLinus Torvalds (state->flags&SS_PWR_AUTO)?"PWR_AUTO ":"", 341*1da177e4SLinus Torvalds (state->flags&SS_IOCARD)?"IOCARD ":"", 342*1da177e4SLinus Torvalds (state->flags&SS_RESET)?"RESET ":"", 343*1da177e4SLinus Torvalds (state->flags&SS_SPKR_ENA)?"SPKR_ENA ":"", 344*1da177e4SLinus Torvalds (state->flags&SS_OUTPUT_ENA)?"OUTPUT_ENA ":"", 345*1da177e4SLinus Torvalds state->Vcc, state->Vpp, state->io_irq); 346*1da177e4SLinus Torvalds 347*1da177e4SLinus Torvalds return soc_common_pcmcia_config_skt(skt, state); 348*1da177e4SLinus Torvalds } 349*1da177e4SLinus Torvalds 350*1da177e4SLinus Torvalds 351*1da177e4SLinus Torvalds /* 352*1da177e4SLinus Torvalds * Implements the set_io_map() operation for the in-kernel PCMCIA 353*1da177e4SLinus Torvalds * service (formerly SS_SetIOMap in Card Services). We configure 354*1da177e4SLinus Torvalds * the map speed as requested, but override the address ranges 355*1da177e4SLinus Torvalds * supplied by Card Services. 356*1da177e4SLinus Torvalds * 357*1da177e4SLinus Torvalds * Returns: 0 on success, -1 on error 358*1da177e4SLinus Torvalds */ 359*1da177e4SLinus Torvalds static int 360*1da177e4SLinus Torvalds soc_common_pcmcia_set_io_map(struct pcmcia_socket *sock, struct pccard_io_map *map) 361*1da177e4SLinus Torvalds { 362*1da177e4SLinus Torvalds struct soc_pcmcia_socket *skt = to_soc_pcmcia_socket(sock); 363*1da177e4SLinus Torvalds unsigned short speed = map->speed; 364*1da177e4SLinus Torvalds 365*1da177e4SLinus Torvalds debug(skt, 2, "map %u speed %u start 0x%08x stop 0x%08x\n", 366*1da177e4SLinus Torvalds map->map, map->speed, map->start, map->stop); 367*1da177e4SLinus Torvalds debug(skt, 2, "flags: %s%s%s%s%s%s%s%s\n", 368*1da177e4SLinus Torvalds (map->flags==0)?"<NONE>":"", 369*1da177e4SLinus Torvalds (map->flags&MAP_ACTIVE)?"ACTIVE ":"", 370*1da177e4SLinus Torvalds (map->flags&MAP_16BIT)?"16BIT ":"", 371*1da177e4SLinus Torvalds (map->flags&MAP_AUTOSZ)?"AUTOSZ ":"", 372*1da177e4SLinus Torvalds (map->flags&MAP_0WS)?"0WS ":"", 373*1da177e4SLinus Torvalds (map->flags&MAP_WRPROT)?"WRPROT ":"", 374*1da177e4SLinus Torvalds (map->flags&MAP_USE_WAIT)?"USE_WAIT ":"", 375*1da177e4SLinus Torvalds (map->flags&MAP_PREFETCH)?"PREFETCH ":""); 376*1da177e4SLinus Torvalds 377*1da177e4SLinus Torvalds if (map->map >= MAX_IO_WIN) { 378*1da177e4SLinus Torvalds printk(KERN_ERR "%s(): map (%d) out of range\n", __FUNCTION__, 379*1da177e4SLinus Torvalds map->map); 380*1da177e4SLinus Torvalds return -1; 381*1da177e4SLinus Torvalds } 382*1da177e4SLinus Torvalds 383*1da177e4SLinus Torvalds if (map->flags & MAP_ACTIVE) { 384*1da177e4SLinus Torvalds if (speed == 0) 385*1da177e4SLinus Torvalds speed = SOC_PCMCIA_IO_ACCESS; 386*1da177e4SLinus Torvalds } else { 387*1da177e4SLinus Torvalds speed = 0; 388*1da177e4SLinus Torvalds } 389*1da177e4SLinus Torvalds 390*1da177e4SLinus Torvalds skt->spd_io[map->map] = speed; 391*1da177e4SLinus Torvalds skt->ops->set_timing(skt); 392*1da177e4SLinus Torvalds 393*1da177e4SLinus Torvalds if (map->stop == 1) 394*1da177e4SLinus Torvalds map->stop = PAGE_SIZE-1; 395*1da177e4SLinus Torvalds 396*1da177e4SLinus Torvalds map->stop -= map->start; 397*1da177e4SLinus Torvalds map->stop += skt->socket.io_offset; 398*1da177e4SLinus Torvalds map->start = skt->socket.io_offset; 399*1da177e4SLinus Torvalds 400*1da177e4SLinus Torvalds return 0; 401*1da177e4SLinus Torvalds } 402*1da177e4SLinus Torvalds 403*1da177e4SLinus Torvalds 404*1da177e4SLinus Torvalds /* 405*1da177e4SLinus Torvalds * Implements the set_mem_map() operation for the in-kernel PCMCIA 406*1da177e4SLinus Torvalds * service (formerly SS_SetMemMap in Card Services). We configure 407*1da177e4SLinus Torvalds * the map speed as requested, but override the address ranges 408*1da177e4SLinus Torvalds * supplied by Card Services. 409*1da177e4SLinus Torvalds * 410*1da177e4SLinus Torvalds * Returns: 0 on success, -1 on error 411*1da177e4SLinus Torvalds */ 412*1da177e4SLinus Torvalds static int 413*1da177e4SLinus Torvalds soc_common_pcmcia_set_mem_map(struct pcmcia_socket *sock, struct pccard_mem_map *map) 414*1da177e4SLinus Torvalds { 415*1da177e4SLinus Torvalds struct soc_pcmcia_socket *skt = to_soc_pcmcia_socket(sock); 416*1da177e4SLinus Torvalds struct resource *res; 417*1da177e4SLinus Torvalds unsigned short speed = map->speed; 418*1da177e4SLinus Torvalds 419*1da177e4SLinus Torvalds debug(skt, 2, "map %u speed %u card_start %08x\n", 420*1da177e4SLinus Torvalds map->map, map->speed, map->card_start); 421*1da177e4SLinus Torvalds debug(skt, 2, "flags: %s%s%s%s%s%s%s%s\n", 422*1da177e4SLinus Torvalds (map->flags==0)?"<NONE>":"", 423*1da177e4SLinus Torvalds (map->flags&MAP_ACTIVE)?"ACTIVE ":"", 424*1da177e4SLinus Torvalds (map->flags&MAP_16BIT)?"16BIT ":"", 425*1da177e4SLinus Torvalds (map->flags&MAP_AUTOSZ)?"AUTOSZ ":"", 426*1da177e4SLinus Torvalds (map->flags&MAP_0WS)?"0WS ":"", 427*1da177e4SLinus Torvalds (map->flags&MAP_WRPROT)?"WRPROT ":"", 428*1da177e4SLinus Torvalds (map->flags&MAP_ATTRIB)?"ATTRIB ":"", 429*1da177e4SLinus Torvalds (map->flags&MAP_USE_WAIT)?"USE_WAIT ":""); 430*1da177e4SLinus Torvalds 431*1da177e4SLinus Torvalds if (map->map >= MAX_WIN) 432*1da177e4SLinus Torvalds return -EINVAL; 433*1da177e4SLinus Torvalds 434*1da177e4SLinus Torvalds if (map->flags & MAP_ACTIVE) { 435*1da177e4SLinus Torvalds if (speed == 0) 436*1da177e4SLinus Torvalds speed = 300; 437*1da177e4SLinus Torvalds } else { 438*1da177e4SLinus Torvalds speed = 0; 439*1da177e4SLinus Torvalds } 440*1da177e4SLinus Torvalds 441*1da177e4SLinus Torvalds if (map->flags & MAP_ATTRIB) { 442*1da177e4SLinus Torvalds res = &skt->res_attr; 443*1da177e4SLinus Torvalds skt->spd_attr[map->map] = speed; 444*1da177e4SLinus Torvalds skt->spd_mem[map->map] = 0; 445*1da177e4SLinus Torvalds } else { 446*1da177e4SLinus Torvalds res = &skt->res_mem; 447*1da177e4SLinus Torvalds skt->spd_attr[map->map] = 0; 448*1da177e4SLinus Torvalds skt->spd_mem[map->map] = speed; 449*1da177e4SLinus Torvalds } 450*1da177e4SLinus Torvalds 451*1da177e4SLinus Torvalds skt->ops->set_timing(skt); 452*1da177e4SLinus Torvalds 453*1da177e4SLinus Torvalds map->static_start = res->start + map->card_start; 454*1da177e4SLinus Torvalds 455*1da177e4SLinus Torvalds return 0; 456*1da177e4SLinus Torvalds } 457*1da177e4SLinus Torvalds 458*1da177e4SLinus Torvalds struct bittbl { 459*1da177e4SLinus Torvalds unsigned int mask; 460*1da177e4SLinus Torvalds const char *name; 461*1da177e4SLinus Torvalds }; 462*1da177e4SLinus Torvalds 463*1da177e4SLinus Torvalds static struct bittbl status_bits[] = { 464*1da177e4SLinus Torvalds { SS_WRPROT, "SS_WRPROT" }, 465*1da177e4SLinus Torvalds { SS_BATDEAD, "SS_BATDEAD" }, 466*1da177e4SLinus Torvalds { SS_BATWARN, "SS_BATWARN" }, 467*1da177e4SLinus Torvalds { SS_READY, "SS_READY" }, 468*1da177e4SLinus Torvalds { SS_DETECT, "SS_DETECT" }, 469*1da177e4SLinus Torvalds { SS_POWERON, "SS_POWERON" }, 470*1da177e4SLinus Torvalds { SS_STSCHG, "SS_STSCHG" }, 471*1da177e4SLinus Torvalds { SS_3VCARD, "SS_3VCARD" }, 472*1da177e4SLinus Torvalds { SS_XVCARD, "SS_XVCARD" }, 473*1da177e4SLinus Torvalds }; 474*1da177e4SLinus Torvalds 475*1da177e4SLinus Torvalds static struct bittbl conf_bits[] = { 476*1da177e4SLinus Torvalds { SS_PWR_AUTO, "SS_PWR_AUTO" }, 477*1da177e4SLinus Torvalds { SS_IOCARD, "SS_IOCARD" }, 478*1da177e4SLinus Torvalds { SS_RESET, "SS_RESET" }, 479*1da177e4SLinus Torvalds { SS_DMA_MODE, "SS_DMA_MODE" }, 480*1da177e4SLinus Torvalds { SS_SPKR_ENA, "SS_SPKR_ENA" }, 481*1da177e4SLinus Torvalds { SS_OUTPUT_ENA, "SS_OUTPUT_ENA" }, 482*1da177e4SLinus Torvalds }; 483*1da177e4SLinus Torvalds 484*1da177e4SLinus Torvalds static void 485*1da177e4SLinus Torvalds dump_bits(char **p, const char *prefix, unsigned int val, struct bittbl *bits, int sz) 486*1da177e4SLinus Torvalds { 487*1da177e4SLinus Torvalds char *b = *p; 488*1da177e4SLinus Torvalds int i; 489*1da177e4SLinus Torvalds 490*1da177e4SLinus Torvalds b += sprintf(b, "%-9s:", prefix); 491*1da177e4SLinus Torvalds for (i = 0; i < sz; i++) 492*1da177e4SLinus Torvalds if (val & bits[i].mask) 493*1da177e4SLinus Torvalds b += sprintf(b, " %s", bits[i].name); 494*1da177e4SLinus Torvalds *b++ = '\n'; 495*1da177e4SLinus Torvalds *p = b; 496*1da177e4SLinus Torvalds } 497*1da177e4SLinus Torvalds 498*1da177e4SLinus Torvalds /* 499*1da177e4SLinus Torvalds * Implements the /sys/class/pcmcia_socket/??/status file. 500*1da177e4SLinus Torvalds * 501*1da177e4SLinus Torvalds * Returns: the number of characters added to the buffer 502*1da177e4SLinus Torvalds */ 503*1da177e4SLinus Torvalds static ssize_t show_status(struct class_device *class_dev, char *buf) 504*1da177e4SLinus Torvalds { 505*1da177e4SLinus Torvalds struct soc_pcmcia_socket *skt = 506*1da177e4SLinus Torvalds container_of(class_dev, struct soc_pcmcia_socket, socket.dev); 507*1da177e4SLinus Torvalds char *p = buf; 508*1da177e4SLinus Torvalds 509*1da177e4SLinus Torvalds p+=sprintf(p, "slot : %d\n", skt->nr); 510*1da177e4SLinus Torvalds 511*1da177e4SLinus Torvalds dump_bits(&p, "status", skt->status, 512*1da177e4SLinus Torvalds status_bits, ARRAY_SIZE(status_bits)); 513*1da177e4SLinus Torvalds dump_bits(&p, "csc_mask", skt->cs_state.csc_mask, 514*1da177e4SLinus Torvalds status_bits, ARRAY_SIZE(status_bits)); 515*1da177e4SLinus Torvalds dump_bits(&p, "cs_flags", skt->cs_state.flags, 516*1da177e4SLinus Torvalds conf_bits, ARRAY_SIZE(conf_bits)); 517*1da177e4SLinus Torvalds 518*1da177e4SLinus Torvalds p+=sprintf(p, "Vcc : %d\n", skt->cs_state.Vcc); 519*1da177e4SLinus Torvalds p+=sprintf(p, "Vpp : %d\n", skt->cs_state.Vpp); 520*1da177e4SLinus Torvalds p+=sprintf(p, "IRQ : %d (%d)\n", skt->cs_state.io_irq, skt->irq); 521*1da177e4SLinus Torvalds if (skt->ops->show_timing) 522*1da177e4SLinus Torvalds p+=skt->ops->show_timing(skt, p); 523*1da177e4SLinus Torvalds 524*1da177e4SLinus Torvalds return p-buf; 525*1da177e4SLinus Torvalds } 526*1da177e4SLinus Torvalds static CLASS_DEVICE_ATTR(status, S_IRUGO, show_status, NULL); 527*1da177e4SLinus Torvalds 528*1da177e4SLinus Torvalds 529*1da177e4SLinus Torvalds static struct pccard_operations soc_common_pcmcia_operations = { 530*1da177e4SLinus Torvalds .init = soc_common_pcmcia_sock_init, 531*1da177e4SLinus Torvalds .suspend = soc_common_pcmcia_suspend, 532*1da177e4SLinus Torvalds .get_status = soc_common_pcmcia_get_status, 533*1da177e4SLinus Torvalds .get_socket = soc_common_pcmcia_get_socket, 534*1da177e4SLinus Torvalds .set_socket = soc_common_pcmcia_set_socket, 535*1da177e4SLinus Torvalds .set_io_map = soc_common_pcmcia_set_io_map, 536*1da177e4SLinus Torvalds .set_mem_map = soc_common_pcmcia_set_mem_map, 537*1da177e4SLinus Torvalds }; 538*1da177e4SLinus Torvalds 539*1da177e4SLinus Torvalds 540*1da177e4SLinus Torvalds int soc_pcmcia_request_irqs(struct soc_pcmcia_socket *skt, 541*1da177e4SLinus Torvalds struct pcmcia_irqs *irqs, int nr) 542*1da177e4SLinus Torvalds { 543*1da177e4SLinus Torvalds int i, res = 0; 544*1da177e4SLinus Torvalds 545*1da177e4SLinus Torvalds for (i = 0; i < nr; i++) { 546*1da177e4SLinus Torvalds if (irqs[i].sock != skt->nr) 547*1da177e4SLinus Torvalds continue; 548*1da177e4SLinus Torvalds res = request_irq(irqs[i].irq, soc_common_pcmcia_interrupt, 549*1da177e4SLinus Torvalds SA_INTERRUPT, irqs[i].str, skt); 550*1da177e4SLinus Torvalds if (res) 551*1da177e4SLinus Torvalds break; 552*1da177e4SLinus Torvalds set_irq_type(irqs[i].irq, IRQT_NOEDGE); 553*1da177e4SLinus Torvalds } 554*1da177e4SLinus Torvalds 555*1da177e4SLinus Torvalds if (res) { 556*1da177e4SLinus Torvalds printk(KERN_ERR "PCMCIA: request for IRQ%d failed (%d)\n", 557*1da177e4SLinus Torvalds irqs[i].irq, res); 558*1da177e4SLinus Torvalds 559*1da177e4SLinus Torvalds while (i--) 560*1da177e4SLinus Torvalds if (irqs[i].sock == skt->nr) 561*1da177e4SLinus Torvalds free_irq(irqs[i].irq, skt); 562*1da177e4SLinus Torvalds } 563*1da177e4SLinus Torvalds return res; 564*1da177e4SLinus Torvalds } 565*1da177e4SLinus Torvalds EXPORT_SYMBOL(soc_pcmcia_request_irqs); 566*1da177e4SLinus Torvalds 567*1da177e4SLinus Torvalds void soc_pcmcia_free_irqs(struct soc_pcmcia_socket *skt, 568*1da177e4SLinus Torvalds struct pcmcia_irqs *irqs, int nr) 569*1da177e4SLinus Torvalds { 570*1da177e4SLinus Torvalds int i; 571*1da177e4SLinus Torvalds 572*1da177e4SLinus Torvalds for (i = 0; i < nr; i++) 573*1da177e4SLinus Torvalds if (irqs[i].sock == skt->nr) 574*1da177e4SLinus Torvalds free_irq(irqs[i].irq, skt); 575*1da177e4SLinus Torvalds } 576*1da177e4SLinus Torvalds EXPORT_SYMBOL(soc_pcmcia_free_irqs); 577*1da177e4SLinus Torvalds 578*1da177e4SLinus Torvalds void soc_pcmcia_disable_irqs(struct soc_pcmcia_socket *skt, 579*1da177e4SLinus Torvalds struct pcmcia_irqs *irqs, int nr) 580*1da177e4SLinus Torvalds { 581*1da177e4SLinus Torvalds int i; 582*1da177e4SLinus Torvalds 583*1da177e4SLinus Torvalds for (i = 0; i < nr; i++) 584*1da177e4SLinus Torvalds if (irqs[i].sock == skt->nr) 585*1da177e4SLinus Torvalds set_irq_type(irqs[i].irq, IRQT_NOEDGE); 586*1da177e4SLinus Torvalds } 587*1da177e4SLinus Torvalds EXPORT_SYMBOL(soc_pcmcia_disable_irqs); 588*1da177e4SLinus Torvalds 589*1da177e4SLinus Torvalds void soc_pcmcia_enable_irqs(struct soc_pcmcia_socket *skt, 590*1da177e4SLinus Torvalds struct pcmcia_irqs *irqs, int nr) 591*1da177e4SLinus Torvalds { 592*1da177e4SLinus Torvalds int i; 593*1da177e4SLinus Torvalds 594*1da177e4SLinus Torvalds for (i = 0; i < nr; i++) 595*1da177e4SLinus Torvalds if (irqs[i].sock == skt->nr) { 596*1da177e4SLinus Torvalds set_irq_type(irqs[i].irq, IRQT_RISING); 597*1da177e4SLinus Torvalds set_irq_type(irqs[i].irq, IRQT_BOTHEDGE); 598*1da177e4SLinus Torvalds } 599*1da177e4SLinus Torvalds } 600*1da177e4SLinus Torvalds EXPORT_SYMBOL(soc_pcmcia_enable_irqs); 601*1da177e4SLinus Torvalds 602*1da177e4SLinus Torvalds 603*1da177e4SLinus Torvalds LIST_HEAD(soc_pcmcia_sockets); 604*1da177e4SLinus Torvalds DECLARE_MUTEX(soc_pcmcia_sockets_lock); 605*1da177e4SLinus Torvalds 606*1da177e4SLinus Torvalds static const char *skt_names[] = { 607*1da177e4SLinus Torvalds "PCMCIA socket 0", 608*1da177e4SLinus Torvalds "PCMCIA socket 1", 609*1da177e4SLinus Torvalds }; 610*1da177e4SLinus Torvalds 611*1da177e4SLinus Torvalds struct skt_dev_info { 612*1da177e4SLinus Torvalds int nskt; 613*1da177e4SLinus Torvalds struct soc_pcmcia_socket skt[0]; 614*1da177e4SLinus Torvalds }; 615*1da177e4SLinus Torvalds 616*1da177e4SLinus Torvalds #define SKT_DEV_INFO_SIZE(n) \ 617*1da177e4SLinus Torvalds (sizeof(struct skt_dev_info) + (n)*sizeof(struct soc_pcmcia_socket)) 618*1da177e4SLinus Torvalds 619*1da177e4SLinus Torvalds #ifdef CONFIG_CPU_FREQ 620*1da177e4SLinus Torvalds static int 621*1da177e4SLinus Torvalds soc_pcmcia_notifier(struct notifier_block *nb, unsigned long val, void *data) 622*1da177e4SLinus Torvalds { 623*1da177e4SLinus Torvalds struct soc_pcmcia_socket *skt; 624*1da177e4SLinus Torvalds struct cpufreq_freqs *freqs = data; 625*1da177e4SLinus Torvalds int ret = 0; 626*1da177e4SLinus Torvalds 627*1da177e4SLinus Torvalds down(&soc_pcmcia_sockets_lock); 628*1da177e4SLinus Torvalds list_for_each_entry(skt, &soc_pcmcia_sockets, node) 629*1da177e4SLinus Torvalds if ( skt->ops->frequency_change ) 630*1da177e4SLinus Torvalds ret += skt->ops->frequency_change(skt, val, freqs); 631*1da177e4SLinus Torvalds up(&soc_pcmcia_sockets_lock); 632*1da177e4SLinus Torvalds 633*1da177e4SLinus Torvalds return ret; 634*1da177e4SLinus Torvalds } 635*1da177e4SLinus Torvalds 636*1da177e4SLinus Torvalds static struct notifier_block soc_pcmcia_notifier_block = { 637*1da177e4SLinus Torvalds .notifier_call = soc_pcmcia_notifier 638*1da177e4SLinus Torvalds }; 639*1da177e4SLinus Torvalds 640*1da177e4SLinus Torvalds static int soc_pcmcia_cpufreq_register(void) 641*1da177e4SLinus Torvalds { 642*1da177e4SLinus Torvalds int ret; 643*1da177e4SLinus Torvalds 644*1da177e4SLinus Torvalds ret = cpufreq_register_notifier(&soc_pcmcia_notifier_block, 645*1da177e4SLinus Torvalds CPUFREQ_TRANSITION_NOTIFIER); 646*1da177e4SLinus Torvalds if (ret < 0) 647*1da177e4SLinus Torvalds printk(KERN_ERR "Unable to register CPU frequency change " 648*1da177e4SLinus Torvalds "notifier for PCMCIA (%d)\n", ret); 649*1da177e4SLinus Torvalds return ret; 650*1da177e4SLinus Torvalds } 651*1da177e4SLinus Torvalds 652*1da177e4SLinus Torvalds static void soc_pcmcia_cpufreq_unregister(void) 653*1da177e4SLinus Torvalds { 654*1da177e4SLinus Torvalds cpufreq_unregister_notifier(&soc_pcmcia_notifier_block, CPUFREQ_TRANSITION_NOTIFIER); 655*1da177e4SLinus Torvalds } 656*1da177e4SLinus Torvalds 657*1da177e4SLinus Torvalds #else 658*1da177e4SLinus Torvalds #define soc_pcmcia_cpufreq_register() 659*1da177e4SLinus Torvalds #define soc_pcmcia_cpufreq_unregister() 660*1da177e4SLinus Torvalds #endif 661*1da177e4SLinus Torvalds 662*1da177e4SLinus Torvalds int soc_common_drv_pcmcia_probe(struct device *dev, struct pcmcia_low_level *ops, int first, int nr) 663*1da177e4SLinus Torvalds { 664*1da177e4SLinus Torvalds struct skt_dev_info *sinfo; 665*1da177e4SLinus Torvalds struct soc_pcmcia_socket *skt; 666*1da177e4SLinus Torvalds int ret, i; 667*1da177e4SLinus Torvalds 668*1da177e4SLinus Torvalds down(&soc_pcmcia_sockets_lock); 669*1da177e4SLinus Torvalds 670*1da177e4SLinus Torvalds sinfo = kmalloc(SKT_DEV_INFO_SIZE(nr), GFP_KERNEL); 671*1da177e4SLinus Torvalds if (!sinfo) { 672*1da177e4SLinus Torvalds ret = -ENOMEM; 673*1da177e4SLinus Torvalds goto out; 674*1da177e4SLinus Torvalds } 675*1da177e4SLinus Torvalds 676*1da177e4SLinus Torvalds memset(sinfo, 0, SKT_DEV_INFO_SIZE(nr)); 677*1da177e4SLinus Torvalds sinfo->nskt = nr; 678*1da177e4SLinus Torvalds 679*1da177e4SLinus Torvalds /* 680*1da177e4SLinus Torvalds * Initialise the per-socket structure. 681*1da177e4SLinus Torvalds */ 682*1da177e4SLinus Torvalds for (i = 0; i < nr; i++) { 683*1da177e4SLinus Torvalds skt = &sinfo->skt[i]; 684*1da177e4SLinus Torvalds 685*1da177e4SLinus Torvalds skt->socket.ops = &soc_common_pcmcia_operations; 686*1da177e4SLinus Torvalds skt->socket.owner = ops->owner; 687*1da177e4SLinus Torvalds skt->socket.dev.dev = dev; 688*1da177e4SLinus Torvalds 689*1da177e4SLinus Torvalds init_timer(&skt->poll_timer); 690*1da177e4SLinus Torvalds skt->poll_timer.function = soc_common_pcmcia_poll_event; 691*1da177e4SLinus Torvalds skt->poll_timer.data = (unsigned long)skt; 692*1da177e4SLinus Torvalds skt->poll_timer.expires = jiffies + SOC_PCMCIA_POLL_PERIOD; 693*1da177e4SLinus Torvalds 694*1da177e4SLinus Torvalds skt->nr = first + i; 695*1da177e4SLinus Torvalds skt->irq = NO_IRQ; 696*1da177e4SLinus Torvalds skt->dev = dev; 697*1da177e4SLinus Torvalds skt->ops = ops; 698*1da177e4SLinus Torvalds 699*1da177e4SLinus Torvalds skt->res_skt.start = _PCMCIA(skt->nr); 700*1da177e4SLinus Torvalds skt->res_skt.end = _PCMCIA(skt->nr) + PCMCIASp - 1; 701*1da177e4SLinus Torvalds skt->res_skt.name = skt_names[skt->nr]; 702*1da177e4SLinus Torvalds skt->res_skt.flags = IORESOURCE_MEM; 703*1da177e4SLinus Torvalds 704*1da177e4SLinus Torvalds ret = request_resource(&iomem_resource, &skt->res_skt); 705*1da177e4SLinus Torvalds if (ret) 706*1da177e4SLinus Torvalds goto out_err_1; 707*1da177e4SLinus Torvalds 708*1da177e4SLinus Torvalds skt->res_io.start = _PCMCIAIO(skt->nr); 709*1da177e4SLinus Torvalds skt->res_io.end = _PCMCIAIO(skt->nr) + PCMCIAIOSp - 1; 710*1da177e4SLinus Torvalds skt->res_io.name = "io"; 711*1da177e4SLinus Torvalds skt->res_io.flags = IORESOURCE_MEM | IORESOURCE_BUSY; 712*1da177e4SLinus Torvalds 713*1da177e4SLinus Torvalds ret = request_resource(&skt->res_skt, &skt->res_io); 714*1da177e4SLinus Torvalds if (ret) 715*1da177e4SLinus Torvalds goto out_err_2; 716*1da177e4SLinus Torvalds 717*1da177e4SLinus Torvalds skt->res_mem.start = _PCMCIAMem(skt->nr); 718*1da177e4SLinus Torvalds skt->res_mem.end = _PCMCIAMem(skt->nr) + PCMCIAMemSp - 1; 719*1da177e4SLinus Torvalds skt->res_mem.name = "memory"; 720*1da177e4SLinus Torvalds skt->res_mem.flags = IORESOURCE_MEM; 721*1da177e4SLinus Torvalds 722*1da177e4SLinus Torvalds ret = request_resource(&skt->res_skt, &skt->res_mem); 723*1da177e4SLinus Torvalds if (ret) 724*1da177e4SLinus Torvalds goto out_err_3; 725*1da177e4SLinus Torvalds 726*1da177e4SLinus Torvalds skt->res_attr.start = _PCMCIAAttr(skt->nr); 727*1da177e4SLinus Torvalds skt->res_attr.end = _PCMCIAAttr(skt->nr) + PCMCIAAttrSp - 1; 728*1da177e4SLinus Torvalds skt->res_attr.name = "attribute"; 729*1da177e4SLinus Torvalds skt->res_attr.flags = IORESOURCE_MEM; 730*1da177e4SLinus Torvalds 731*1da177e4SLinus Torvalds ret = request_resource(&skt->res_skt, &skt->res_attr); 732*1da177e4SLinus Torvalds if (ret) 733*1da177e4SLinus Torvalds goto out_err_4; 734*1da177e4SLinus Torvalds 735*1da177e4SLinus Torvalds skt->virt_io = ioremap(skt->res_io.start, 0x10000); 736*1da177e4SLinus Torvalds if (skt->virt_io == NULL) { 737*1da177e4SLinus Torvalds ret = -ENOMEM; 738*1da177e4SLinus Torvalds goto out_err_5; 739*1da177e4SLinus Torvalds } 740*1da177e4SLinus Torvalds 741*1da177e4SLinus Torvalds if ( list_empty(&soc_pcmcia_sockets) ) 742*1da177e4SLinus Torvalds soc_pcmcia_cpufreq_register(); 743*1da177e4SLinus Torvalds 744*1da177e4SLinus Torvalds list_add(&skt->node, &soc_pcmcia_sockets); 745*1da177e4SLinus Torvalds 746*1da177e4SLinus Torvalds /* 747*1da177e4SLinus Torvalds * We initialize default socket timing here, because 748*1da177e4SLinus Torvalds * we are not guaranteed to see a SetIOMap operation at 749*1da177e4SLinus Torvalds * runtime. 750*1da177e4SLinus Torvalds */ 751*1da177e4SLinus Torvalds ops->set_timing(skt); 752*1da177e4SLinus Torvalds 753*1da177e4SLinus Torvalds ret = ops->hw_init(skt); 754*1da177e4SLinus Torvalds if (ret) 755*1da177e4SLinus Torvalds goto out_err_6; 756*1da177e4SLinus Torvalds 757*1da177e4SLinus Torvalds skt->socket.features = SS_CAP_STATIC_MAP|SS_CAP_PCCARD; 758*1da177e4SLinus Torvalds skt->socket.resource_ops = &pccard_static_ops; 759*1da177e4SLinus Torvalds skt->socket.irq_mask = 0; 760*1da177e4SLinus Torvalds skt->socket.map_size = PAGE_SIZE; 761*1da177e4SLinus Torvalds skt->socket.pci_irq = skt->irq; 762*1da177e4SLinus Torvalds skt->socket.io_offset = (unsigned long)skt->virt_io; 763*1da177e4SLinus Torvalds 764*1da177e4SLinus Torvalds skt->status = soc_common_pcmcia_skt_state(skt); 765*1da177e4SLinus Torvalds 766*1da177e4SLinus Torvalds ret = pcmcia_register_socket(&skt->socket); 767*1da177e4SLinus Torvalds if (ret) 768*1da177e4SLinus Torvalds goto out_err_7; 769*1da177e4SLinus Torvalds 770*1da177e4SLinus Torvalds WARN_ON(skt->socket.sock != i); 771*1da177e4SLinus Torvalds 772*1da177e4SLinus Torvalds add_timer(&skt->poll_timer); 773*1da177e4SLinus Torvalds 774*1da177e4SLinus Torvalds class_device_create_file(&skt->socket.dev, &class_device_attr_status); 775*1da177e4SLinus Torvalds } 776*1da177e4SLinus Torvalds 777*1da177e4SLinus Torvalds dev_set_drvdata(dev, sinfo); 778*1da177e4SLinus Torvalds ret = 0; 779*1da177e4SLinus Torvalds goto out; 780*1da177e4SLinus Torvalds 781*1da177e4SLinus Torvalds do { 782*1da177e4SLinus Torvalds skt = &sinfo->skt[i]; 783*1da177e4SLinus Torvalds 784*1da177e4SLinus Torvalds del_timer_sync(&skt->poll_timer); 785*1da177e4SLinus Torvalds pcmcia_unregister_socket(&skt->socket); 786*1da177e4SLinus Torvalds 787*1da177e4SLinus Torvalds out_err_7: 788*1da177e4SLinus Torvalds flush_scheduled_work(); 789*1da177e4SLinus Torvalds 790*1da177e4SLinus Torvalds ops->hw_shutdown(skt); 791*1da177e4SLinus Torvalds out_err_6: 792*1da177e4SLinus Torvalds list_del(&skt->node); 793*1da177e4SLinus Torvalds iounmap(skt->virt_io); 794*1da177e4SLinus Torvalds out_err_5: 795*1da177e4SLinus Torvalds release_resource(&skt->res_attr); 796*1da177e4SLinus Torvalds out_err_4: 797*1da177e4SLinus Torvalds release_resource(&skt->res_mem); 798*1da177e4SLinus Torvalds out_err_3: 799*1da177e4SLinus Torvalds release_resource(&skt->res_io); 800*1da177e4SLinus Torvalds out_err_2: 801*1da177e4SLinus Torvalds release_resource(&skt->res_skt); 802*1da177e4SLinus Torvalds out_err_1: 803*1da177e4SLinus Torvalds i--; 804*1da177e4SLinus Torvalds } while (i > 0); 805*1da177e4SLinus Torvalds 806*1da177e4SLinus Torvalds kfree(sinfo); 807*1da177e4SLinus Torvalds 808*1da177e4SLinus Torvalds out: 809*1da177e4SLinus Torvalds up(&soc_pcmcia_sockets_lock); 810*1da177e4SLinus Torvalds return ret; 811*1da177e4SLinus Torvalds } 812*1da177e4SLinus Torvalds 813*1da177e4SLinus Torvalds int soc_common_drv_pcmcia_remove(struct device *dev) 814*1da177e4SLinus Torvalds { 815*1da177e4SLinus Torvalds struct skt_dev_info *sinfo = dev_get_drvdata(dev); 816*1da177e4SLinus Torvalds int i; 817*1da177e4SLinus Torvalds 818*1da177e4SLinus Torvalds dev_set_drvdata(dev, NULL); 819*1da177e4SLinus Torvalds 820*1da177e4SLinus Torvalds down(&soc_pcmcia_sockets_lock); 821*1da177e4SLinus Torvalds for (i = 0; i < sinfo->nskt; i++) { 822*1da177e4SLinus Torvalds struct soc_pcmcia_socket *skt = &sinfo->skt[i]; 823*1da177e4SLinus Torvalds 824*1da177e4SLinus Torvalds del_timer_sync(&skt->poll_timer); 825*1da177e4SLinus Torvalds 826*1da177e4SLinus Torvalds pcmcia_unregister_socket(&skt->socket); 827*1da177e4SLinus Torvalds 828*1da177e4SLinus Torvalds flush_scheduled_work(); 829*1da177e4SLinus Torvalds 830*1da177e4SLinus Torvalds skt->ops->hw_shutdown(skt); 831*1da177e4SLinus Torvalds 832*1da177e4SLinus Torvalds soc_common_pcmcia_config_skt(skt, &dead_socket); 833*1da177e4SLinus Torvalds 834*1da177e4SLinus Torvalds list_del(&skt->node); 835*1da177e4SLinus Torvalds iounmap(skt->virt_io); 836*1da177e4SLinus Torvalds skt->virt_io = NULL; 837*1da177e4SLinus Torvalds release_resource(&skt->res_attr); 838*1da177e4SLinus Torvalds release_resource(&skt->res_mem); 839*1da177e4SLinus Torvalds release_resource(&skt->res_io); 840*1da177e4SLinus Torvalds release_resource(&skt->res_skt); 841*1da177e4SLinus Torvalds } 842*1da177e4SLinus Torvalds if ( list_empty(&soc_pcmcia_sockets) ) 843*1da177e4SLinus Torvalds soc_pcmcia_cpufreq_unregister(); 844*1da177e4SLinus Torvalds 845*1da177e4SLinus Torvalds up(&soc_pcmcia_sockets_lock); 846*1da177e4SLinus Torvalds 847*1da177e4SLinus Torvalds kfree(sinfo); 848*1da177e4SLinus Torvalds 849*1da177e4SLinus Torvalds return 0; 850*1da177e4SLinus Torvalds } 851