xref: /openbmc/linux/drivers/pcmcia/soc_common.c (revision 1da177e4c3f41524e886b7f1b8a0c1fc7321cac2)
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