1/*
2 *
3 * Alchemy Semi Db1x00 boards specific pcmcia routines.
4 *
5 * Copyright 2002 MontaVista Software Inc.
6 * Author: MontaVista Software, Inc.
7 *         	ppopov@mvista.com or source@mvista.com
8 *
9 * Copyright 2004 Pete Popov, updated the driver to 2.6.
10 * Followed the sa11xx API and largely copied many of the hardware
11 * independent functions.
12 *
13 * ########################################################################
14 *
15 *  This program is free software; you can distribute it and/or modify it
16 *  under the terms of the GNU General Public License (Version 2) as
17 *  published by the Free Software Foundation.
18 *
19 *  This program is distributed in the hope it will be useful, but WITHOUT
20 *  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
21 *  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
22 *  for more details.
23 *
24 *  You should have received a copy of the GNU General Public License along
25 *  with this program; if not, write to the Free Software Foundation, Inc.,
26 *  59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
27 *
28 * ########################################################################
29 *
30 *
31 */
32
33#include <linux/module.h>
34#include <linux/kernel.h>
35#include <linux/errno.h>
36#include <linux/interrupt.h>
37#include <linux/device.h>
38#include <linux/init.h>
39
40#include <asm/irq.h>
41#include <asm/signal.h>
42#include <asm/mach-au1x00/au1000.h>
43
44#if defined(CONFIG_MIPS_DB1200)
45	#include <db1200.h>
46#elif defined(CONFIG_MIPS_PB1200)
47	#include <pb1200.h>
48#else
49	#include <asm/mach-db1x00/db1x00.h>
50	static BCSR * const bcsr = (BCSR *)BCSR_KSEG1_ADDR;
51#endif
52
53#include "au1000_generic.h"
54
55#define debug(x,args...)
56
57
58struct au1000_pcmcia_socket au1000_pcmcia_socket[PCMCIA_NUM_SOCKS];
59extern int au1x00_pcmcia_socket_probe(struct device *, struct pcmcia_low_level *, int, int);
60
61static int db1x00_pcmcia_hw_init(struct au1000_pcmcia_socket *skt)
62{
63#ifdef CONFIG_MIPS_DB1550
64	skt->irq = skt->nr ? AU1000_GPIO_5 : AU1000_GPIO_3;
65#elif defined(CONFIG_MIPS_DB1200) || defined(CONFIG_MIPS_PB1200)
66	skt->irq = skt->nr ? BOARD_PC1_INT : BOARD_PC0_INT;
67#else
68	skt->irq = skt->nr ? AU1000_GPIO_5 : AU1000_GPIO_2;
69#endif
70	return 0;
71}
72
73static void db1x00_pcmcia_shutdown(struct au1000_pcmcia_socket *skt)
74{
75	bcsr->pcmcia = 0; /* turn off power */
76	au_sync_delay(2);
77}
78
79static void
80db1x00_pcmcia_socket_state(struct au1000_pcmcia_socket *skt, struct pcmcia_state *state)
81{
82	u32 inserted;
83	unsigned char vs;
84
85	state->ready = 0;
86	state->vs_Xv = 0;
87	state->vs_3v = 0;
88	state->detect = 0;
89
90	switch (skt->nr) {
91	case 0:
92		vs = bcsr->status & 0x3;
93#if defined(CONFIG_MIPS_DB1200) || defined(CONFIG_MIPS_PB1200)
94		inserted = BOARD_CARD_INSERTED(0);
95#else
96		inserted = !(bcsr->status & (1<<4));
97#endif
98		break;
99	case 1:
100		vs = (bcsr->status & 0xC)>>2;
101#if defined(CONFIG_MIPS_DB1200) || defined(CONFIG_MIPS_PB1200)
102		inserted = BOARD_CARD_INSERTED(1);
103#else
104		inserted = !(bcsr->status & (1<<5));
105#endif
106		break;
107	default:/* should never happen */
108		return;
109	}
110
111	if (inserted)
112		debug("db1x00 socket %d: inserted %d, vs %d pcmcia %x\n",
113				skt->nr, inserted, vs, bcsr->pcmcia);
114
115	if (inserted) {
116		switch (vs) {
117			case 0:
118			case 2:
119				state->vs_3v=1;
120				break;
121			case 3: /* 5V */
122				break;
123			default:
124				/* return without setting 'detect' */
125				printk(KERN_ERR "db1x00 bad VS (%d)\n",
126						vs);
127		}
128		state->detect = 1;
129		state->ready = 1;
130	}
131	else {
132		/* if the card was previously inserted and then ejected,
133		 * we should turn off power to it
134		 */
135		if ((skt->nr == 0) && (bcsr->pcmcia & BCSR_PCMCIA_PC0RST)) {
136			bcsr->pcmcia &= ~(BCSR_PCMCIA_PC0RST |
137					BCSR_PCMCIA_PC0DRVEN |
138					BCSR_PCMCIA_PC0VPP |
139					BCSR_PCMCIA_PC0VCC);
140			au_sync_delay(10);
141		}
142		else if ((skt->nr == 1) && bcsr->pcmcia & BCSR_PCMCIA_PC1RST) {
143			bcsr->pcmcia &= ~(BCSR_PCMCIA_PC1RST |
144					BCSR_PCMCIA_PC1DRVEN |
145					BCSR_PCMCIA_PC1VPP |
146					BCSR_PCMCIA_PC1VCC);
147			au_sync_delay(10);
148		}
149	}
150
151	state->bvd1=1;
152	state->bvd2=1;
153	state->wrprot=0;
154}
155
156static int
157db1x00_pcmcia_configure_socket(struct au1000_pcmcia_socket *skt, struct socket_state_t *state)
158{
159	u16 pwr;
160	int sock = skt->nr;
161
162	debug("config_skt %d Vcc %dV Vpp %dV, reset %d\n",
163			sock, state->Vcc, state->Vpp,
164			state->flags & SS_RESET);
165
166	/* pcmcia reg was set to zero at init time. Be careful when
167	 * initializing a socket not to wipe out the settings of the
168	 * other socket.
169	 */
170	pwr = bcsr->pcmcia;
171	pwr &= ~(0xf << sock*8); /* clear voltage settings */
172
173	state->Vpp = 0;
174	switch(state->Vcc){
175		case 0:  /* Vcc 0 */
176			pwr |= SET_VCC_VPP(0,0,sock);
177			break;
178		case 50: /* Vcc 5V */
179			switch(state->Vpp) {
180				case 0:
181					pwr |= SET_VCC_VPP(2,0,sock);
182					break;
183				case 50:
184					pwr |= SET_VCC_VPP(2,1,sock);
185					break;
186				case 12:
187					pwr |= SET_VCC_VPP(2,2,sock);
188					break;
189				case 33:
190				default:
191					pwr |= SET_VCC_VPP(0,0,sock);
192					printk("%s: bad Vcc/Vpp (%d:%d)\n",
193							__FUNCTION__,
194							state->Vcc,
195							state->Vpp);
196					break;
197			}
198			break;
199		case 33: /* Vcc 3.3V */
200			switch(state->Vpp) {
201				case 0:
202					pwr |= SET_VCC_VPP(1,0,sock);
203					break;
204				case 12:
205					pwr |= SET_VCC_VPP(1,2,sock);
206					break;
207				case 33:
208					pwr |= SET_VCC_VPP(1,1,sock);
209					break;
210				case 50:
211				default:
212					pwr |= SET_VCC_VPP(0,0,sock);
213					printk("%s: bad Vcc/Vpp (%d:%d)\n",
214							__FUNCTION__,
215							state->Vcc,
216							state->Vpp);
217					break;
218			}
219			break;
220		default: /* what's this ? */
221			pwr |= SET_VCC_VPP(0,0,sock);
222			printk(KERN_ERR "%s: bad Vcc %d\n",
223					__FUNCTION__, state->Vcc);
224			break;
225	}
226
227	bcsr->pcmcia = pwr;
228	au_sync_delay(300);
229
230	if (sock == 0) {
231		if (!(state->flags & SS_RESET)) {
232			pwr |= BCSR_PCMCIA_PC0DRVEN;
233			bcsr->pcmcia = pwr;
234			au_sync_delay(300);
235			pwr |= BCSR_PCMCIA_PC0RST;
236			bcsr->pcmcia = pwr;
237			au_sync_delay(100);
238		}
239		else {
240			pwr &= ~(BCSR_PCMCIA_PC0RST | BCSR_PCMCIA_PC0DRVEN);
241			bcsr->pcmcia = pwr;
242			au_sync_delay(100);
243		}
244	}
245	else {
246		if (!(state->flags & SS_RESET)) {
247			pwr |= BCSR_PCMCIA_PC1DRVEN;
248			bcsr->pcmcia = pwr;
249			au_sync_delay(300);
250			pwr |= BCSR_PCMCIA_PC1RST;
251			bcsr->pcmcia = pwr;
252			au_sync_delay(100);
253		}
254		else {
255			pwr &= ~(BCSR_PCMCIA_PC1RST | BCSR_PCMCIA_PC1DRVEN);
256			bcsr->pcmcia = pwr;
257			au_sync_delay(100);
258		}
259	}
260	return 0;
261}
262
263/*
264 * Enable card status IRQs on (re-)initialisation.  This can
265 * be called at initialisation, power management event, or
266 * pcmcia event.
267 */
268void db1x00_socket_init(struct au1000_pcmcia_socket *skt)
269{
270	/* nothing to do for now */
271}
272
273/*
274 * Disable card status IRQs and PCMCIA bus on suspend.
275 */
276void db1x00_socket_suspend(struct au1000_pcmcia_socket *skt)
277{
278	/* nothing to do for now */
279}
280
281struct pcmcia_low_level db1x00_pcmcia_ops = {
282	.owner			= THIS_MODULE,
283
284	.hw_init 		= db1x00_pcmcia_hw_init,
285	.hw_shutdown		= db1x00_pcmcia_shutdown,
286
287	.socket_state		= db1x00_pcmcia_socket_state,
288	.configure_socket	= db1x00_pcmcia_configure_socket,
289
290	.socket_init		= db1x00_socket_init,
291	.socket_suspend		= db1x00_socket_suspend
292};
293
294int au1x_board_init(struct device *dev)
295{
296	int ret = -ENODEV;
297	bcsr->pcmcia = 0; /* turn off power, if it's not already off */
298	au_sync_delay(2);
299	ret = au1x00_pcmcia_socket_probe(dev, &db1x00_pcmcia_ops, 0, 2);
300	return ret;
301}
302