blob: 1a8c1239d8859e9a6ac50d263b32b6217379ee99 [file] [log] [blame]
wdenkc6097192002-11-03 00:24:07 +00001/*
2 * (C) Copyright 2000-2002
3 * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
4 *
5 * See file CREDITS for list of people who contributed to this
6 * project.
7 *
8 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public License as
10 * published by the Free Software Foundation; either version 2 of
11 * the License, or (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
21 * MA 02111-1307 USA
22 *
23 ********************************************************************
24 *
25 * Lots of code copied from:
26 *
27 * m8xx_pcmcia.c - Linux PCMCIA socket driver for the mpc8xx series.
28 * (C) 1999-2000 Magnus Damm <damm@bitsmart.com>
29 *
30 * "The ExCA standard specifies that socket controllers should provide
31 * two IO and five memory windows per socket, which can be independently
32 * configured and positioned in the host address space and mapped to
33 * arbitrary segments of card address space. " - David A Hinds. 1999
34 *
35 * This controller does _not_ meet the ExCA standard.
36 *
37 * m8xx pcmcia controller brief info:
38 * + 8 windows (attrib, mem, i/o)
39 * + up to two slots (SLOT_A and SLOT_B)
40 * + inputpins, outputpins, event and mask registers.
41 * - no offset register. sigh.
42 *
43 * Because of the lacking offset register we must map the whole card.
44 * We assign each memory window PCMCIA_MEM_WIN_SIZE address space.
45 * Make sure there is (PCMCIA_MEM_WIN_SIZE * PCMCIA_MEM_WIN_NO
46 * * PCMCIA_SOCKETS_NO) bytes at PCMCIA_MEM_WIN_BASE.
47 * The i/o windows are dynamically allocated at PCMCIA_IO_WIN_BASE.
48 * They are maximum 64KByte each...
49 */
50
51/* #define DEBUG 1 */
52
53/*
54 * PCMCIA support
55 */
56#include <common.h>
57#include <command.h>
58#include <config.h>
59#include <pcmcia.h>
wdenkc6097192002-11-03 00:24:07 +000060#if defined(CONFIG_IDE_8xx_PCCARD) && defined(CONFIG_8xx)
61#include <mpc8xx.h>
62#endif
63#if defined(CONFIG_LWMON)
64#include <i2c.h>
65#endif
66
67#if (CONFIG_COMMANDS & CFG_CMD_PCMCIA) || \
68 ((CONFIG_COMMANDS & CFG_CMD_IDE) && defined(CONFIG_IDE_8xx_PCCARD))
69
70int pcmcia_on (void);
71
72#if (CONFIG_COMMANDS & CFG_CMD_PCMCIA)
73static int pcmcia_off (void);
wdenke5d61c72003-05-18 11:30:09 +000074#endif
75
76#ifdef CONFIG_I82365
77
78extern int i82365_init (void);
79extern void i82365_exit (void);
80
81#else /* ! CONFIG_I82365 */
82
83#if (CONFIG_COMMANDS & CFG_CMD_PCMCIA)
wdenkc6097192002-11-03 00:24:07 +000084static int hardware_disable(int slot);
85#endif
86static int hardware_enable (int slot);
87static int voltage_set(int slot, int vcc, int vpp);
wdenkc6097192002-11-03 00:24:07 +000088
wdenk0893c472003-05-20 14:25:27 +000089#ifndef CONFIG_I82365
wdenkc6097192002-11-03 00:24:07 +000090static u_int m8xx_get_graycode(u_int size);
wdenk0893c472003-05-20 14:25:27 +000091#endif /* CONFIG_I82365 */
wdenkc6097192002-11-03 00:24:07 +000092#if 0
93static u_int m8xx_get_speed(u_int ns, u_int is_io);
94#endif
95
wdenk90e7e422002-12-04 23:39:58 +000096/* -------------------------------------------------------------------- */
wdenkc6097192002-11-03 00:24:07 +000097
98/* look up table for pgcrx registers */
99
100static u_int *pcmcia_pgcrx[2] = {
101 &((immap_t *)CFG_IMMR)->im_pcmcia.pcmc_pgcra,
102 &((immap_t *)CFG_IMMR)->im_pcmcia.pcmc_pgcrb,
103};
104
105#define PCMCIA_PGCRX(slot) (*pcmcia_pgcrx[slot])
106
wdenke5d61c72003-05-18 11:30:09 +0000107#endif /* CONFIG_I82365 */
108
109#ifdef CONFIG_IDE_8xx_PCCARD
110static void print_funcid (int func);
111static void print_fixed (volatile uchar *p);
112static int identify (volatile uchar *p);
113static int check_ide_device (int slot);
114#endif /* CONFIG_IDE_8xx_PCCARD */
115
wdenkc6097192002-11-03 00:24:07 +0000116const char *indent = "\t ";
117
wdenk90e7e422002-12-04 23:39:58 +0000118/* -------------------------------------------------------------------- */
wdenkc6097192002-11-03 00:24:07 +0000119
120#if (CONFIG_COMMANDS & CFG_CMD_PCMCIA)
121
122int do_pinit (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
123{
124 int rcode = 0;
125
126 if (argc != 2) {
127 printf ("Usage: pinit {on | off}\n");
128 return 1;
129 }
130 if (strcmp(argv[1],"on") == 0) {
131 rcode = pcmcia_on ();
132 } else if (strcmp(argv[1],"off") == 0) {
133 rcode = pcmcia_off ();
134 } else {
135 printf ("Usage: pinit {on | off}\n");
136 return 1;
137 }
138
139 return rcode;
140}
141#endif /* CFG_CMD_PCMCIA */
142
wdenk90e7e422002-12-04 23:39:58 +0000143/* -------------------------------------------------------------------- */
wdenkc6097192002-11-03 00:24:07 +0000144
wdenke5d61c72003-05-18 11:30:09 +0000145#ifdef CONFIG_I82365
146int pcmcia_on (void)
147{
148 u_int rc;
149
150 debug ("Enable PCMCIA " PCMCIA_SLOT_MSG "\n");
151
152 rc = i82365_init();
153
154 if (rc == 0)
155 {
156 rc = check_ide_device(0);
157 }
158
159 return (rc);
160}
161#else
162
dzub02ed682003-10-19 21:43:26 +0000163#if defined(CONFIG_LWMON) || defined(CONFIG_NSCU)
wdenkc6097192002-11-03 00:24:07 +0000164# define CFG_PCMCIA_TIMING (PCMCIA_SHT(9) | PCMCIA_SST(3) | PCMCIA_SL(12))
165#else
166# define CFG_PCMCIA_TIMING (PCMCIA_SHT(2) | PCMCIA_SST(4) | PCMCIA_SL(9))
167#endif
168
169int pcmcia_on (void)
170{
171 int i;
172 u_long reg, base;
173 pcmcia_win_t *win;
wdenk2029f4d2002-11-21 23:11:29 +0000174 u_int slotbit;
175 u_int rc, slot;
wdenkc6097192002-11-03 00:24:07 +0000176
177 debug ("Enable PCMCIA " PCMCIA_SLOT_MSG "\n");
178
179 /* intialize the fixed memory windows */
180 win = (pcmcia_win_t *)(&((immap_t *)CFG_IMMR)->im_pcmcia.pcmc_pbr0);
181 base = CFG_PCMCIA_MEM_ADDR;
182
183 if((reg = m8xx_get_graycode(CFG_PCMCIA_MEM_SIZE)) == -1) {
184 printf ("Cannot set window size to 0x%08x\n",
185 CFG_PCMCIA_MEM_SIZE);
186 return (1);
187 }
188
wdenk2029f4d2002-11-21 23:11:29 +0000189 slotbit = PCMCIA_SLOT_x;
wdenkc6097192002-11-03 00:24:07 +0000190 for (i=0; i<PCMCIA_MEM_WIN_NO; ++i) {
191 win->br = base;
192
wdenk2029f4d2002-11-21 23:11:29 +0000193#if (PCMCIA_SOCKETS_NO == 2)
194 if (i == 4) /* Another slot starting from win 4 */
195 slotbit = (slotbit ? PCMCIA_PSLOT_A : PCMCIA_PSLOT_B);
196#endif
wdenkc6097192002-11-03 00:24:07 +0000197 switch (i) {
198#ifdef CONFIG_IDE_8xx_PCCARD
wdenk2029f4d2002-11-21 23:11:29 +0000199 case 4:
wdenkc6097192002-11-03 00:24:07 +0000200 case 0: { /* map attribute memory */
201 win->or = ( PCMCIA_BSIZE_64M
202 | PCMCIA_PPS_8
203 | PCMCIA_PRS_ATTR
wdenk2029f4d2002-11-21 23:11:29 +0000204 | slotbit
wdenkc6097192002-11-03 00:24:07 +0000205 | PCMCIA_PV
206 | CFG_PCMCIA_TIMING );
207 break;
208 }
wdenk2029f4d2002-11-21 23:11:29 +0000209 case 5:
wdenkc6097192002-11-03 00:24:07 +0000210 case 1: { /* map I/O window for data reg */
211 win->or = ( PCMCIA_BSIZE_1K
212 | PCMCIA_PPS_16
213 | PCMCIA_PRS_IO
wdenk2029f4d2002-11-21 23:11:29 +0000214 | slotbit
wdenkc6097192002-11-03 00:24:07 +0000215 | PCMCIA_PV
216 | CFG_PCMCIA_TIMING );
217 break;
218 }
wdenk2029f4d2002-11-21 23:11:29 +0000219 case 6:
wdenk90e7e422002-12-04 23:39:58 +0000220 case 2: { /* map I/O window for cmd/ctrl reg block */
wdenkc6097192002-11-03 00:24:07 +0000221 win->or = ( PCMCIA_BSIZE_1K
222 | PCMCIA_PPS_8
223 | PCMCIA_PRS_IO
wdenk2029f4d2002-11-21 23:11:29 +0000224 | slotbit
wdenkc6097192002-11-03 00:24:07 +0000225 | PCMCIA_PV
226 | CFG_PCMCIA_TIMING );
227 break;
228 }
229#endif /* CONFIG_IDE_8xx_PCCARD */
230 default: /* set to not valid */
231 win->or = 0;
232 break;
233 }
234
235 debug ("MemWin %d: PBR 0x%08lX POR %08lX\n",
236 i, win->br, win->or);
237 base += CFG_PCMCIA_MEM_SIZE;
238 ++win;
239 }
240
wdenk90e7e422002-12-04 23:39:58 +0000241 for (i=0, rc=0, slot=_slot_; i<PCMCIA_SOCKETS_NO; i++, slot = !slot) {
wdenk2029f4d2002-11-21 23:11:29 +0000242 /* turn off voltage */
243 if ((rc = voltage_set(slot, 0, 0)))
244 continue;
wdenk90e7e422002-12-04 23:39:58 +0000245
wdenk2029f4d2002-11-21 23:11:29 +0000246 /* Enable external hardware */
247 if ((rc = hardware_enable(slot)))
248 continue;
wdenk90e7e422002-12-04 23:39:58 +0000249
wdenkc6097192002-11-03 00:24:07 +0000250#ifdef CONFIG_IDE_8xx_PCCARD
wdenk2029f4d2002-11-21 23:11:29 +0000251 if ((rc = check_ide_device(i)))
252 continue;
wdenkc6097192002-11-03 00:24:07 +0000253#endif
wdenk2029f4d2002-11-21 23:11:29 +0000254 }
255 return (rc);
wdenkc6097192002-11-03 00:24:07 +0000256}
wdenke5d61c72003-05-18 11:30:09 +0000257#endif /* CONFIG_I82365 */
wdenkc6097192002-11-03 00:24:07 +0000258
wdenk90e7e422002-12-04 23:39:58 +0000259/* -------------------------------------------------------------------- */
wdenkc6097192002-11-03 00:24:07 +0000260
261#if (CONFIG_COMMANDS & CFG_CMD_PCMCIA)
262
wdenke5d61c72003-05-18 11:30:09 +0000263#ifdef CONFIG_I82365
264static int pcmcia_off (void)
265{
266 printf ("Disable PCMCIA " PCMCIA_SLOT_MSG "\n");
267
268 i82365_exit();
269
270 return 0;
271}
272#else
wdenkc6097192002-11-03 00:24:07 +0000273static int pcmcia_off (void)
274{
275 int i;
276 pcmcia_win_t *win;
277
278 printf ("Disable PCMCIA " PCMCIA_SLOT_MSG "\n");
279
280 /* clear interrupt state, and disable interrupts */
281 ((immap_t *)CFG_IMMR)->im_pcmcia.pcmc_pscr = PCMCIA_MASK(_slot_);
282 ((immap_t *)CFG_IMMR)->im_pcmcia.pcmc_per &= ~PCMCIA_MASK(_slot_);
283
284 /* turn off interrupt and disable CxOE */
285 PCMCIA_PGCRX(_slot_) = __MY_PCMCIA_GCRX_CXOE;
286
287 /* turn off memory windows */
288 win = (pcmcia_win_t *)(&((immap_t *)CFG_IMMR)->im_pcmcia.pcmc_pbr0);
289
290 for (i=0; i<PCMCIA_MEM_WIN_NO; ++i) {
291 /* disable memory window */
292 win->or = 0;
293 ++win;
294 }
295
296 /* turn off voltage */
297 voltage_set(_slot_, 0, 0);
298
299 /* disable external hardware */
300 printf ("Shutdown and Poweroff " PCMCIA_SLOT_MSG "\n");
301 hardware_disable(_slot_);
302 return 0;
303}
wdenke5d61c72003-05-18 11:30:09 +0000304#endif /* CONFIG_I82365 */
wdenkc6097192002-11-03 00:24:07 +0000305
306#endif /* CFG_CMD_PCMCIA */
307
wdenk90e7e422002-12-04 23:39:58 +0000308/* -------------------------------------------------------------------- */
wdenkc6097192002-11-03 00:24:07 +0000309
310#ifdef CONFIG_IDE_8xx_PCCARD
311
312#define MAX_TUPEL_SZ 512
313#define MAX_FEATURES 4
314
wdenk4fc95692003-02-28 00:49:47 +0000315int ide_devices_found;
wdenk2029f4d2002-11-21 23:11:29 +0000316static int check_ide_device (int slot)
wdenkc6097192002-11-03 00:24:07 +0000317{
318 volatile uchar *ident = NULL;
319 volatile uchar *feature_p[MAX_FEATURES];
wdenk2029f4d2002-11-21 23:11:29 +0000320 volatile uchar *p, *start, *addr;
wdenkc6097192002-11-03 00:24:07 +0000321 int n_features = 0;
322 uchar func_id = ~0;
323 uchar code, len;
324 ushort config_base = 0;
325 int found = 0;
326 int i;
327
wdenk90e7e422002-12-04 23:39:58 +0000328 addr = (volatile uchar *)(CFG_PCMCIA_MEM_ADDR +
329 CFG_PCMCIA_MEM_SIZE * (slot * 4));
wdenke7f34c62003-01-11 09:48:40 +0000330 debug ("PCMCIA MEM: %08lX\n", (ulong)addr);
wdenkc6097192002-11-03 00:24:07 +0000331
wdenk2029f4d2002-11-21 23:11:29 +0000332 start = p = (volatile uchar *) addr;
wdenkc6097192002-11-03 00:24:07 +0000333
334 while ((p - start) < MAX_TUPEL_SZ) {
335
336 code = *p; p += 2;
337
338 if (code == 0xFF) { /* End of chain */
339 break;
340 }
341
342 len = *p; p += 2;
343#if defined(DEBUG) && (DEBUG > 1)
344 { volatile uchar *q = p;
345 printf ("\nTuple code %02x length %d\n\tData:",
346 code, len);
347
348 for (i = 0; i < len; ++i) {
349 printf (" %02x", *q);
350 q+= 2;
351 }
352 }
353#endif /* DEBUG */
354 switch (code) {
355 case CISTPL_VERS_1:
356 ident = p + 4;
357 break;
358 case CISTPL_FUNCID:
359 /* Fix for broken SanDisk which may have 0x80 bit set */
360 func_id = *p & 0x7F;
361 break;
362 case CISTPL_FUNCE:
363 if (n_features < MAX_FEATURES)
364 feature_p[n_features++] = p;
365 break;
366 case CISTPL_CONFIG:
367 config_base = (*(p+6) << 8) + (*(p+4));
368 debug ("\n## Config_base = %04x ###\n", config_base);
369 default:
370 break;
371 }
372 p += 2 * len;
373 }
374
375 found = identify (ident);
376
377 if (func_id != ((uchar)~0)) {
378 print_funcid (func_id);
379
380 if (func_id == CISTPL_FUNCID_FIXED)
381 found = 1;
382 else
383 return (1); /* no disk drive */
384 }
385
386 for (i=0; i<n_features; ++i) {
387 print_fixed (feature_p[i]);
388 }
389
390 if (!found) {
391 printf ("unknown card type\n");
392 return (1);
393 }
394
wdenk4fc95692003-02-28 00:49:47 +0000395 ide_devices_found |= (1 << slot);
396
wdenkc6097192002-11-03 00:24:07 +0000397 /* set I/O area in config reg -> only valid for ARGOSY D5!!! */
wdenk2029f4d2002-11-21 23:11:29 +0000398 *((uchar *)(addr + config_base)) = 1;
wdenkc6097192002-11-03 00:24:07 +0000399
400 return (0);
401}
402#endif /* CONFIG_IDE_8xx_PCCARD */
403
wdenk90e7e422002-12-04 23:39:58 +0000404/* -------------------------------------------------------------------- */
wdenkc6097192002-11-03 00:24:07 +0000405
406
wdenk90e7e422002-12-04 23:39:58 +0000407/* -------------------------------------------------------------------- */
408/* board specific stuff: */
409/* voltage_set(), hardware_enable() and hardware_disable() */
410/* -------------------------------------------------------------------- */
wdenkc6097192002-11-03 00:24:07 +0000411
wdenk90e7e422002-12-04 23:39:58 +0000412/* -------------------------------------------------------------------- */
413/* RPX Boards from Embedded Planet */
414/* -------------------------------------------------------------------- */
wdenkc6097192002-11-03 00:24:07 +0000415
416#if defined(CONFIG_RPXCLASSIC) || defined(CONFIG_RPXLITE)
417
418/* The RPX boards seems to have it's bus monitor timeout set to 6*8 clocks.
419 * SYPCR is write once only, therefore must the slowest memory be faster
420 * than the bus monitor or we will get a machine check due to the bus timeout.
421 */
422
423#define PCMCIA_BOARD_MSG "RPX CLASSIC or RPX LITE"
424
425#undef PCMCIA_BMT_LIMIT
426#define PCMCIA_BMT_LIMIT (6*8)
427
428static int voltage_set(int slot, int vcc, int vpp)
429{
430 u_long reg = 0;
431
432 switch(vcc) {
433 case 0: break;
434 case 33: reg |= BCSR1_PCVCTL4; break;
435 case 50: reg |= BCSR1_PCVCTL5; break;
436 default: return 1;
437 }
438
439 switch(vpp) {
440 case 0: break;
441 case 33:
442 case 50:
443 if(vcc == vpp)
444 reg |= BCSR1_PCVCTL6;
445 else
446 return 1;
447 break;
448 case 120:
449 reg |= BCSR1_PCVCTL7;
450 default: return 1;
451 }
452
453 if(vcc == 120)
454 return 1;
455
456 /* first, turn off all power */
457
458 *((uint *)RPX_CSR_ADDR) &= ~(BCSR1_PCVCTL4 | BCSR1_PCVCTL5
459 | BCSR1_PCVCTL6 | BCSR1_PCVCTL7);
460
461 /* enable new powersettings */
462
463 *((uint *)RPX_CSR_ADDR) |= reg;
464
465 return 0;
466}
467
468#define socket_get(_slot_) PCMCIA_SOCKET_KEY_5V
469static int hardware_enable (int slot)
470{
471 return 0; /* No hardware to enable */
472}
473#if (CONFIG_COMMANDS & CFG_CMD_PCMCIA)
474static int hardware_disable(int slot)
475{
476 return 0; /* No hardware to disable */
477}
478#endif /* CFG_CMD_PCMCIA */
479#endif /* CONFIG_RPXCLASSIC */
480
wdenk90e7e422002-12-04 23:39:58 +0000481/* -------------------------------------------------------------------- */
482/* (F)ADS Boards from Motorola */
483/* -------------------------------------------------------------------- */
wdenkc6097192002-11-03 00:24:07 +0000484
485#if defined(CONFIG_ADS) || defined(CONFIG_FADS)
486
487#ifdef CONFIG_ADS
488#define PCMCIA_BOARD_MSG "ADS"
489#define PCMCIA_GLITCHY_CD /* My ADS board needs this */
490#else
491#define PCMCIA_BOARD_MSG "FADS"
492#endif
493
494static int voltage_set(int slot, int vcc, int vpp)
495{
496 u_long reg = 0;
497
498 switch(vpp) {
499 case 0: reg = 0; break;
500 case 50: reg = 1; break;
501 case 120: reg = 2; break;
502 default: return 1;
503 }
504
505 switch(vcc) {
506 case 0: reg = 0; break;
507#ifdef CONFIG_ADS
508 case 50: reg = BCSR1_PCCVCCON; break;
509#endif
510#ifdef CONFIG_FADS
511 case 33: reg = BCSR1_PCCVCC0 | BCSR1_PCCVCC1; break;
512 case 50: reg = BCSR1_PCCVCC1; break;
513#endif
514 default: return 1;
515 }
516
517 /* first, turn off all power */
518
519#ifdef CONFIG_ADS
520 *((uint *)BCSR1) |= BCSR1_PCCVCCON;
521#endif
522#ifdef CONFIG_FADS
523 *((uint *)BCSR1) &= ~(BCSR1_PCCVCC0 | BCSR1_PCCVCC1);
524#endif
525 *((uint *)BCSR1) &= ~BCSR1_PCCVPP_MASK;
526
527 /* enable new powersettings */
528
529#ifdef CONFIG_ADS
530 *((uint *)BCSR1) &= ~reg;
531#endif
532#ifdef CONFIG_FADS
533 *((uint *)BCSR1) |= reg;
534#endif
535
536 *((uint *)BCSR1) |= reg << 20;
537
538 return 0;
539}
540
541#define socket_get(_slot_) PCMCIA_SOCKET_KEY_5V
542
543static int hardware_enable(int slot)
544{
545 *((uint *)BCSR1) &= ~BCSR1_PCCEN;
546 return 0;
547}
548
549#if (CONFIG_COMMANDS & CFG_CMD_PCMCIA)
550static int hardware_disable(int slot)
551{
552 *((uint *)BCSR1) &= ~BCSR1_PCCEN;
553 return 0;
554}
555#endif /* CFG_CMD_PCMCIA */
556
557#endif /* (F)ADS */
558
wdenk90e7e422002-12-04 23:39:58 +0000559/* -------------------------------------------------------------------- */
560/* TQM8xxL Boards by TQ Components */
wdenkc8434db2003-03-26 06:55:25 +0000561/* SC8xx Boards by SinoVee Microsystems */
wdenk90e7e422002-12-04 23:39:58 +0000562/* -------------------------------------------------------------------- */
wdenkc6097192002-11-03 00:24:07 +0000563
wdenkc8434db2003-03-26 06:55:25 +0000564#if defined(CONFIG_TQM8xxL) || defined(CONFIG_SVM_SC8xx)
wdenkc6097192002-11-03 00:24:07 +0000565
wdenkc8434db2003-03-26 06:55:25 +0000566#if defined(CONFIG_TQM8xxL)
wdenkc6097192002-11-03 00:24:07 +0000567#define PCMCIA_BOARD_MSG "TQM8xxL"
wdenkc8434db2003-03-26 06:55:25 +0000568#endif
569#if defined(CONFIG_SVM_SC8xx)
570#define PCMCIA_BOARD_MSG "SC8xx"
571#endif
wdenkc6097192002-11-03 00:24:07 +0000572
573static int hardware_enable(int slot)
574{
575 volatile immap_t *immap;
576 volatile cpm8xx_t *cp;
577 volatile pcmconf8xx_t *pcmp;
578 volatile sysconf8xx_t *sysp;
579 uint reg, mask;
580
581 debug ("hardware_enable: " PCMCIA_BOARD_MSG " Slot %c\n", 'A'+slot);
582
583 udelay(10000);
584
585 immap = (immap_t *)CFG_IMMR;
586 sysp = (sysconf8xx_t *)(&(((immap_t *)CFG_IMMR)->im_siu_conf));
587 pcmp = (pcmconf8xx_t *)(&(((immap_t *)CFG_IMMR)->im_pcmcia));
588 cp = (cpm8xx_t *)(&(((immap_t *)CFG_IMMR)->im_cpm));
589
590 /*
591 * Configure SIUMCR to enable PCMCIA port B
592 * (VFLS[0:1] are not used for debugging, we connect FRZ# instead)
593 */
594 sysp->sc_siumcr &= ~SIUMCR_DBGC11; /* set DBGC to 00 */
595
596 /* clear interrupt state, and disable interrupts */
dzub02ed682003-10-19 21:43:26 +0000597 pcmp->pcmc_pscr = PCMCIA_MASK(slot);
598 pcmp->pcmc_per &= ~PCMCIA_MASK(slot);
wdenkc6097192002-11-03 00:24:07 +0000599
wdenkc6097192002-11-03 00:24:07 +0000600 /*
wdenk90e7e422002-12-04 23:39:58 +0000601 * Disable interrupts, DMA, and PCMCIA buffers
602 * (isolate the interface) and assert RESET signal
wdenkc6097192002-11-03 00:24:07 +0000603 */
604 debug ("Disable PCMCIA buffers and assert RESET\n");
wdenk90e7e422002-12-04 23:39:58 +0000605 reg = 0;
606 reg |= __MY_PCMCIA_GCRX_CXRESET; /* active high */
dzub02ed682003-10-19 21:43:26 +0000607#ifndef NSCU_OE_INV
wdenk90e7e422002-12-04 23:39:58 +0000608 reg |= __MY_PCMCIA_GCRX_CXOE; /* active low */
dzub02ed682003-10-19 21:43:26 +0000609#endif
610 PCMCIA_PGCRX(slot) = reg;
wdenkc6097192002-11-03 00:24:07 +0000611 udelay(500);
612
dzub02ed682003-10-19 21:43:26 +0000613#ifndef CONFIG_NSCU
wdenkc6097192002-11-03 00:24:07 +0000614 /*
615 * Configure Port C pins for
616 * 5 Volts Enable and 3 Volts enable
617 */
618 immap->im_ioport.iop_pcpar &= ~(0x0002 | 0x0004);
619 immap->im_ioport.iop_pcso &= ~(0x0002 | 0x0004);
620 /* remove all power */
621
622 immap->im_ioport.iop_pcdat &= ~(0x0002 | 0x0004);
dzub02ed682003-10-19 21:43:26 +0000623#endif
wdenkc6097192002-11-03 00:24:07 +0000624
625 /*
626 * Make sure there is a card in the slot, then configure the interface.
627 */
628 udelay(10000);
629 debug ("[%d] %s: PIPR(%p)=0x%x\n",
630 __LINE__,__FUNCTION__,
631 &(pcmp->pcmc_pipr),pcmp->pcmc_pipr);
wdenk2029f4d2002-11-21 23:11:29 +0000632 if (pcmp->pcmc_pipr & (0x18000000 >> (slot << 4))) {
wdenkc6097192002-11-03 00:24:07 +0000633 printf (" No Card found\n");
634 return (1);
635 }
636
637 /*
638 * Power On.
639 */
640 mask = PCMCIA_VS1(slot) | PCMCIA_VS2(slot);
641 reg = pcmp->pcmc_pipr;
642 debug ("PIPR: 0x%x ==> VS1=o%s, VS2=o%s\n",
643 reg,
644 (reg&PCMCIA_VS1(slot))?"n":"ff",
645 (reg&PCMCIA_VS2(slot))?"n":"ff");
dzub02ed682003-10-19 21:43:26 +0000646#ifndef CONFIG_NSCU
wdenkc6097192002-11-03 00:24:07 +0000647 if ((reg & mask) == mask) {
648 immap->im_ioport.iop_pcdat |= 0x0004;
649 puts (" 5.0V card found: ");
650 } else {
651 immap->im_ioport.iop_pcdat |= 0x0002;
652 puts (" 3.3V card found: ");
653 }
wdenk90e7e422002-12-04 23:39:58 +0000654 immap->im_ioport.iop_pcdir |= (0x0002 | 0x0004);
dzub02ed682003-10-19 21:43:26 +0000655#else
656 if ((reg & mask) == mask) {
657 puts (" 5.0V card found: ");
658 } else {
659 puts (" 3.3V card found: ");
660 }
661#endif
wdenkc6097192002-11-03 00:24:07 +0000662#if 0
663 /* VCC switch error flag, PCMCIA slot INPACK_ pin */
664 cp->cp_pbdir &= ~(0x0020 | 0x0010);
665 cp->cp_pbpar &= ~(0x0020 | 0x0010);
666 udelay(500000);
667#endif
668 udelay(1000);
669 debug ("Enable PCMCIA buffers and stop RESET\n");
dzub02ed682003-10-19 21:43:26 +0000670 reg = PCMCIA_PGCRX(slot);
wdenkc6097192002-11-03 00:24:07 +0000671 reg &= ~__MY_PCMCIA_GCRX_CXRESET; /* active high */
dzub02ed682003-10-19 21:43:26 +0000672#ifndef NSCU_OE_INV
wdenkc6097192002-11-03 00:24:07 +0000673 reg &= ~__MY_PCMCIA_GCRX_CXOE; /* active low */
dzub02ed682003-10-19 21:43:26 +0000674#else
675 reg |= __MY_PCMCIA_GCRX_CXOE; /* active low */
676#endif
677 PCMCIA_PGCRX(slot) = reg;
wdenkc6097192002-11-03 00:24:07 +0000678
679 udelay(250000); /* some cards need >150 ms to come up :-( */
680
681 debug ("# hardware_enable done\n");
682
683 return (0);
684}
685
686
wdenkc6097192002-11-03 00:24:07 +0000687#if (CONFIG_COMMANDS & CFG_CMD_PCMCIA)
688static int hardware_disable(int slot)
689{
690 volatile immap_t *immap;
691 volatile pcmconf8xx_t *pcmp;
692 u_long reg;
693
694 debug ("hardware_disable: " PCMCIA_BOARD_MSG " Slot %c\n", 'A'+slot);
695
696 immap = (immap_t *)CFG_IMMR;
697 pcmp = (pcmconf8xx_t *)(&(((immap_t *)CFG_IMMR)->im_pcmcia));
698
dzub02ed682003-10-19 21:43:26 +0000699#ifndef CONFIG_NSCU
wdenkc6097192002-11-03 00:24:07 +0000700 /* remove all power */
701 immap->im_ioport.iop_pcdat &= ~(0x0002 | 0x0004);
dzub02ed682003-10-19 21:43:26 +0000702#endif
wdenkc6097192002-11-03 00:24:07 +0000703
wdenkc6097192002-11-03 00:24:07 +0000704 debug ("Disable PCMCIA buffers and assert RESET\n");
wdenk90e7e422002-12-04 23:39:58 +0000705 reg = 0;
wdenkc6097192002-11-03 00:24:07 +0000706 reg |= __MY_PCMCIA_GCRX_CXRESET; /* active high */
dzub02ed682003-10-19 21:43:26 +0000707#ifndef NSCU_OE_INV
wdenkc6097192002-11-03 00:24:07 +0000708 reg |= __MY_PCMCIA_GCRX_CXOE; /* active low */
dzub02ed682003-10-19 21:43:26 +0000709#endif
710 PCMCIA_PGCRX(slot) = reg;
wdenkc6097192002-11-03 00:24:07 +0000711
712 udelay(10000);
713
714 return (0);
715}
716#endif /* CFG_CMD_PCMCIA */
717
dzub02ed682003-10-19 21:43:26 +0000718#ifdef CONFIG_NSCU
wdenkc6097192002-11-03 00:24:07 +0000719static int voltage_set(int slot, int vcc, int vpp)
720{
dzub02ed682003-10-19 21:43:26 +0000721 return 0;
722}
723#else
724static int voltage_set(int slot, int vcc, int vpp)
725{
wdenkc6097192002-11-03 00:24:07 +0000726 volatile immap_t *immap;
727 volatile pcmconf8xx_t *pcmp;
728 u_long reg;
729
730 debug ("voltage_set: "
731 PCMCIA_BOARD_MSG
732 " Slot %c, Vcc=%d.%d, Vpp=%d.%d\n",
733 'A'+slot, vcc/10, vcc%10, vpp/10, vcc%10);
734
735 immap = (immap_t *)CFG_IMMR;
736 pcmp = (pcmconf8xx_t *)(&(((immap_t *)CFG_IMMR)->im_pcmcia));
737 /*
738 * Disable PCMCIA buffers (isolate the interface)
739 * and assert RESET signal
740 */
741 debug ("Disable PCMCIA buffers and assert RESET\n");
dzub02ed682003-10-19 21:43:26 +0000742 reg = PCMCIA_PGCRX(slot);
wdenk90e7e422002-12-04 23:39:58 +0000743 reg |= __MY_PCMCIA_GCRX_CXRESET; /* active high */
dzub02ed682003-10-19 21:43:26 +0000744#ifndef NSCU_OE_INV
wdenk90e7e422002-12-04 23:39:58 +0000745 reg |= __MY_PCMCIA_GCRX_CXOE; /* active low */
dzub02ed682003-10-19 21:43:26 +0000746#else
747 reg &= ~__MY_PCMCIA_GCRX_CXOE; /* active low */
748#endif
749 PCMCIA_PGCRX(slot) = reg;
wdenkc6097192002-11-03 00:24:07 +0000750 udelay(500);
751
752 /*
753 * Configure Port C pins for
754 * 5 Volts Enable and 3 Volts enable,
755 * Turn off all power
756 */
757 debug ("PCMCIA power OFF\n");
758 immap->im_ioport.iop_pcpar &= ~(0x0002 | 0x0004);
759 immap->im_ioport.iop_pcso &= ~(0x0002 | 0x0004);
760 immap->im_ioport.iop_pcdat &= ~(0x0002 | 0x0004);
761
762 reg = 0;
763 switch(vcc) {
764 case 0: break;
765 case 33: reg |= 0x0002; break;
766 case 50: reg |= 0x0004; break;
767 default: goto done;
768 }
769
770 /* Checking supported voltages */
771
772 debug ("PIPR: 0x%x --> %s\n",
773 pcmp->pcmc_pipr,
774 (pcmp->pcmc_pipr & 0x00008000) ? "only 5 V" : "can do 3.3V");
775
776 immap->im_ioport.iop_pcdat |= reg;
wdenk90e7e422002-12-04 23:39:58 +0000777 immap->im_ioport.iop_pcdir |= (0x0002 | 0x0004);
wdenkc6097192002-11-03 00:24:07 +0000778 if (reg) {
779 debug ("PCMCIA powered at %sV\n",
780 (reg&0x0004) ? "5.0" : "3.3");
781 } else {
782 debug ("PCMCIA powered down\n");
783 }
784
785done:
786 debug ("Enable PCMCIA buffers and stop RESET\n");
dzub02ed682003-10-19 21:43:26 +0000787 reg = PCMCIA_PGCRX(slot);
wdenkc6097192002-11-03 00:24:07 +0000788 reg &= ~__MY_PCMCIA_GCRX_CXRESET; /* active high */
dzub02ed682003-10-19 21:43:26 +0000789#ifndef NSCU_OE_INV
wdenkc6097192002-11-03 00:24:07 +0000790 reg &= ~__MY_PCMCIA_GCRX_CXOE; /* active low */
dzub02ed682003-10-19 21:43:26 +0000791#else
792 reg |= __MY_PCMCIA_GCRX_CXOE; /* active low */
793#endif
794 PCMCIA_PGCRX(slot) = reg;
wdenkc6097192002-11-03 00:24:07 +0000795 udelay(500);
796
797 debug ("voltage_set: " PCMCIA_BOARD_MSG " Slot %c, DONE\n",
798 slot+'A');
799 return (0);
800}
dzub02ed682003-10-19 21:43:26 +0000801#endif
wdenkc6097192002-11-03 00:24:07 +0000802
803#endif /* TQM8xxL */
804
805
wdenk90e7e422002-12-04 23:39:58 +0000806/* -------------------------------------------------------------------- */
807/* LWMON Board */
808/* -------------------------------------------------------------------- */
wdenkc6097192002-11-03 00:24:07 +0000809
810#if defined(CONFIG_LWMON)
811
812#define PCMCIA_BOARD_MSG "LWMON"
813
814/* #define's for MAX1604 Power Switch */
815#define MAX1604_OP_SUS 0x80
816#define MAX1604_VCCBON 0x40
817#define MAX1604_VCC_35 0x20
818#define MAX1604_VCCBHIZ 0x10
819#define MAX1604_VPPBON 0x08
820#define MAX1604_VPPBPBPGM 0x04
821#define MAX1604_VPPBHIZ 0x02
822/* reserved 0x01 */
823
824static int hardware_enable(int slot)
825{
826 volatile immap_t *immap;
827 volatile cpm8xx_t *cp;
828 volatile pcmconf8xx_t *pcmp;
829 volatile sysconf8xx_t *sysp;
830 uint reg, mask;
831 uchar val;
832
833
834 debug ("hardware_enable: " PCMCIA_BOARD_MSG " Slot %c\n", 'A'+slot);
835
836 /* Switch on PCMCIA port in PIC register 0x60 */
837 reg = pic_read (0x60);
838 debug ("[%d] PIC read: reg_60 = 0x%02x\n", __LINE__, reg);
839 reg &= ~0x10;
wdenk90e7e422002-12-04 23:39:58 +0000840 /* reg |= 0x08; Vpp not needed */
wdenkc6097192002-11-03 00:24:07 +0000841 pic_write (0x60, reg);
842#ifdef DEBUG
843 reg = pic_read (0x60);
844 printf ("[%d] PIC read: reg_60 = 0x%02x\n", __LINE__, reg);
845#endif
846 udelay(10000);
847
848 immap = (immap_t *)CFG_IMMR;
849 sysp = (sysconf8xx_t *)(&(((immap_t *)CFG_IMMR)->im_siu_conf));
850 pcmp = (pcmconf8xx_t *)(&(((immap_t *)CFG_IMMR)->im_pcmcia));
851 cp = (cpm8xx_t *)(&(((immap_t *)CFG_IMMR)->im_cpm));
852
853 /*
854 * Configure SIUMCR to enable PCMCIA port B
855 * (VFLS[0:1] are not used for debugging, we connect FRZ# instead)
856 */
857 sysp->sc_siumcr &= ~SIUMCR_DBGC11; /* set DBGC to 00 */
858
859 /* clear interrupt state, and disable interrupts */
860 pcmp->pcmc_pscr = PCMCIA_MASK(_slot_);
861 pcmp->pcmc_per &= ~PCMCIA_MASK(_slot_);
862
wdenkc6097192002-11-03 00:24:07 +0000863 /*
wdenk90e7e422002-12-04 23:39:58 +0000864 * Disable interrupts, DMA, and PCMCIA buffers
865 * (isolate the interface) and assert RESET signal
wdenkc6097192002-11-03 00:24:07 +0000866 */
867 debug ("Disable PCMCIA buffers and assert RESET\n");
wdenk90e7e422002-12-04 23:39:58 +0000868 reg = 0;
869 reg |= __MY_PCMCIA_GCRX_CXRESET; /* active high */
870 reg |= __MY_PCMCIA_GCRX_CXOE; /* active low */
wdenkc6097192002-11-03 00:24:07 +0000871 PCMCIA_PGCRX(_slot_) = reg;
872 udelay(500);
873
874 /*
875 * Make sure there is a card in the slot, then configure the interface.
876 */
877 udelay(10000);
878 debug ("[%d] %s: PIPR(%p)=0x%x\n",
879 __LINE__,__FUNCTION__,
880 &(pcmp->pcmc_pipr),pcmp->pcmc_pipr);
wdenk2029f4d2002-11-21 23:11:29 +0000881 if (pcmp->pcmc_pipr & (0x18000000 >> (slot << 4))) {
wdenkc6097192002-11-03 00:24:07 +0000882 printf (" No Card found\n");
883 return (1);
884 }
885
886 /*
887 * Power On.
888 */
889 mask = PCMCIA_VS1(slot) | PCMCIA_VS2(slot);
890 reg = pcmp->pcmc_pipr;
891 debug ("PIPR: 0x%x ==> VS1=o%s, VS2=o%s\n",
892 reg,
893 (reg&PCMCIA_VS1(slot))?"n":"ff",
894 (reg&PCMCIA_VS2(slot))?"n":"ff");
895 if ((reg & mask) == mask) {
896 val = 0; /* VCCB3/5 = 0 ==> use Vx = 5.0 V */
897 puts (" 5.0V card found: ");
898 } else {
899 val = MAX1604_VCC_35; /* VCCB3/5 = 1 ==> use Vy = 3.3 V */
900 puts (" 3.3V card found: ");
901 }
902
903 /* switch VCC on */
wdenk90e7e422002-12-04 23:39:58 +0000904 val |= MAX1604_OP_SUS | MAX1604_VCCBON;
wdenkc6097192002-11-03 00:24:07 +0000905 i2c_init (CFG_I2C_SPEED, CFG_I2C_SLAVE);
906 i2c_write (CFG_I2C_POWER_A_ADDR, 0, 0, &val, 1);
907
908 udelay(500000);
909
910 debug ("Enable PCMCIA buffers and stop RESET\n");
911 reg = PCMCIA_PGCRX(_slot_);
912 reg &= ~__MY_PCMCIA_GCRX_CXRESET; /* active high */
913 reg &= ~__MY_PCMCIA_GCRX_CXOE; /* active low */
914 PCMCIA_PGCRX(_slot_) = reg;
915
916 udelay(250000); /* some cards need >150 ms to come up :-( */
917
918 debug ("# hardware_enable done\n");
919
920 return (0);
921}
922
923
wdenkc6097192002-11-03 00:24:07 +0000924#if (CONFIG_COMMANDS & CFG_CMD_PCMCIA)
925static int hardware_disable(int slot)
926{
927 volatile immap_t *immap;
928 volatile pcmconf8xx_t *pcmp;
929 u_long reg;
930 uchar val;
931
932 debug ("hardware_disable: " PCMCIA_BOARD_MSG " Slot %c\n", 'A'+slot);
933
934 immap = (immap_t *)CFG_IMMR;
935 pcmp = (pcmconf8xx_t *)(&(((immap_t *)CFG_IMMR)->im_pcmcia));
936
937 /* remove all power, put output in high impedance state */
938 val = MAX1604_VCCBHIZ | MAX1604_VPPBHIZ;
939 i2c_init (CFG_I2C_SPEED, CFG_I2C_SLAVE);
940 i2c_write (CFG_I2C_POWER_A_ADDR, 0, 0, &val, 1);
941
942 /* Configure PCMCIA General Control Register */
wdenkc6097192002-11-03 00:24:07 +0000943 debug ("Disable PCMCIA buffers and assert RESET\n");
wdenk90e7e422002-12-04 23:39:58 +0000944 reg = 0;
wdenkc6097192002-11-03 00:24:07 +0000945 reg |= __MY_PCMCIA_GCRX_CXRESET; /* active high */
946 reg |= __MY_PCMCIA_GCRX_CXOE; /* active low */
947 PCMCIA_PGCRX(_slot_) = reg;
948
949 /* Switch off PCMCIA port in PIC register 0x60 */
950 reg = pic_read (0x60);
951 debug ("[%d] PIC read: reg_60 = 0x%02x\n", __LINE__, reg);
952 reg |= 0x10;
953 reg &= ~0x08;
954 pic_write (0x60, reg);
955#ifdef DEBUG
956 reg = pic_read (0x60);
957 printf ("[%d] PIC read: reg_60 = 0x%02x\n", __LINE__, reg);
958#endif
959 udelay(10000);
960
961 return (0);
962}
963#endif /* CFG_CMD_PCMCIA */
964
965
wdenkc6097192002-11-03 00:24:07 +0000966static int voltage_set(int slot, int vcc, int vpp)
967{
968 volatile immap_t *immap;
969 volatile pcmconf8xx_t *pcmp;
970 u_long reg;
971 uchar val;
972
973 debug ("voltage_set: "
974 PCMCIA_BOARD_MSG
975 " Slot %c, Vcc=%d.%d, Vpp=%d.%d\n",
976 'A'+slot, vcc/10, vcc%10, vpp/10, vcc%10);
977
978 immap = (immap_t *)CFG_IMMR;
979 pcmp = (pcmconf8xx_t *)(&(((immap_t *)CFG_IMMR)->im_pcmcia));
980 /*
981 * Disable PCMCIA buffers (isolate the interface)
982 * and assert RESET signal
983 */
984 debug ("Disable PCMCIA buffers and assert RESET\n");
wdenk90e7e422002-12-04 23:39:58 +0000985 reg = PCMCIA_PGCRX(_slot_);
986 reg |= __MY_PCMCIA_GCRX_CXRESET; /* active high */
987 reg |= __MY_PCMCIA_GCRX_CXOE; /* active low */
wdenkc6097192002-11-03 00:24:07 +0000988 PCMCIA_PGCRX(_slot_) = reg;
989 udelay(500);
990
991 /*
992 * Turn off all power (switch to high impedance)
993 */
994 debug ("PCMCIA power OFF\n");
995 val = MAX1604_VCCBHIZ | MAX1604_VPPBHIZ;
996 i2c_init (CFG_I2C_SPEED, CFG_I2C_SLAVE);
997 i2c_write (CFG_I2C_POWER_A_ADDR, 0, 0, &val, 1);
998
999 val = 0;
1000 switch(vcc) {
1001 case 0: break;
1002 case 33: val = MAX1604_VCC_35; break;
1003 case 50: break;
1004 default: goto done;
1005 }
1006
1007 /* Checking supported voltages */
1008
1009 debug ("PIPR: 0x%x --> %s\n",
1010 pcmp->pcmc_pipr,
1011 (pcmp->pcmc_pipr & 0x00008000) ? "only 5 V" : "can do 3.3V");
1012
1013 i2c_write (CFG_I2C_POWER_A_ADDR, 0, 0, &val, 1);
1014 if (val) {
1015 debug ("PCMCIA powered at %sV\n",
1016 (val & MAX1604_VCC_35) ? "3.3" : "5.0");
1017 } else {
1018 debug ("PCMCIA powered down\n");
1019 }
1020
1021done:
1022 debug ("Enable PCMCIA buffers and stop RESET\n");
1023 reg = PCMCIA_PGCRX(_slot_);
1024 reg &= ~__MY_PCMCIA_GCRX_CXRESET; /* active high */
1025 reg &= ~__MY_PCMCIA_GCRX_CXOE; /* active low */
1026 PCMCIA_PGCRX(_slot_) = reg;
1027 udelay(500);
1028
1029 debug ("voltage_set: " PCMCIA_BOARD_MSG " Slot %c, DONE\n",
1030 slot+'A');
1031 return (0);
1032}
1033
1034#endif /* LWMON */
1035
wdenk90e7e422002-12-04 23:39:58 +00001036/* -------------------------------------------------------------------- */
1037/* GTH board by Corelatus AB */
1038/* -------------------------------------------------------------------- */
wdenkc6097192002-11-03 00:24:07 +00001039#if defined(CONFIG_GTH)
1040
1041#define PCMCIA_BOARD_MSG "GTH COMPACT FLASH"
1042
wdenk90e7e422002-12-04 23:39:58 +00001043static int voltage_set (int slot, int vcc, int vpp)
1044{ /* Do nothing */
1045 return 0;
wdenkc6097192002-11-03 00:24:07 +00001046}
1047
1048static int hardware_enable (int slot)
1049{
wdenk90e7e422002-12-04 23:39:58 +00001050 volatile immap_t *immap;
1051 volatile cpm8xx_t *cp;
1052 volatile pcmconf8xx_t *pcmp;
1053 volatile sysconf8xx_t *sysp;
1054 uint reg, mask;
wdenkc6097192002-11-03 00:24:07 +00001055
wdenk90e7e422002-12-04 23:39:58 +00001056 debug ("hardware_enable: GTH Slot %c\n", 'A' + slot);
wdenkc6097192002-11-03 00:24:07 +00001057
wdenk90e7e422002-12-04 23:39:58 +00001058 immap = (immap_t *) CFG_IMMR;
1059 sysp = (sysconf8xx_t *) (&(((immap_t *) CFG_IMMR)->im_siu_conf));
1060 pcmp = (pcmconf8xx_t *) (&(((immap_t *) CFG_IMMR)->im_pcmcia));
1061 cp = (cpm8xx_t *) (&(((immap_t *) CFG_IMMR)->im_cpm));
wdenkc6097192002-11-03 00:24:07 +00001062
wdenk90e7e422002-12-04 23:39:58 +00001063 /* clear interrupt state, and disable interrupts */
1064 pcmp->pcmc_pscr = PCMCIA_MASK (_slot_);
1065 pcmp->pcmc_per &= ~PCMCIA_MASK (_slot_);
wdenkc6097192002-11-03 00:24:07 +00001066
wdenk90e7e422002-12-04 23:39:58 +00001067 /*
1068 * Disable interrupts, DMA, and PCMCIA buffers
1069 * (isolate the interface) and assert RESET signal
1070 */
1071 debug ("Disable PCMCIA buffers and assert RESET\n");
1072 reg = 0;
1073 reg |= __MY_PCMCIA_GCRX_CXRESET; /* active high */
1074 reg |= __MY_PCMCIA_GCRX_CXOE; /* active low */
1075 PCMCIA_PGCRX (_slot_) = reg;
1076 udelay (500);
wdenkc6097192002-11-03 00:24:07 +00001077
wdenk90e7e422002-12-04 23:39:58 +00001078 /*
1079 * Make sure there is a card in the slot,
1080 * then configure the interface.
1081 */
1082 udelay (10000);
1083 debug ("[%d] %s: PIPR(%p)=0x%x\n",
1084 __LINE__, __FUNCTION__,
1085 &(pcmp->pcmc_pipr), pcmp->pcmc_pipr);
1086 if (pcmp->pcmc_pipr & 0x98000000) {
1087 printf (" No Card found\n");
1088 return (1);
1089 }
wdenkc6097192002-11-03 00:24:07 +00001090
wdenk90e7e422002-12-04 23:39:58 +00001091 mask = PCMCIA_VS1 (slot) | PCMCIA_VS2 (slot);
1092 reg = pcmp->pcmc_pipr;
1093 debug ("PIPR: 0x%x ==> VS1=o%s, VS2=o%s\n",
1094 reg,
1095 (reg & PCMCIA_VS1 (slot)) ? "n" : "ff",
1096 (reg & PCMCIA_VS2 (slot)) ? "n" : "ff");
wdenkc6097192002-11-03 00:24:07 +00001097
wdenk90e7e422002-12-04 23:39:58 +00001098 debug ("Enable PCMCIA buffers and stop RESET\n");
1099 reg = PCMCIA_PGCRX (_slot_);
1100 reg &= ~__MY_PCMCIA_GCRX_CXRESET; /* active high */
1101 reg &= ~__MY_PCMCIA_GCRX_CXOE; /* active low */
1102 PCMCIA_PGCRX (_slot_) = reg;
wdenkc6097192002-11-03 00:24:07 +00001103
wdenk90e7e422002-12-04 23:39:58 +00001104 udelay (250000); /* some cards need >150 ms to come up :-( */
wdenkc6097192002-11-03 00:24:07 +00001105
wdenk90e7e422002-12-04 23:39:58 +00001106 debug ("# hardware_enable done\n");
wdenkc6097192002-11-03 00:24:07 +00001107
wdenk90e7e422002-12-04 23:39:58 +00001108 return 0;
wdenkc6097192002-11-03 00:24:07 +00001109}
1110#if (CONFIG_COMMANDS & CFG_CMD_PCMCIA)
1111static int hardware_disable(int slot)
1112{
1113 return 0; /* No hardware to disable */
1114}
1115#endif /* CFG_CMD_PCMCIA */
1116#endif /* CONFIG_GTH */
1117
wdenk90e7e422002-12-04 23:39:58 +00001118/* -------------------------------------------------------------------- */
1119/* ICU862 Boards by Cambridge Broadband Ltd. */
1120/* -------------------------------------------------------------------- */
wdenkc6097192002-11-03 00:24:07 +00001121
1122#if defined(CONFIG_ICU862)
1123
1124#define PCMCIA_BOARD_MSG "ICU862"
1125
1126static void cfg_port_B (void);
1127
1128static int hardware_enable(int slot)
1129{
1130 volatile immap_t *immap;
1131 volatile cpm8xx_t *cp;
1132 volatile pcmconf8xx_t *pcmp;
1133 volatile sysconf8xx_t *sysp;
1134 uint reg, pipr, mask;
1135 int i;
1136
1137 debug ("hardware_enable: " PCMCIA_BOARD_MSG " Slot %c\n", 'A'+slot);
1138
1139 udelay(10000);
1140
1141 immap = (immap_t *)CFG_IMMR;
1142 sysp = (sysconf8xx_t *)(&(((immap_t *)CFG_IMMR)->im_siu_conf));
1143 pcmp = (pcmconf8xx_t *)(&(((immap_t *)CFG_IMMR)->im_pcmcia));
1144 cp = (cpm8xx_t *)(&(((immap_t *)CFG_IMMR)->im_cpm));
1145
1146 /* Configure Port B for TPS2205 PC-Card Power-Interface Switch */
1147 cfg_port_B ();
1148
1149 /*
1150 * Configure SIUMCR to enable PCMCIA port B
1151 * (VFLS[0:1] are not used for debugging, we connect FRZ# instead)
1152 */
1153 sysp->sc_siumcr &= ~SIUMCR_DBGC11; /* set DBGC to 00 */
1154
1155 /* clear interrupt state, and disable interrupts */
1156 pcmp->pcmc_pscr = PCMCIA_MASK(_slot_);
1157 pcmp->pcmc_per &= ~PCMCIA_MASK(_slot_);
1158
wdenkc6097192002-11-03 00:24:07 +00001159 /*
wdenk90e7e422002-12-04 23:39:58 +00001160 * Disable interrupts, DMA, and PCMCIA buffers
1161 * (isolate the interface) and assert RESET signal
wdenkc6097192002-11-03 00:24:07 +00001162 */
1163 debug ("Disable PCMCIA buffers and assert RESET\n");
wdenk90e7e422002-12-04 23:39:58 +00001164 reg = 0;
1165 reg |= __MY_PCMCIA_GCRX_CXRESET; /* active high */
1166 reg |= __MY_PCMCIA_GCRX_CXOE; /* active low */
wdenkc6097192002-11-03 00:24:07 +00001167 PCMCIA_PGCRX(_slot_) = reg;
1168 udelay(500);
1169
1170 /*
1171 * Make sure there is a card in the slot, then configure the interface.
1172 */
1173 udelay(10000);
1174 debug ("[%d] %s: PIPR(%p)=0x%x\n",
1175 __LINE__,__FUNCTION__,
1176 &(pcmp->pcmc_pipr),pcmp->pcmc_pipr);
wdenk2029f4d2002-11-21 23:11:29 +00001177 if (pcmp->pcmc_pipr & (0x18000000 >> (slot << 4))) {
wdenkc6097192002-11-03 00:24:07 +00001178 printf (" No Card found\n");
1179 return (1);
1180 }
1181
1182 /*
1183 * Power On: Set VAVCC to 3.3V or 5V, set VAVPP to Hi-Z
1184 */
1185 mask = PCMCIA_VS1(slot) | PCMCIA_VS2(slot);
1186 pipr = pcmp->pcmc_pipr;
1187 debug ("PIPR: 0x%x ==> VS1=o%s, VS2=o%s\n",
1188 pipr,
1189 (reg&PCMCIA_VS1(slot))?"n":"ff",
1190 (reg&PCMCIA_VS2(slot))?"n":"ff");
1191
1192 reg = cp->cp_pbdat;
1193 if ((pipr & mask) == mask) {
wdenk90e7e422002-12-04 23:39:58 +00001194 reg |= (TPS2205_VPP_PGM | TPS2205_VPP_VCC | /* VAVPP => Hi-Z */
1195 TPS2205_VCC3); /* 3V off */
wdenkc6097192002-11-03 00:24:07 +00001196 reg &= ~(TPS2205_VCC5); /* 5V on */
1197 puts (" 5.0V card found: ");
1198 } else {
wdenk90e7e422002-12-04 23:39:58 +00001199 reg |= (TPS2205_VPP_PGM | TPS2205_VPP_VCC | /* VAVPP => Hi-Z */
1200 TPS2205_VCC5); /* 5V off */
wdenkc6097192002-11-03 00:24:07 +00001201 reg &= ~(TPS2205_VCC3); /* 3V on */
1202 puts (" 3.3V card found: ");
1203 }
1204
1205 debug ("\nPB DAT: %08x -> 3.3V %s 5.0V %s VPP_PGM %s VPP_VCC %s\n",
1206 reg,
1207 (reg & TPS2205_VCC3) ? "off" : "on",
1208 (reg & TPS2205_VCC5) ? "off" : "on",
1209 (reg & TPS2205_VPP_PGM) ? "off" : "on",
1210 (reg & TPS2205_VPP_VCC) ? "off" : "on" );
1211
1212 cp->cp_pbdat = reg;
1213
1214 /* Wait 500 ms; use this to check for over-current */
1215 for (i=0; i<5000; ++i) {
1216 if ((cp->cp_pbdat & TPS2205_OC) == 0) {
1217 printf (" *** Overcurrent - Safety shutdown ***\n");
1218 cp->cp_pbdat &= ~(TPS2205_SHDN);
1219 return (1);
1220 }
1221 udelay (100);
1222 }
1223
1224 debug ("Enable PCMCIA buffers and stop RESET\n");
1225 reg = PCMCIA_PGCRX(_slot_);
1226 reg &= ~__MY_PCMCIA_GCRX_CXRESET; /* active high */
1227 reg &= ~__MY_PCMCIA_GCRX_CXOE; /* active low */
1228 PCMCIA_PGCRX(_slot_) = reg;
1229
1230 udelay(250000); /* some cards need >150 ms to come up :-( */
1231
1232 debug ("# hardware_enable done\n");
1233
1234 return (0);
1235}
1236
1237
wdenkc6097192002-11-03 00:24:07 +00001238#if (CONFIG_COMMANDS & CFG_CMD_PCMCIA)
1239static int hardware_disable(int slot)
1240{
1241 volatile immap_t *immap;
1242 volatile cpm8xx_t *cp;
1243 volatile pcmconf8xx_t *pcmp;
1244 u_long reg;
1245
1246 debug ("hardware_disable: " PCMCIA_BOARD_MSG " Slot %c\n", 'A'+slot);
1247
1248 immap = (immap_t *)CFG_IMMR;
1249 cp = (cpm8xx_t *)(&(((immap_t *)CFG_IMMR)->im_cpm));
1250 pcmp = (pcmconf8xx_t *)(&(((immap_t *)CFG_IMMR)->im_pcmcia));
1251
1252 /* Shut down */
1253 cp->cp_pbdat &= ~(TPS2205_SHDN);
1254
1255 /* Configure PCMCIA General Control Register */
wdenkc6097192002-11-03 00:24:07 +00001256 debug ("Disable PCMCIA buffers and assert RESET\n");
wdenk90e7e422002-12-04 23:39:58 +00001257 reg = 0;
wdenkc6097192002-11-03 00:24:07 +00001258 reg |= __MY_PCMCIA_GCRX_CXRESET; /* active high */
1259 reg |= __MY_PCMCIA_GCRX_CXOE; /* active low */
1260 PCMCIA_PGCRX(_slot_) = reg;
1261
1262 udelay(10000);
1263
1264 return (0);
1265}
1266#endif /* CFG_CMD_PCMCIA */
1267
1268
wdenkc6097192002-11-03 00:24:07 +00001269static int voltage_set(int slot, int vcc, int vpp)
1270{
1271 volatile immap_t *immap;
1272 volatile cpm8xx_t *cp;
1273 volatile pcmconf8xx_t *pcmp;
1274 u_long reg;
1275
1276 debug ("voltage_set: "
1277 PCMCIA_BOARD_MSG
1278 " Slot %c, Vcc=%d.%d, Vpp=%d.%d\n",
1279 'A'+slot, vcc/10, vcc%10, vpp/10, vcc%10);
1280
1281 immap = (immap_t *)CFG_IMMR;
1282 cp = (cpm8xx_t *)(&(((immap_t *)CFG_IMMR)->im_cpm));
1283 pcmp = (pcmconf8xx_t *)(&(((immap_t *)CFG_IMMR)->im_pcmcia));
1284 /*
1285 * Disable PCMCIA buffers (isolate the interface)
1286 * and assert RESET signal
1287 */
1288 debug ("Disable PCMCIA buffers and assert RESET\n");
wdenk90e7e422002-12-04 23:39:58 +00001289 reg = PCMCIA_PGCRX(_slot_);
1290 reg |= __MY_PCMCIA_GCRX_CXRESET; /* active high */
1291 reg |= __MY_PCMCIA_GCRX_CXOE; /* active low */
wdenkc6097192002-11-03 00:24:07 +00001292 PCMCIA_PGCRX(_slot_) = reg;
1293 udelay(500);
1294
1295 /*
1296 * Configure Port C pins for
1297 * 5 Volts Enable and 3 Volts enable,
1298 * Turn all power pins to Hi-Z
1299 */
1300 debug ("PCMCIA power OFF\n");
1301 cfg_port_B (); /* Enables switch, but all in Hi-Z */
1302
1303 reg = cp->cp_pbdat;
1304
1305 switch(vcc) {
1306 case 0: break; /* Switch off */
1307 case 33: reg &= ~TPS2205_VCC3; break; /* Switch on 3.3V */
1308 case 50: reg &= ~TPS2205_VCC5; break; /* Switch on 5.0V */
1309 default: goto done;
1310 }
1311
1312 /* Checking supported voltages */
1313
1314 debug ("PIPR: 0x%x --> %s\n",
1315 pcmp->pcmc_pipr,
1316 (pcmp->pcmc_pipr & 0x00008000) ? "only 5 V" : "can do 3.3V");
1317
1318 cp->cp_pbdat = reg;
1319
1320#ifdef DEBUG
1321 {
1322 char *s;
1323
1324 if ((reg & TPS2205_VCC3) == 0) {
1325 s = "at 3.3V";
1326 } else if ((reg & TPS2205_VCC5) == 0) {
1327 s = "at 5.0V";
1328 } else {
1329 s = "down";
1330 }
1331 printf ("PCMCIA powered %s\n", s);
1332 }
1333#endif
1334
1335done:
1336 debug ("Enable PCMCIA buffers and stop RESET\n");
1337 reg = PCMCIA_PGCRX(_slot_);
1338 reg &= ~__MY_PCMCIA_GCRX_CXRESET; /* active high */
1339 reg &= ~__MY_PCMCIA_GCRX_CXOE; /* active low */
1340 PCMCIA_PGCRX(_slot_) = reg;
1341 udelay(500);
1342
1343 debug ("voltage_set: " PCMCIA_BOARD_MSG " Slot %c, DONE\n",
1344 slot+'A');
1345 return (0);
1346}
1347
1348static void cfg_port_B (void)
1349{
1350 volatile immap_t *immap;
1351 volatile cpm8xx_t *cp;
1352 uint reg;
1353
1354 immap = (immap_t *)CFG_IMMR;
1355 cp = (cpm8xx_t *)(&(((immap_t *)CFG_IMMR)->im_cpm));
1356
1357 /*
1358 * Configure Port B for TPS2205 PC-Card Power-Interface Switch
1359 *
1360 * Switch off all voltages, assert shutdown
1361 */
1362 reg = cp->cp_pbdat;
wdenk90e7e422002-12-04 23:39:58 +00001363 reg |= (TPS2205_VPP_PGM | TPS2205_VPP_VCC | /* VAVPP => Hi-Z */
1364 TPS2205_VCC3 | TPS2205_VCC5 | /* VAVCC => Hi-Z */
1365 TPS2205_SHDN); /* enable switch */
wdenkc6097192002-11-03 00:24:07 +00001366 cp->cp_pbdat = reg;
1367
1368 cp->cp_pbpar &= ~(TPS2205_INPUTS | TPS2205_OUTPUTS);
1369
1370 reg = cp->cp_pbdir & ~(TPS2205_INPUTS);
1371 cp->cp_pbdir = reg | TPS2205_OUTPUTS;
1372
1373 debug ("Set Port B: PAR: %08x DIR: %08x DAT: %08x\n",
1374 cp->cp_pbpar, cp->cp_pbdir, cp->cp_pbdat);
1375}
1376
1377#endif /* ICU862 */
1378
1379
wdenk90e7e422002-12-04 23:39:58 +00001380/* -------------------------------------------------------------------- */
1381/* C2MON Boards by TTTech Computertechnik AG */
1382/* -------------------------------------------------------------------- */
wdenkc6097192002-11-03 00:24:07 +00001383
1384#if defined(CONFIG_C2MON)
1385
1386#define PCMCIA_BOARD_MSG "C2MON"
1387
1388static void cfg_ports (void);
1389
1390static int hardware_enable(int slot)
1391{
1392 volatile immap_t *immap;
1393 volatile cpm8xx_t *cp;
1394 volatile pcmconf8xx_t *pcmp;
1395 volatile sysconf8xx_t *sysp;
1396 uint reg, pipr, mask;
1397 ushort sreg;
1398 int i;
1399
1400 debug ("hardware_enable: " PCMCIA_BOARD_MSG " Slot %c\n", 'A'+slot);
1401
1402 udelay(10000);
1403
1404 immap = (immap_t *)CFG_IMMR;
1405 sysp = (sysconf8xx_t *)(&(((immap_t *)CFG_IMMR)->im_siu_conf));
1406 pcmp = (pcmconf8xx_t *)(&(((immap_t *)CFG_IMMR)->im_pcmcia));
1407 cp = (cpm8xx_t *)(&(((immap_t *)CFG_IMMR)->im_cpm));
1408
1409 /* Configure Ports for TPS2211A PC-Card Power-Interface Switch */
1410 cfg_ports ();
1411
1412 /*
1413 * Configure SIUMCR to enable PCMCIA port B
1414 * (VFLS[0:1] are not used for debugging, we connect FRZ# instead)
1415 */
1416 sysp->sc_siumcr &= ~SIUMCR_DBGC11; /* set DBGC to 00 */
1417
1418 /* clear interrupt state, and disable interrupts */
1419 pcmp->pcmc_pscr = PCMCIA_MASK(_slot_);
1420 pcmp->pcmc_per &= ~PCMCIA_MASK(_slot_);
1421
wdenkc6097192002-11-03 00:24:07 +00001422 /*
wdenk90e7e422002-12-04 23:39:58 +00001423 * Disable interrupts, DMA, and PCMCIA buffers
1424 * (isolate the interface) and assert RESET signal
wdenkc6097192002-11-03 00:24:07 +00001425 */
1426 debug ("Disable PCMCIA buffers and assert RESET\n");
wdenk90e7e422002-12-04 23:39:58 +00001427 reg = 0;
1428 reg |= __MY_PCMCIA_GCRX_CXRESET; /* active high */
1429 reg |= __MY_PCMCIA_GCRX_CXOE; /* active low */
wdenkc6097192002-11-03 00:24:07 +00001430 PCMCIA_PGCRX(_slot_) = reg;
1431 udelay(500);
1432
1433 /*
1434 * Make sure there is a card in the slot, then configure the interface.
1435 */
1436 udelay(10000);
1437 debug ("[%d] %s: PIPR(%p)=0x%x\n",
1438 __LINE__,__FUNCTION__,
1439 &(pcmp->pcmc_pipr),pcmp->pcmc_pipr);
wdenk2029f4d2002-11-21 23:11:29 +00001440 if (pcmp->pcmc_pipr & (0x18000000 >> (slot << 4))) {
wdenkc6097192002-11-03 00:24:07 +00001441 printf (" No Card found\n");
1442 return (1);
1443 }
1444
1445 /*
1446 * Power On: Set VAVCC to 3.3V or 5V, set VAVPP to Hi-Z
1447 */
1448 mask = PCMCIA_VS1(slot) | PCMCIA_VS2(slot);
1449 pipr = pcmp->pcmc_pipr;
1450 debug ("PIPR: 0x%x ==> VS1=o%s, VS2=o%s\n",
1451 pipr,
1452 (reg&PCMCIA_VS1(slot))?"n":"ff",
1453 (reg&PCMCIA_VS2(slot))?"n":"ff");
1454
1455 sreg = immap->im_ioport.iop_pcdat;
1456 if ((pipr & mask) == mask) {
1457 sreg |= (TPS2211_VPPD0 | TPS2211_VPPD1 | /* VAVPP => Hi-Z */
1458 TPS2211_VCCD1); /* 5V on */
1459 sreg &= ~(TPS2211_VCCD0); /* 3V off */
1460 puts (" 5.0V card found: ");
1461 } else {
1462 sreg |= (TPS2211_VPPD0 | TPS2211_VPPD1 | /* VAVPP => Hi-Z */
1463 TPS2211_VCCD0); /* 3V on */
1464 sreg &= ~(TPS2211_VCCD1); /* 5V off */
1465 puts (" 3.3V card found: ");
1466 }
1467
1468 debug ("\nPC DAT: %04x -> 3.3V %s 5.0V %s\n",
1469 sreg,
1470 ( (sreg & TPS2211_VCCD0) && !(sreg & TPS2211_VCCD1)) ? "on" : "off",
1471 (!(sreg & TPS2211_VCCD0) && (sreg & TPS2211_VCCD1)) ? "on" : "off"
1472 );
1473
1474 immap->im_ioport.iop_pcdat = sreg;
1475
1476 /* Wait 500 ms; use this to check for over-current */
1477 for (i=0; i<5000; ++i) {
1478 if ((cp->cp_pbdat & TPS2211_OC) == 0) {
1479 printf (" *** Overcurrent - Safety shutdown ***\n");
1480 immap->im_ioport.iop_pcdat &= ~(TPS2211_VCCD0|TPS2211_VCCD1);
1481 return (1);
1482 }
1483 udelay (100);
1484 }
1485
1486 debug ("Enable PCMCIA buffers and stop RESET\n");
1487 reg = PCMCIA_PGCRX(_slot_);
1488 reg &= ~__MY_PCMCIA_GCRX_CXRESET; /* active high */
1489 reg &= ~__MY_PCMCIA_GCRX_CXOE; /* active low */
1490 PCMCIA_PGCRX(_slot_) = reg;
1491
1492 udelay(250000); /* some cards need >150 ms to come up :-( */
1493
1494 debug ("# hardware_enable done\n");
1495
1496 return (0);
1497}
1498
1499
wdenkc6097192002-11-03 00:24:07 +00001500#if (CONFIG_COMMANDS & CFG_CMD_PCMCIA)
1501static int hardware_disable(int slot)
1502{
1503 volatile immap_t *immap;
1504 volatile cpm8xx_t *cp;
1505 volatile pcmconf8xx_t *pcmp;
1506 u_long reg;
1507
1508 debug ("hardware_disable: " PCMCIA_BOARD_MSG " Slot %c\n", 'A'+slot);
1509
1510 immap = (immap_t *)CFG_IMMR;
1511 pcmp = (pcmconf8xx_t *)(&(((immap_t *)CFG_IMMR)->im_pcmcia));
1512
1513 /* Configure PCMCIA General Control Register */
wdenkc6097192002-11-03 00:24:07 +00001514 debug ("Disable PCMCIA buffers and assert RESET\n");
wdenk90e7e422002-12-04 23:39:58 +00001515 reg = 0;
wdenkc6097192002-11-03 00:24:07 +00001516 reg |= __MY_PCMCIA_GCRX_CXRESET; /* active high */
1517 reg |= __MY_PCMCIA_GCRX_CXOE; /* active low */
1518 PCMCIA_PGCRX(_slot_) = reg;
1519
1520 /* ALl voltages off / Hi-Z */
1521 immap->im_ioport.iop_pcdat |= (TPS2211_VPPD0 | TPS2211_VPPD1 |
1522 TPS2211_VCCD0 | TPS2211_VCCD1 );
1523
1524 udelay(10000);
1525
1526 return (0);
1527}
1528#endif /* CFG_CMD_PCMCIA */
1529
1530
wdenkc6097192002-11-03 00:24:07 +00001531static int voltage_set(int slot, int vcc, int vpp)
1532{
1533 volatile immap_t *immap;
1534 volatile cpm8xx_t *cp;
1535 volatile pcmconf8xx_t *pcmp;
1536 u_long reg;
1537 ushort sreg;
1538
1539 debug ("voltage_set: "
1540 PCMCIA_BOARD_MSG
1541 " Slot %c, Vcc=%d.%d, Vpp=%d.%d\n",
1542 'A'+slot, vcc/10, vcc%10, vpp/10, vcc%10);
1543
1544 immap = (immap_t *)CFG_IMMR;
1545 cp = (cpm8xx_t *)(&(((immap_t *)CFG_IMMR)->im_cpm));
1546 pcmp = (pcmconf8xx_t *)(&(((immap_t *)CFG_IMMR)->im_pcmcia));
1547 /*
1548 * Disable PCMCIA buffers (isolate the interface)
1549 * and assert RESET signal
1550 */
1551 debug ("Disable PCMCIA buffers and assert RESET\n");
wdenk90e7e422002-12-04 23:39:58 +00001552 reg = PCMCIA_PGCRX(_slot_);
1553 reg |= __MY_PCMCIA_GCRX_CXRESET; /* active high */
1554 reg |= __MY_PCMCIA_GCRX_CXOE; /* active low */
wdenkc6097192002-11-03 00:24:07 +00001555 PCMCIA_PGCRX(_slot_) = reg;
1556 udelay(500);
1557
1558 /*
1559 * Configure Port C pins for
1560 * 5 Volts Enable and 3 Volts enable,
1561 * Turn all power pins to Hi-Z
1562 */
1563 debug ("PCMCIA power OFF\n");
1564 cfg_ports (); /* Enables switch, but all in Hi-Z */
1565
1566 sreg = immap->im_ioport.iop_pcdat;
1567 sreg |= TPS2211_VPPD0 | TPS2211_VPPD1; /* VAVPP always Hi-Z */
1568
1569 switch(vcc) {
1570 case 0: break; /* Switch off */
1571 case 33: sreg |= TPS2211_VCCD0; /* Switch on 3.3V */
1572 sreg &= ~TPS2211_VCCD1;
1573 break;
1574 case 50: sreg &= ~TPS2211_VCCD0; /* Switch on 5.0V */
1575 sreg |= TPS2211_VCCD1;
1576 break;
1577 default: goto done;
1578 }
1579
1580 /* Checking supported voltages */
1581
1582 debug ("PIPR: 0x%x --> %s\n",
1583 pcmp->pcmc_pipr,
1584 (pcmp->pcmc_pipr & 0x00008000) ? "only 5 V" : "can do 3.3V");
1585
1586 immap->im_ioport.iop_pcdat = sreg;
1587
1588#ifdef DEBUG
1589 {
1590 char *s;
1591
1592 if ((sreg & TPS2211_VCCD0) && !(sreg & TPS2211_VCCD1)) {
1593 s = "at 3.3V";
1594 } else if (!(sreg & TPS2211_VCCD0) && (sreg & TPS2211_VCCD1)) {
1595 s = "at 5.0V";
1596 } else {
1597 s = "down";
1598 }
1599 printf ("PCMCIA powered %s\n", s);
1600 }
1601#endif
1602
1603done:
1604 debug ("Enable PCMCIA buffers and stop RESET\n");
1605 reg = PCMCIA_PGCRX(_slot_);
1606 reg &= ~__MY_PCMCIA_GCRX_CXRESET; /* active high */
1607 reg &= ~__MY_PCMCIA_GCRX_CXOE; /* active low */
1608 PCMCIA_PGCRX(_slot_) = reg;
1609 udelay(500);
1610
1611 debug ("voltage_set: " PCMCIA_BOARD_MSG " Slot %c, DONE\n",
1612 slot+'A');
1613 return (0);
1614}
1615
1616static void cfg_ports (void)
1617{
1618 volatile immap_t *immap;
1619 volatile cpm8xx_t *cp;
1620 ushort sreg;
1621
1622 immap = (immap_t *)CFG_IMMR;
1623 cp = (cpm8xx_t *)(&(((immap_t *)CFG_IMMR)->im_cpm));
1624
1625 /*
1626 * Configure Port C for TPS2211 PC-Card Power-Interface Switch
1627 *
1628 * Switch off all voltages, assert shutdown
1629 */
1630 sreg = immap->im_ioport.iop_pcdat;
1631 sreg |= (TPS2211_VPPD0 | TPS2211_VPPD1); /* VAVPP => Hi-Z */
1632 sreg &= ~(TPS2211_VCCD0 | TPS2211_VCCD1); /* 3V and 5V off */
1633 immap->im_ioport.iop_pcdat = sreg;
1634
1635 immap->im_ioport.iop_pcpar &= ~(TPS2211_OUTPUTS);
1636 immap->im_ioport.iop_pcdir |= TPS2211_OUTPUTS;
1637
1638 debug ("Set Port C: PAR: %04x DIR: %04x DAT: %04x\n",
1639 immap->im_ioport.iop_pcpar,
1640 immap->im_ioport.iop_pcdir,
1641 immap->im_ioport.iop_pcdat);
1642
1643 /*
1644 * Configure Port B for TPS2211 PC-Card Power-Interface Switch
1645 *
1646 * Over-Current Input only
1647 */
1648 cp->cp_pbpar &= ~(TPS2211_INPUTS);
1649 cp->cp_pbdir &= ~(TPS2211_INPUTS);
1650
1651 debug ("Set Port B: PAR: %08x DIR: %08x DAT: %08x\n",
1652 cp->cp_pbpar, cp->cp_pbdir, cp->cp_pbdat);
1653}
1654
1655#endif /* C2MON */
1656
wdenk90e7e422002-12-04 23:39:58 +00001657/* -------------------------------------------------------------------- */
1658/* MBX board from Morotola */
1659/* -------------------------------------------------------------------- */
wdenkc6097192002-11-03 00:24:07 +00001660
1661#if defined( CONFIG_MBX )
1662#include <../board/mbx8xx/csr.h>
1663
1664/* A lot of this has been taken from the RPX code in this file it works from me.
1665 I have added the voltage selection for the MBX board. */
1666
1667/* MBX voltage bit in control register #2 */
1668#define CR2_VPP12 ((uchar)0x10)
1669#define CR2_VPPVDD ((uchar)0x20)
1670#define CR2_VDD5 ((uchar)0x40)
1671#define CR2_VDD3 ((uchar)0x80)
1672
1673#define PCMCIA_BOARD_MSG "MBX860"
1674
1675static int voltage_set (int slot, int vcc, int vpp)
1676{
1677 uchar reg = 0;
1678
1679 debug ("voltage_set: PCMCIA_BOARD_MSG Slot %c, Vcc=%d.%d, Vpp=%d.%d\n",
1680 'A' + slot, vcc / 10, vcc % 10, vpp / 10, vcc % 10);
1681
1682 switch (vcc) {
1683 case 0:
1684 break;
1685 case 33:
1686 reg |= CR2_VDD3;
1687 break;
1688 case 50:
1689 reg |= CR2_VDD5;
1690 break;
1691 default:
1692 return 1;
1693 }
1694
1695 switch (vpp) {
1696 case 0:
1697 break;
1698 case 33:
1699 case 50:
1700 if (vcc == vpp) {
1701 reg |= CR2_VPPVDD;
1702 } else {
1703 return 1;
1704 }
1705 break;
1706 case 120:
1707 reg |= CR2_VPP12;
1708 break;
1709 default:
1710 return 1;
1711 }
1712
1713 /* first, turn off all power */
1714 MBX_CSR2 &= ~(CR2_VDDSEL | CR2_VPPSEL);
1715
1716 /* enable new powersettings */
1717 MBX_CSR2 |= reg;
1718 debug ("MBX_CSR2 read = 0x%02x\n", MBX_CSR2);
1719
1720 return (0);
1721}
1722
1723static int hardware_enable (int slot)
1724{
1725 volatile immap_t *immap;
1726 volatile cpm8xx_t *cp;
1727 volatile pcmconf8xx_t *pcmp;
1728 volatile sysconf8xx_t *sysp;
1729 uint reg, mask;
1730
1731 debug ("hardware_enable: " PCMCIA_BOARD_MSG " Slot %c\n",
1732 'A' + slot);
1733
1734 udelay (10000);
1735
1736 immap = (immap_t *) CFG_IMMR;
1737 sysp = (sysconf8xx_t *) (&(((immap_t *) CFG_IMMR)->im_siu_conf));
1738 pcmp = (pcmconf8xx_t *) (&(((immap_t *) CFG_IMMR)->im_pcmcia));
1739 cp = (cpm8xx_t *) (&(((immap_t *) CFG_IMMR)->im_cpm));
1740
1741 /* clear interrupt state, and disable interrupts */
1742 pcmp->pcmc_pscr = PCMCIA_MASK (_slot_);
1743 pcmp->pcmc_per &= ~PCMCIA_MASK (_slot_);
1744
wdenkc6097192002-11-03 00:24:07 +00001745 /*
wdenk90e7e422002-12-04 23:39:58 +00001746 * Disable interrupts, DMA, and PCMCIA buffers
1747 * (isolate the interface) and assert RESET signal
wdenkc6097192002-11-03 00:24:07 +00001748 */
1749 debug ("Disable PCMCIA buffers and assert RESET\n");
wdenk90e7e422002-12-04 23:39:58 +00001750 reg = 0;
wdenkc6097192002-11-03 00:24:07 +00001751 reg |= __MY_PCMCIA_GCRX_CXRESET; /* active high */
1752 reg |= __MY_PCMCIA_GCRX_CXOE; /* active low */
1753 PCMCIA_PGCRX (_slot_) = reg;
1754 udelay (500);
1755
1756 /* remove all power */
1757 voltage_set (slot, 0, 0);
1758 /*
1759 * Make sure there is a card in the slot, then configure the interface.
1760 */
wdenk2029f4d2002-11-21 23:11:29 +00001761 udelay(10000);
1762 debug ("[%d] %s: PIPR(%p)=0x%x\n",
1763 __LINE__,__FUNCTION__,
1764 &(pcmp->pcmc_pipr),pcmp->pcmc_pipr);
1765 if (pcmp->pcmc_pipr & (0x18000000 >> (slot << 4))) {
wdenkc6097192002-11-03 00:24:07 +00001766 printf (" No Card found\n");
1767 return (1);
1768 }
1769
1770 /*
1771 * Power On.
1772 */
1773 mask = PCMCIA_VS1 (_slot_) | PCMCIA_VS2 (_slot_);
1774 reg = pcmp->pcmc_pipr;
1775 debug ("PIPR: 0x%x ==> VS1=o%s, VS2=o%s\n", reg,
1776 (reg & PCMCIA_VS1 (slot)) ? "n" : "ff",
1777 (reg & PCMCIA_VS2 (slot)) ? "n" : "ff");
1778
1779 if ((reg & mask) == mask) {
1780 voltage_set (_slot_, 50, 0);
1781 printf (" 5.0V card found: ");
1782 } else {
1783 voltage_set (_slot_, 33, 0);
1784 printf (" 3.3V card found: ");
1785 }
1786
1787 debug ("Enable PCMCIA buffers and stop RESET\n");
1788 reg = PCMCIA_PGCRX (_slot_);
1789 reg &= ~__MY_PCMCIA_GCRX_CXRESET; /* active high */
1790 reg &= ~__MY_PCMCIA_GCRX_CXOE; /* active low */
1791 PCMCIA_PGCRX (_slot_) = reg;
1792
1793 udelay (250000); /* some cards need >150 ms to come up :-( */
1794
1795 debug ("# hardware_enable done\n");
1796
1797 return (0);
1798}
1799
1800#if (CONFIG_COMMANDS & CFG_CMD_PCMCIA)
1801static int hardware_disable (int slot)
1802{
1803 return 0; /* No hardware to disable */
1804}
1805#endif /* CFG_CMD_PCMCIA */
1806#endif /* CONFIG_MBX */
wdenk90e7e422002-12-04 23:39:58 +00001807/* -------------------------------------------------------------------- */
1808/* R360MPI Board */
1809/* -------------------------------------------------------------------- */
wdenkc6097192002-11-03 00:24:07 +00001810
1811#if defined(CONFIG_R360MPI)
1812
1813#define PCMCIA_BOARD_MSG "R360MPI"
1814
1815
1816static int hardware_enable(int slot)
1817{
1818 volatile immap_t *immap;
1819 volatile cpm8xx_t *cp;
1820 volatile pcmconf8xx_t *pcmp;
1821 volatile sysconf8xx_t *sysp;
1822 uint reg, mask;
1823
1824 debug ("hardware_enable: " PCMCIA_BOARD_MSG " Slot %c\n", 'A'+slot);
1825
1826 udelay(10000);
1827
1828 immap = (immap_t *)CFG_IMMR;
1829 sysp = (sysconf8xx_t *)(&(((immap_t *)CFG_IMMR)->im_siu_conf));
1830 pcmp = (pcmconf8xx_t *)(&(((immap_t *)CFG_IMMR)->im_pcmcia));
1831 cp = (cpm8xx_t *)(&(((immap_t *)CFG_IMMR)->im_cpm));
1832
1833 /*
1834 * Configure SIUMCR to enable PCMCIA port B
1835 * (VFLS[0:1] are not used for debugging, we connect FRZ# instead)
1836 */
1837 sysp->sc_siumcr &= ~SIUMCR_DBGC11; /* set DBGC to 00 */
1838
1839 /* clear interrupt state, and disable interrupts */
1840 pcmp->pcmc_pscr = PCMCIA_MASK(_slot_);
1841 pcmp->pcmc_per &= ~PCMCIA_MASK(_slot_);
1842
wdenkc6097192002-11-03 00:24:07 +00001843 /*
wdenk90e7e422002-12-04 23:39:58 +00001844 * Disable interrupts, DMA, and PCMCIA buffers
1845 * (isolate the interface) and assert RESET signal
wdenkc6097192002-11-03 00:24:07 +00001846 */
1847 debug ("Disable PCMCIA buffers and assert RESET\n");
wdenk90e7e422002-12-04 23:39:58 +00001848 reg = 0;
1849 reg |= __MY_PCMCIA_GCRX_CXRESET; /* active high */
1850 reg |= __MY_PCMCIA_GCRX_CXOE; /* active low */
wdenkc6097192002-11-03 00:24:07 +00001851 PCMCIA_PGCRX(_slot_) = reg;
1852 udelay(500);
1853
1854 /*
1855 * Configure Ports A, B & C pins for
1856 * 5 Volts Enable and 3 Volts enable
1857 */
1858 immap->im_ioport.iop_pcpar &= ~(0x0400);
1859 immap->im_ioport.iop_pcso &= ~(0x0400);/*
1860 immap->im_ioport.iop_pcdir |= 0x0400;*/
1861
1862 immap->im_ioport.iop_papar &= ~(0x0200);/*
1863 immap->im_ioport.iop_padir |= 0x0200;*/
1864#if 0
1865 immap->im_ioport.iop_pbpar &= ~(0xC000);
1866 immap->im_ioport.iop_pbdir &= ~(0xC000);
1867#endif
1868 /* remove all power */
1869
1870 immap->im_ioport.iop_pcdat |= 0x0400;
1871 immap->im_ioport.iop_padat |= 0x0200;
1872
1873 /*
1874 * Make sure there is a card in the slot, then configure the interface.
1875 */
1876 udelay(10000);
1877 debug ("[%d] %s: PIPR(%p)=0x%x\n",
1878 __LINE__,__FUNCTION__,
1879 &(pcmp->pcmc_pipr),pcmp->pcmc_pipr);
wdenk2029f4d2002-11-21 23:11:29 +00001880 if (pcmp->pcmc_pipr & (0x18000000 >> (slot << 4))) {
wdenkc6097192002-11-03 00:24:07 +00001881 printf (" No Card found\n");
1882 return (1);
1883 }
1884
1885 /*
1886 * Power On.
1887 */
1888 mask = PCMCIA_VS1(slot) | PCMCIA_VS2(slot);
1889 reg = pcmp->pcmc_pipr;
1890 debug ("PIPR: 0x%x ==> VS1=o%s, VS2=o%s\n",
1891 reg,
1892 (reg&PCMCIA_VS1(slot))?"n":"ff",
1893 (reg&PCMCIA_VS2(slot))?"n":"ff");
1894 if ((reg & mask) == mask) {
1895 immap->im_ioport.iop_pcdat &= ~(0x4000);
1896 puts (" 5.0V card found: ");
1897 } else {
1898 immap->im_ioport.iop_padat &= ~(0x0002);
1899 puts (" 3.3V card found: ");
1900 }
1901 immap->im_ioport.iop_pcdir |= 0x0400;
1902 immap->im_ioport.iop_padir |= 0x0200;
1903#if 0
1904 /* VCC switch error flag, PCMCIA slot INPACK_ pin */
1905 cp->cp_pbdir &= ~(0x0020 | 0x0010);
1906 cp->cp_pbpar &= ~(0x0020 | 0x0010);
1907 udelay(500000);
1908#endif
1909 debug ("Enable PCMCIA buffers and stop RESET\n");
1910 reg = PCMCIA_PGCRX(_slot_);
1911 reg &= ~__MY_PCMCIA_GCRX_CXRESET; /* active high */
1912 reg &= ~__MY_PCMCIA_GCRX_CXOE; /* active low */
1913 PCMCIA_PGCRX(_slot_) = reg;
1914
1915 udelay(250000); /* some cards need >150 ms to come up :-( */
1916
1917 debug ("# hardware_enable done\n");
1918
1919 return (0);
1920}
1921
1922
wdenkc6097192002-11-03 00:24:07 +00001923#if (CONFIG_COMMANDS & CFG_CMD_PCMCIA)
1924static int hardware_disable(int slot)
1925{
1926 volatile immap_t *immap;
1927 volatile pcmconf8xx_t *pcmp;
1928 u_long reg;
1929
1930 debug ("hardware_disable: " PCMCIA_BOARD_MSG " Slot %c\n", 'A'+slot);
1931
1932 immap = (immap_t *)CFG_IMMR;
1933 pcmp = (pcmconf8xx_t *)(&(((immap_t *)CFG_IMMR)->im_pcmcia));
1934
1935 /* remove all power */
1936 immap->im_ioport.iop_pcdat |= 0x0400;
1937 immap->im_ioport.iop_padat |= 0x0200;
1938
1939 /* Configure PCMCIA General Control Register */
wdenkc6097192002-11-03 00:24:07 +00001940 debug ("Disable PCMCIA buffers and assert RESET\n");
wdenk90e7e422002-12-04 23:39:58 +00001941 reg = 0;
wdenkc6097192002-11-03 00:24:07 +00001942 reg |= __MY_PCMCIA_GCRX_CXRESET; /* active high */
1943 reg |= __MY_PCMCIA_GCRX_CXOE; /* active low */
1944 PCMCIA_PGCRX(_slot_) = reg;
1945
1946 udelay(10000);
1947
1948 return (0);
1949}
1950#endif /* CFG_CMD_PCMCIA */
1951
1952
wdenkc6097192002-11-03 00:24:07 +00001953static int voltage_set(int slot, int vcc, int vpp)
1954{
1955 volatile immap_t *immap;
1956 volatile pcmconf8xx_t *pcmp;
1957 u_long reg;
1958
1959 debug ("voltage_set: "
1960 PCMCIA_BOARD_MSG
1961 " Slot %c, Vcc=%d.%d, Vpp=%d.%d\n",
1962 'A'+slot, vcc/10, vcc%10, vpp/10, vcc%10);
1963
1964 immap = (immap_t *)CFG_IMMR;
1965 pcmp = (pcmconf8xx_t *)(&(((immap_t *)CFG_IMMR)->im_pcmcia));
1966 /*
1967 * Disable PCMCIA buffers (isolate the interface)
1968 * and assert RESET signal
1969 */
1970 debug ("Disable PCMCIA buffers and assert RESET\n");
wdenk90e7e422002-12-04 23:39:58 +00001971 reg = PCMCIA_PGCRX(_slot_);
1972 reg |= __MY_PCMCIA_GCRX_CXRESET; /* active high */
1973 reg |= __MY_PCMCIA_GCRX_CXOE; /* active low */
wdenkc6097192002-11-03 00:24:07 +00001974 PCMCIA_PGCRX(_slot_) = reg;
1975 udelay(500);
1976
1977 /*
1978 * Configure Ports A & C pins for
1979 * 5 Volts Enable and 3 Volts enable,
1980 * Turn off all power
1981 */
1982 debug ("PCMCIA power OFF\n");
1983 immap->im_ioport.iop_pcpar &= ~(0x0400);
1984 immap->im_ioport.iop_pcso &= ~(0x0400);/*
1985 immap->im_ioport.iop_pcdir |= 0x0400;*/
1986
1987 immap->im_ioport.iop_papar &= ~(0x0200);/*
1988 immap->im_ioport.iop_padir |= 0x0200;*/
1989
1990 immap->im_ioport.iop_pcdat |= 0x0400;
1991 immap->im_ioport.iop_padat |= 0x0200;
1992
1993 reg = 0;
1994 switch(vcc) {
1995 case 0: break;
1996 case 33: reg |= 0x0200; break;
1997 case 50: reg |= 0x0400; break;
1998 default: goto done;
1999 }
2000
2001 /* Checking supported voltages */
2002
2003 debug ("PIPR: 0x%x --> %s\n",
2004 pcmp->pcmc_pipr,
2005 (pcmp->pcmc_pipr & 0x00008000) ? "only 5 V" : "can do 3.3V");
2006
2007 if (reg & 0x0200)
2008 immap->im_ioport.iop_pcdat &= !reg;
2009 if (reg & 0x0400)
2010 immap->im_ioport.iop_padat &= !reg;
wdenk90e7e422002-12-04 23:39:58 +00002011 immap->im_ioport.iop_pcdir |= 0x0200;
2012 immap->im_ioport.iop_padir |= 0x0400;
wdenkc6097192002-11-03 00:24:07 +00002013 if (reg) {
2014 debug ("PCMCIA powered at %sV\n",
2015 (reg&0x0400) ? "5.0" : "3.3");
2016 } else {
2017 debug ("PCMCIA powered down\n");
2018 }
2019
2020done:
2021 debug ("Enable PCMCIA buffers and stop RESET\n");
2022 reg = PCMCIA_PGCRX(_slot_);
2023 reg &= ~__MY_PCMCIA_GCRX_CXRESET; /* active high */
2024 reg &= ~__MY_PCMCIA_GCRX_CXOE; /* active low */
2025 PCMCIA_PGCRX(_slot_) = reg;
2026 udelay(500);
2027
2028 debug ("voltage_set: " PCMCIA_BOARD_MSG " Slot %c, DONE\n",
2029 slot+'A');
2030 return (0);
2031}
2032
2033#endif /* R360MPI */
2034
wdenk90e7e422002-12-04 23:39:58 +00002035/* -------------------------------------------------------------------- */
2036/* KUP4K Board */
2037/* -------------------------------------------------------------------- */
wdenk56f94be2002-11-05 16:35:14 +00002038#if defined(CONFIG_KUP4K)
2039
2040#define PCMCIA_BOARD_MSG "KUP4K"
2041
2042#define KUP4K_PCMCIA_B_3V3 (0x00020000)
2043
2044static int hardware_enable(int slot)
2045{
2046 volatile immap_t *immap;
2047 volatile cpm8xx_t *cp;
2048 volatile pcmconf8xx_t *pcmp;
2049 volatile sysconf8xx_t *sysp;
2050 uint reg, mask;
2051
2052 debug ("hardware_enable: " PCMCIA_BOARD_MSG " Slot %c\n", 'A'+slot);
2053
2054 udelay(10000);
2055
2056 immap = (immap_t *)CFG_IMMR;
2057 sysp = (sysconf8xx_t *)(&(((immap_t *)CFG_IMMR)->im_siu_conf));
2058 pcmp = (pcmconf8xx_t *)(&(((immap_t *)CFG_IMMR)->im_pcmcia));
2059 cp = (cpm8xx_t *)(&(((immap_t *)CFG_IMMR)->im_cpm));
2060
2061 /*
2062 * Configure SIUMCR to enable PCMCIA port B
2063 * (VFLS[0:1] are not used for debugging, we connect FRZ# instead)
2064 */
2065 sysp->sc_siumcr &= ~SIUMCR_DBGC11; /* set DBGC to 00 */
2066
2067 /* clear interrupt state, and disable interrupts */
wdenk2029f4d2002-11-21 23:11:29 +00002068 pcmp->pcmc_pscr = PCMCIA_MASK(slot);
2069 pcmp->pcmc_per &= ~PCMCIA_MASK(slot);
wdenk56f94be2002-11-05 16:35:14 +00002070
wdenk56f94be2002-11-05 16:35:14 +00002071 /*
wdenk90e7e422002-12-04 23:39:58 +00002072 * Disable interrupts, DMA, and PCMCIA buffers
2073 * (isolate the interface) and assert RESET signal
wdenk56f94be2002-11-05 16:35:14 +00002074 */
2075 debug ("Disable PCMCIA buffers and assert RESET\n");
wdenk90e7e422002-12-04 23:39:58 +00002076 reg = 0;
2077 reg |= __MY_PCMCIA_GCRX_CXRESET; /* active high */
2078 reg |= __MY_PCMCIA_GCRX_CXOE; /* active low */
wdenk2029f4d2002-11-21 23:11:29 +00002079 PCMCIA_PGCRX(slot) = reg;
2080 udelay(2500);
wdenk56f94be2002-11-05 16:35:14 +00002081
2082 /*
2083 * Configure Port B pins for
2084 * 3 Volts enable
2085 */
wdenk2029f4d2002-11-21 23:11:29 +00002086 if (slot) { /* Slot A is built-in */
2087 cp->cp_pbdir |= KUP4K_PCMCIA_B_3V3;
2088 cp->cp_pbpar &= ~KUP4K_PCMCIA_B_3V3;
2089 /* remove all power */
2090 cp->cp_pbdat |= KUP4K_PCMCIA_B_3V3; /* active low */
2091 }
wdenk56f94be2002-11-05 16:35:14 +00002092 /*
2093 * Make sure there is a card in the slot, then configure the interface.
2094 */
2095 udelay(10000);
2096 debug ("[%d] %s: PIPR(%p)=0x%x\n",
2097 __LINE__,__FUNCTION__,
2098 &(pcmp->pcmc_pipr),pcmp->pcmc_pipr);
wdenk2029f4d2002-11-21 23:11:29 +00002099 if (pcmp->pcmc_pipr & (0x18000000 >> (slot << 4))) {
wdenk56f94be2002-11-05 16:35:14 +00002100 printf (" No Card found\n");
2101 return (1);
2102 }
2103
2104 /*
2105 * Power On.
2106 */
wdenk9dd2b882002-12-03 21:28:10 +00002107 printf("%s Slot %c:", slot ? "" : "\n", 'A' + slot);
wdenk56f94be2002-11-05 16:35:14 +00002108 mask = PCMCIA_VS1(slot) | PCMCIA_VS2(slot);
2109 reg = pcmp->pcmc_pipr;
2110 debug ("PIPR: 0x%x ==> VS1=o%s, VS2=o%s\n",
2111 reg,
2112 (reg&PCMCIA_VS1(slot))?"n":"ff",
2113 (reg&PCMCIA_VS2(slot))?"n":"ff");
2114 if ((reg & mask) == mask) {
2115 puts (" 5.0V card found: NOT SUPPORTED !!!\n");
2116 } else {
wdenk2029f4d2002-11-21 23:11:29 +00002117 if(slot)
2118 cp->cp_pbdat &= ~KUP4K_PCMCIA_B_3V3;
wdenk56f94be2002-11-05 16:35:14 +00002119 puts (" 3.3V card found: ");
2120 }
2121#if 0
2122 /* VCC switch error flag, PCMCIA slot INPACK_ pin */
2123 cp->cp_pbdir &= ~(0x0020 | 0x0010);
2124 cp->cp_pbpar &= ~(0x0020 | 0x0010);
2125 udelay(500000);
2126#endif
2127 debug ("Enable PCMCIA buffers and stop RESET\n");
wdenk2029f4d2002-11-21 23:11:29 +00002128 reg = PCMCIA_PGCRX(slot);
wdenk56f94be2002-11-05 16:35:14 +00002129 reg &= ~__MY_PCMCIA_GCRX_CXRESET; /* active high */
2130 reg &= ~__MY_PCMCIA_GCRX_CXOE; /* active low */
wdenk2029f4d2002-11-21 23:11:29 +00002131 PCMCIA_PGCRX(slot) = reg;
wdenk56f94be2002-11-05 16:35:14 +00002132
2133 udelay(250000); /* some cards need >150 ms to come up :-( */
2134
2135 debug ("# hardware_enable done\n");
2136
2137 return (0);
2138}
2139
2140
wdenk56f94be2002-11-05 16:35:14 +00002141#if (CONFIG_COMMANDS & CFG_CMD_PCMCIA)
2142static int hardware_disable(int slot)
2143{
2144 volatile immap_t *immap;
2145 volatile cpm8xx_t *cp;
2146 volatile pcmconf8xx_t *pcmp;
2147 u_long reg;
2148
2149 debug ("hardware_disable: " PCMCIA_BOARD_MSG " Slot %c\n", 'A'+slot);
2150
2151 immap = (immap_t *)CFG_IMMR;
2152 pcmp = (pcmconf8xx_t *)(&(((immap_t *)CFG_IMMR)->im_pcmcia));
2153 cp = (cpm8xx_t *)(&(((immap_t *)CFG_IMMR)->im_cpm));
wdenk90e7e422002-12-04 23:39:58 +00002154
wdenk56f94be2002-11-05 16:35:14 +00002155 /* remove all power */
wdenk2029f4d2002-11-21 23:11:29 +00002156 if (slot)
2157 cp->cp_pbdat |= KUP4K_PCMCIA_B_3V3;
wdenk56f94be2002-11-05 16:35:14 +00002158
2159 /* Configure PCMCIA General Control Register */
wdenk56f94be2002-11-05 16:35:14 +00002160 debug ("Disable PCMCIA buffers and assert RESET\n");
wdenk90e7e422002-12-04 23:39:58 +00002161 reg = 0;
wdenk56f94be2002-11-05 16:35:14 +00002162 reg |= __MY_PCMCIA_GCRX_CXRESET; /* active high */
2163 reg |= __MY_PCMCIA_GCRX_CXOE; /* active low */
wdenk2029f4d2002-11-21 23:11:29 +00002164 PCMCIA_PGCRX(slot) = reg;
wdenk56f94be2002-11-05 16:35:14 +00002165
2166 udelay(10000);
2167
2168 return (0);
2169}
2170#endif /* CFG_CMD_PCMCIA */
2171
2172
wdenk56f94be2002-11-05 16:35:14 +00002173static int voltage_set(int slot, int vcc, int vpp)
2174{
2175 volatile immap_t *immap;
2176 volatile cpm8xx_t *cp;
2177 volatile pcmconf8xx_t *pcmp;
2178 u_long reg;
2179
2180 debug ("voltage_set: " \
2181 PCMCIA_BOARD_MSG \
2182 " Slot %c, Vcc=%d.%d, Vpp=%d.%d\n",
2183 'A'+slot, vcc/10, vcc%10, vpp/10, vcc%10);
2184
wdenk2029f4d2002-11-21 23:11:29 +00002185 if (!slot) /* Slot A is not configurable */
2186 return 0;
2187
wdenk56f94be2002-11-05 16:35:14 +00002188 immap = (immap_t *)CFG_IMMR;
2189 pcmp = (pcmconf8xx_t *)(&(((immap_t *)CFG_IMMR)->im_pcmcia));
2190 cp = (cpm8xx_t *)(&(((immap_t *)CFG_IMMR)->im_cpm));
2191
2192 /*
2193 * Disable PCMCIA buffers (isolate the interface)
2194 * and assert RESET signal
2195 */
2196 debug ("Disable PCMCIA buffers and assert RESET\n");
wdenk90e7e422002-12-04 23:39:58 +00002197 reg = PCMCIA_PGCRX(slot);
2198 reg |= __MY_PCMCIA_GCRX_CXRESET; /* active high */
2199 reg |= __MY_PCMCIA_GCRX_CXOE; /* active low */
wdenk2029f4d2002-11-21 23:11:29 +00002200 PCMCIA_PGCRX(slot) = reg;
wdenk56f94be2002-11-05 16:35:14 +00002201 udelay(500);
2202
2203 debug ("PCMCIA power OFF\n");
2204 /*
2205 * Configure Port B pins for
2206 * 3 Volts enable
2207 */
2208 cp->cp_pbdir |= KUP4K_PCMCIA_B_3V3;
2209 cp->cp_pbpar &= ~KUP4K_PCMCIA_B_3V3;
2210 /* remove all power */
2211 cp->cp_pbdat |= KUP4K_PCMCIA_B_3V3; /* active low */
2212
2213 switch(vcc) {
2214 case 0: break;
2215 case 33:
2216 cp->cp_pbdat &= ~KUP4K_PCMCIA_B_3V3;
2217 debug ("PCMCIA powered at 3.3V\n");
2218 break;
2219 case 50:
2220 debug ("PCMCIA: 5Volt vcc not supported\n");
2221 break;
2222 default:
2223 puts("PCMCIA: vcc not supported");
2224 break;
2225 }
wdenk2029f4d2002-11-21 23:11:29 +00002226 udelay(10000);
wdenk56f94be2002-11-05 16:35:14 +00002227 /* Checking supported voltages */
2228
2229 debug ("PIPR: 0x%x --> %s\n",
2230 pcmp->pcmc_pipr,
wdenk2029f4d2002-11-21 23:11:29 +00002231 (pcmp->pcmc_pipr & (0x80000000 >> (slot << 4)))
wdenk56f94be2002-11-05 16:35:14 +00002232 ? "only 5 V --> NOT SUPPORTED"
2233 : "can do 3.3V");
2234
2235
2236 debug ("Enable PCMCIA buffers and stop RESET\n");
wdenk2029f4d2002-11-21 23:11:29 +00002237 reg = PCMCIA_PGCRX(slot);
wdenk56f94be2002-11-05 16:35:14 +00002238 reg &= ~__MY_PCMCIA_GCRX_CXRESET; /* active high */
2239 reg &= ~__MY_PCMCIA_GCRX_CXOE; /* active low */
wdenk2029f4d2002-11-21 23:11:29 +00002240 PCMCIA_PGCRX(slot) = reg;
wdenk56f94be2002-11-05 16:35:14 +00002241 udelay(500);
2242
2243 debug ("voltage_set: " PCMCIA_BOARD_MSG " Slot %c, DONE\n",
2244 slot+'A');
2245 return (0);
2246}
2247
2248#endif /* KUP4K */
2249
2250
wdenk90e7e422002-12-04 23:39:58 +00002251/* -------------------------------------------------------------------- */
2252/* End of Board Specific Stuff */
2253/* -------------------------------------------------------------------- */
wdenkc6097192002-11-03 00:24:07 +00002254
2255
wdenk90e7e422002-12-04 23:39:58 +00002256/* -------------------------------------------------------------------- */
2257/* MPC8xx Specific Stuff - should go to MPC8xx directory */
2258/* -------------------------------------------------------------------- */
wdenkc6097192002-11-03 00:24:07 +00002259
2260/*
2261 * Search this table to see if the windowsize is
2262 * supported...
2263 */
2264
2265#define M8XX_SIZES_NO 32
2266
2267static const u_int m8xx_size_to_gray[M8XX_SIZES_NO] =
2268{ 0x00000001, 0x00000002, 0x00000008, 0x00000004,
2269 0x00000080, 0x00000040, 0x00000010, 0x00000020,
2270 0x00008000, 0x00004000, 0x00001000, 0x00002000,
2271 0x00000100, 0x00000200, 0x00000800, 0x00000400,
2272
2273 0x0fffffff, 0xffffffff, 0xffffffff, 0xffffffff,
2274 0x01000000, 0x02000000, 0xffffffff, 0x04000000,
2275 0x00010000, 0x00020000, 0x00080000, 0x00040000,
2276 0x00800000, 0x00400000, 0x00100000, 0x00200000 };
2277
2278
wdenk90e7e422002-12-04 23:39:58 +00002279/* -------------------------------------------------------------------- */
wdenkc6097192002-11-03 00:24:07 +00002280
wdenk0893c472003-05-20 14:25:27 +00002281#ifndef CONFIG_I82365
2282
wdenkc6097192002-11-03 00:24:07 +00002283static u_int m8xx_get_graycode(u_int size)
2284{
2285 u_int k;
2286
2287 for (k = 0; k < M8XX_SIZES_NO; k++) {
2288 if(m8xx_size_to_gray[k] == size)
2289 break;
2290 }
2291
2292 if((k == M8XX_SIZES_NO) || (m8xx_size_to_gray[k] == -1))
2293 k = -1;
2294
2295 return k;
2296}
2297
wdenk0893c472003-05-20 14:25:27 +00002298#endif /* CONFIG_I82365 */
2299
wdenk90e7e422002-12-04 23:39:58 +00002300/* -------------------------------------------------------------------- */
wdenkc6097192002-11-03 00:24:07 +00002301
2302#if 0
2303static u_int m8xx_get_speed(u_int ns, u_int is_io)
2304{
2305 u_int reg, clocks, psst, psl, psht;
2306
2307 if(!ns) {
2308
2309 /*
2310 * We get called with IO maps setup to 0ns
2311 * if not specified by the user.
2312 * They should be 255ns.
2313 */
2314
2315 if(is_io)
2316 ns = 255;
2317 else
2318 ns = 100; /* fast memory if 0 */
2319 }
2320
2321 /*
2322 * In PSST, PSL, PSHT fields we tell the controller
2323 * timing parameters in CLKOUT clock cycles.
2324 * CLKOUT is the same as GCLK2_50.
2325 */
2326
2327/* how we want to adjust the timing - in percent */
2328
2329#define ADJ 180 /* 80 % longer accesstime - to be sure */
2330
2331 clocks = ((M8XX_BUSFREQ / 1000) * ns) / 1000;
2332 clocks = (clocks * ADJ) / (100*1000);
2333
2334 if(clocks >= PCMCIA_BMT_LIMIT) {
2335 DEBUG(0, "Max access time limit reached\n");
2336 clocks = PCMCIA_BMT_LIMIT-1;
2337 }
2338
2339 psst = clocks / 7; /* setup time */
2340 psht = clocks / 7; /* hold time */
2341 psl = (clocks * 5) / 7; /* strobe length */
2342
2343 psst += clocks - (psst + psht + psl);
2344
2345 reg = psst << 12;
2346 reg |= psl << 7;
2347 reg |= psht << 16;
2348
2349 return reg;
2350}
2351#endif
2352
wdenk90e7e422002-12-04 23:39:58 +00002353/* -------------------------------------------------------------------- */
wdenkc6097192002-11-03 00:24:07 +00002354
2355#ifdef CONFIG_IDE_8xx_PCCARD
2356static void print_funcid (int func)
2357{
2358 puts (indent);
2359 switch (func) {
2360 case CISTPL_FUNCID_MULTI:
2361 puts (" Multi-Function");
2362 break;
2363 case CISTPL_FUNCID_MEMORY:
2364 puts (" Memory");
2365 break;
2366 case CISTPL_FUNCID_SERIAL:
2367 puts (" Serial Port");
2368 break;
2369 case CISTPL_FUNCID_PARALLEL:
2370 puts (" Parallel Port");
2371 break;
2372 case CISTPL_FUNCID_FIXED:
2373 puts (" Fixed Disk");
2374 break;
2375 case CISTPL_FUNCID_VIDEO:
2376 puts (" Video Adapter");
2377 break;
2378 case CISTPL_FUNCID_NETWORK:
2379 puts (" Network Adapter");
2380 break;
2381 case CISTPL_FUNCID_AIMS:
2382 puts (" AIMS Card");
2383 break;
2384 case CISTPL_FUNCID_SCSI:
2385 puts (" SCSI Adapter");
2386 break;
2387 default:
2388 puts (" Unknown");
2389 break;
2390 }
2391 puts (" Card\n");
2392}
2393#endif /* CONFIG_IDE_8xx_PCCARD */
2394
wdenk90e7e422002-12-04 23:39:58 +00002395/* -------------------------------------------------------------------- */
wdenkc6097192002-11-03 00:24:07 +00002396
2397#ifdef CONFIG_IDE_8xx_PCCARD
2398static void print_fixed (volatile uchar *p)
2399{
2400 if (p == NULL)
2401 return;
2402
2403 puts(indent);
2404
2405 switch (*p) {
2406 case CISTPL_FUNCE_IDE_IFACE:
2407 { uchar iface = *(p+2);
2408
2409 puts ((iface == CISTPL_IDE_INTERFACE) ? " IDE" : " unknown");
2410 puts (" interface ");
2411 break;
2412 }
2413 case CISTPL_FUNCE_IDE_MASTER:
2414 case CISTPL_FUNCE_IDE_SLAVE:
2415 { uchar f1 = *(p+2);
2416 uchar f2 = *(p+4);
2417
2418 puts ((f1 & CISTPL_IDE_SILICON) ? " [silicon]" : " [rotating]");
2419
2420 if (f1 & CISTPL_IDE_UNIQUE)
2421 puts (" [unique]");
2422
2423 puts ((f1 & CISTPL_IDE_DUAL) ? " [dual]" : " [single]");
2424
2425 if (f2 & CISTPL_IDE_HAS_SLEEP)
2426 puts (" [sleep]");
2427
2428 if (f2 & CISTPL_IDE_HAS_STANDBY)
2429 puts (" [standby]");
2430
2431 if (f2 & CISTPL_IDE_HAS_IDLE)
2432 puts (" [idle]");
2433
2434 if (f2 & CISTPL_IDE_LOW_POWER)
2435 puts (" [low power]");
2436
2437 if (f2 & CISTPL_IDE_REG_INHIBIT)
2438 puts (" [reg inhibit]");
2439
2440 if (f2 & CISTPL_IDE_HAS_INDEX)
2441 puts (" [index]");
2442
2443 if (f2 & CISTPL_IDE_IOIS16)
2444 puts (" [IOis16]");
2445
2446 break;
2447 }
2448 }
2449 putc ('\n');
2450}
2451#endif /* CONFIG_IDE_8xx_PCCARD */
2452
wdenk90e7e422002-12-04 23:39:58 +00002453/* -------------------------------------------------------------------- */
wdenkc6097192002-11-03 00:24:07 +00002454
2455#ifdef CONFIG_IDE_8xx_PCCARD
2456
2457#define MAX_IDENT_CHARS 64
2458#define MAX_IDENT_FIELDS 4
2459
2460static uchar *known_cards[] = {
2461 "ARGOSY PnPIDE D5",
2462 NULL
2463};
2464
2465static int identify (volatile uchar *p)
2466{
2467 uchar id_str[MAX_IDENT_CHARS];
2468 uchar data;
2469 uchar *t;
2470 uchar **card;
2471 int i, done;
2472
2473 if (p == NULL)
2474 return (0); /* Don't know */
2475
2476 t = id_str;
2477 done =0;
2478
2479 for (i=0; i<=4 && !done; ++i, p+=2) {
2480 while ((data = *p) != '\0') {
2481 if (data == 0xFF) {
2482 done = 1;
2483 break;
2484 }
2485 *t++ = data;
2486 if (t == &id_str[MAX_IDENT_CHARS-1]) {
2487 done = 1;
2488 break;
2489 }
2490 p += 2;
2491 }
2492 if (!done)
2493 *t++ = ' ';
2494 }
2495 *t = '\0';
2496 while (--t > id_str) {
2497 if (*t == ' ')
2498 *t = '\0';
2499 else
2500 break;
2501 }
2502 puts (id_str);
2503 putc ('\n');
2504
2505 for (card=known_cards; *card; ++card) {
2506 debug ("## Compare against \"%s\"\n", *card);
2507 if (strcmp(*card, id_str) == 0) { /* found! */
2508 debug ("## CARD FOUND ##\n");
2509 return (1);
2510 }
2511 }
2512
2513 return (0); /* don't know */
2514}
2515#endif /* CONFIG_IDE_8xx_PCCARD */
2516
wdenk90e7e422002-12-04 23:39:58 +00002517/* -------------------------------------------------------------------- */
wdenkc6097192002-11-03 00:24:07 +00002518
2519#endif /* CFG_CMD_PCMCIA || (CFG_CMD_IDE && CONFIG_IDE_8xx_PCCARD) */
wdenk57b2d802003-06-27 21:31:46 +00002520
2521/**************************************************/
2522
2523#if (CONFIG_COMMANDS & CFG_CMD_PCMCIA)
wdenkf287a242003-07-01 21:06:45 +00002524U_BOOT_CMD(
2525 pinit, 2, 1, do_pinit,
wdenk57b2d802003-06-27 21:31:46 +00002526 "pinit - PCMCIA sub-system\n",
2527 "on - power on PCMCIA socket\n"
2528 "pinit off - power off PCMCIA socket\n"
2529);
2530#endif