blob: 5a979cb8f3e66a54fc7e1ea98548e92f9018b43d [file] [log] [blame]
Linus Torvalds1da177e2005-04-16 15:20:36 -07001/*
2 *
Manuel Lauss66213b32009-10-04 14:55:27 +02003 * Alchemy Semi Pb1000 boards specific pcmcia routines.
Linus Torvalds1da177e2005-04-16 15:20:36 -07004 *
5 * Copyright 2002 MontaVista Software Inc.
6 * Author: MontaVista Software, Inc.
7 * ppopov@mvista.com or source@mvista.com
8 *
9 * ########################################################################
10 *
11 * This program is free software; you can distribute it and/or modify it
12 * under the terms of the GNU General Public License (Version 2) as
13 * published by the Free Software Foundation.
14 *
15 * This program is distributed in the hope it will be useful, but WITHOUT
16 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
17 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
18 * for more details.
19 *
20 * You should have received a copy of the GNU General Public License along
21 * with this program; if not, write to the Free Software Foundation, Inc.,
22 * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
23 */
24#include <linux/module.h>
25#include <linux/init.h>
26#include <linux/delay.h>
27#include <linux/ioport.h>
28#include <linux/kernel.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070029#include <linux/timer.h>
30#include <linux/mm.h>
31#include <linux/proc_fs.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070032#include <linux/types.h>
33
Linus Torvalds1da177e2005-04-16 15:20:36 -070034#include <pcmcia/cs_types.h>
35#include <pcmcia/cs.h>
36#include <pcmcia/ss.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070037#include <pcmcia/cistpl.h>
38#include <pcmcia/bus_ops.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070039
40#include <asm/io.h>
41#include <asm/irq.h>
42#include <asm/system.h>
43
44#include <asm/au1000.h>
45#include <asm/au1000_pcmcia.h>
46
47#define debug(fmt, arg...) do { } while (0)
48
Linus Torvalds1da177e2005-04-16 15:20:36 -070049#include <asm/pb1000.h>
50#define PCMCIA_IRQ AU1000_GPIO_15
Linus Torvalds1da177e2005-04-16 15:20:36 -070051
52static int pb1x00_pcmcia_init(struct pcmcia_init *init)
53{
Linus Torvalds1da177e2005-04-16 15:20:36 -070054 u16 pcr;
55 pcr = PCR_SLOT_0_RST | PCR_SLOT_1_RST;
56
57 au_writel(0x8000, PB1000_MDR); /* clear pcmcia interrupt */
58 au_sync_delay(100);
59 au_writel(0x4000, PB1000_MDR); /* enable pcmcia interrupt */
60 au_sync();
61
62 pcr |= SET_VCC_VPP(VCC_HIZ,VPP_HIZ,0);
63 pcr |= SET_VCC_VPP(VCC_HIZ,VPP_HIZ,1);
64 au_writel(pcr, PB1000_PCR);
65 au_sync_delay(20);
66
67 return PCMCIA_NUM_SOCKS;
Linus Torvalds1da177e2005-04-16 15:20:36 -070068}
69
70static int pb1x00_pcmcia_shutdown(void)
71{
Linus Torvalds1da177e2005-04-16 15:20:36 -070072 u16 pcr;
73 pcr = PCR_SLOT_0_RST | PCR_SLOT_1_RST;
74 pcr |= SET_VCC_VPP(VCC_HIZ,VPP_HIZ,0);
75 pcr |= SET_VCC_VPP(VCC_HIZ,VPP_HIZ,1);
76 au_writel(pcr, PB1000_PCR);
77 au_sync_delay(20);
78 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -070079}
80
81static int
82pb1x00_pcmcia_socket_state(unsigned sock, struct pcmcia_state *state)
83{
84 u32 inserted0, inserted1;
85 u16 vs0, vs1;
86
Linus Torvalds1da177e2005-04-16 15:20:36 -070087 vs0 = vs1 = (u16)au_readl(PB1000_ACR1);
88 inserted0 = !(vs0 & (ACR1_SLOT_0_CD1 | ACR1_SLOT_0_CD2));
89 inserted1 = !(vs1 & (ACR1_SLOT_1_CD1 | ACR1_SLOT_1_CD2));
90 vs0 = (vs0 >> 4) & 0x3;
91 vs1 = (vs1 >> 12) & 0x3;
Linus Torvalds1da177e2005-04-16 15:20:36 -070092
93 state->ready = 0;
94 state->vs_Xv = 0;
95 state->vs_3v = 0;
96 state->detect = 0;
97
98 if (sock == 0) {
99 if (inserted0) {
100 switch (vs0) {
101 case 0:
102 case 2:
103 state->vs_3v=1;
104 break;
105 case 3: /* 5V */
106 break;
107 default:
108 /* return without setting 'detect' */
109 printk(KERN_ERR "pb1x00 bad VS (%d)\n",
110 vs0);
111 return 0;
112 }
113 state->detect = 1;
114 }
115 }
116 else {
117 if (inserted1) {
118 switch (vs1) {
119 case 0:
120 case 2:
121 state->vs_3v=1;
122 break;
123 case 3: /* 5V */
124 break;
125 default:
126 /* return without setting 'detect' */
127 printk(KERN_ERR "pb1x00 bad VS (%d)\n",
128 vs1);
129 return 0;
130 }
131 state->detect = 1;
132 }
133 }
134
135 if (state->detect) {
136 state->ready = 1;
137 }
138
139 state->bvd1=1;
140 state->bvd2=1;
141 state->wrprot=0;
142 return 1;
143}
144
145
146static int pb1x00_pcmcia_get_irq_info(struct pcmcia_irq_info *info)
147{
148
149 if(info->sock > PCMCIA_MAX_SOCK) return -1;
150
151 /*
152 * Even in the case of the Pb1000, both sockets are connected
153 * to the same irq line.
154 */
155 info->irq = PCMCIA_IRQ;
156
157 return 0;
158}
159
160
161static int
162pb1x00_pcmcia_configure_socket(const struct pcmcia_configure *configure)
163{
164 u16 pcr;
165
166 if(configure->sock > PCMCIA_MAX_SOCK) return -1;
167
Linus Torvalds1da177e2005-04-16 15:20:36 -0700168 pcr = au_readl(PB1000_PCR);
169
170 if (configure->sock == 0) {
171 pcr &= ~(PCR_SLOT_0_VCC0 | PCR_SLOT_0_VCC1 |
172 PCR_SLOT_0_VPP0 | PCR_SLOT_0_VPP1);
173 }
174 else {
175 pcr &= ~(PCR_SLOT_1_VCC0 | PCR_SLOT_1_VCC1 |
176 PCR_SLOT_1_VPP0 | PCR_SLOT_1_VPP1);
177 }
178
179 pcr &= ~PCR_SLOT_0_RST;
180 debug("Vcc %dV Vpp %dV, pcr %x\n",
181 configure->vcc, configure->vpp, pcr);
182 switch(configure->vcc){
183 case 0: /* Vcc 0 */
184 switch(configure->vpp) {
185 case 0:
186 pcr |= SET_VCC_VPP(VCC_HIZ,VPP_GND,
187 configure->sock);
188 break;
189 case 12:
190 pcr |= SET_VCC_VPP(VCC_HIZ,VPP_12V,
191 configure->sock);
192 break;
193 case 50:
194 pcr |= SET_VCC_VPP(VCC_HIZ,VPP_5V,
195 configure->sock);
196 break;
197 case 33:
198 pcr |= SET_VCC_VPP(VCC_HIZ,VPP_3V,
199 configure->sock);
200 break;
201 default:
202 pcr |= SET_VCC_VPP(VCC_HIZ,VPP_HIZ,
203 configure->sock);
204 printk("%s: bad Vcc/Vpp (%d:%d)\n",
Harvey Harrison2e11cb42008-05-01 04:34:54 -0700205 __func__,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700206 configure->vcc,
207 configure->vpp);
208 break;
209 }
210 break;
211 case 50: /* Vcc 5V */
212 switch(configure->vpp) {
213 case 0:
214 pcr |= SET_VCC_VPP(VCC_5V,VPP_GND,
215 configure->sock);
216 break;
217 case 50:
218 pcr |= SET_VCC_VPP(VCC_5V,VPP_5V,
219 configure->sock);
220 break;
221 case 12:
222 pcr |= SET_VCC_VPP(VCC_5V,VPP_12V,
223 configure->sock);
224 break;
225 case 33:
226 pcr |= SET_VCC_VPP(VCC_5V,VPP_3V,
227 configure->sock);
228 break;
229 default:
230 pcr |= SET_VCC_VPP(VCC_HIZ,VPP_HIZ,
231 configure->sock);
232 printk("%s: bad Vcc/Vpp (%d:%d)\n",
Harvey Harrison2e11cb42008-05-01 04:34:54 -0700233 __func__,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700234 configure->vcc,
235 configure->vpp);
236 break;
237 }
238 break;
239 case 33: /* Vcc 3.3V */
240 switch(configure->vpp) {
241 case 0:
242 pcr |= SET_VCC_VPP(VCC_3V,VPP_GND,
243 configure->sock);
244 break;
245 case 50:
246 pcr |= SET_VCC_VPP(VCC_3V,VPP_5V,
247 configure->sock);
248 break;
249 case 12:
250 pcr |= SET_VCC_VPP(VCC_3V,VPP_12V,
251 configure->sock);
252 break;
253 case 33:
254 pcr |= SET_VCC_VPP(VCC_3V,VPP_3V,
255 configure->sock);
256 break;
257 default:
258 pcr |= SET_VCC_VPP(VCC_HIZ,VPP_HIZ,
259 configure->sock);
260 printk("%s: bad Vcc/Vpp (%d:%d)\n",
Harvey Harrison2e11cb42008-05-01 04:34:54 -0700261 __func__,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700262 configure->vcc,
263 configure->vpp);
264 break;
265 }
266 break;
267 default: /* what's this ? */
268 pcr |= SET_VCC_VPP(VCC_HIZ,VPP_HIZ,configure->sock);
269 printk(KERN_ERR "%s: bad Vcc %d\n",
Harvey Harrison2e11cb42008-05-01 04:34:54 -0700270 __func__, configure->vcc);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700271 break;
272 }
273
274 if (configure->sock == 0) {
275 pcr &= ~(PCR_SLOT_0_RST);
276 if (configure->reset)
277 pcr |= PCR_SLOT_0_RST;
278 }
279 else {
280 pcr &= ~(PCR_SLOT_1_RST);
281 if (configure->reset)
282 pcr |= PCR_SLOT_1_RST;
283 }
284 au_writel(pcr, PB1000_PCR);
285 au_sync_delay(300);
286
Linus Torvalds1da177e2005-04-16 15:20:36 -0700287 return 0;
288}
289
290
291struct pcmcia_low_level pb1x00_pcmcia_ops = {
292 pb1x00_pcmcia_init,
293 pb1x00_pcmcia_shutdown,
294 pb1x00_pcmcia_socket_state,
295 pb1x00_pcmcia_get_irq_info,
296 pb1x00_pcmcia_configure_socket
297};