blob: 8c17859daa3e11b5c5431c0a4f52a8a3032b6ac8 [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>
wdenk444f22b2003-12-07 21:39:28 +000060#if defined(CONFIG_8xx)
wdenkc6097192002-11-03 00:24:07 +000061#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 */
wdenk67f13362003-12-27 19:24:54 +0000230#ifdef CONFIG_BMS2003
231 case 3: { /* map I/O window for 4xUART data/ctrl */
wdenk2f99a692004-01-04 22:51:12 +0000232 win->br += 0x40000;
wdenk67f13362003-12-27 19:24:54 +0000233 win->or = ( PCMCIA_BSIZE_256K
234 | PCMCIA_PPS_8
235 | PCMCIA_PRS_IO
236 | slotbit
237 | PCMCIA_PV
238 | CFG_PCMCIA_TIMING );
239 break;
240 }
241#endif /* CONFIG_BMS2003 */
wdenkc6097192002-11-03 00:24:07 +0000242 default: /* set to not valid */
243 win->or = 0;
244 break;
245 }
246
247 debug ("MemWin %d: PBR 0x%08lX POR %08lX\n",
248 i, win->br, win->or);
249 base += CFG_PCMCIA_MEM_SIZE;
250 ++win;
251 }
252
wdenk90e7e422002-12-04 23:39:58 +0000253 for (i=0, rc=0, slot=_slot_; i<PCMCIA_SOCKETS_NO; i++, slot = !slot) {
wdenk2029f4d2002-11-21 23:11:29 +0000254 /* turn off voltage */
255 if ((rc = voltage_set(slot, 0, 0)))
256 continue;
wdenk90e7e422002-12-04 23:39:58 +0000257
wdenk2029f4d2002-11-21 23:11:29 +0000258 /* Enable external hardware */
259 if ((rc = hardware_enable(slot)))
260 continue;
wdenk90e7e422002-12-04 23:39:58 +0000261
wdenkc6097192002-11-03 00:24:07 +0000262#ifdef CONFIG_IDE_8xx_PCCARD
wdenk2029f4d2002-11-21 23:11:29 +0000263 if ((rc = check_ide_device(i)))
264 continue;
wdenkc6097192002-11-03 00:24:07 +0000265#endif
wdenk2029f4d2002-11-21 23:11:29 +0000266 }
267 return (rc);
wdenkc6097192002-11-03 00:24:07 +0000268}
wdenke5d61c72003-05-18 11:30:09 +0000269#endif /* CONFIG_I82365 */
wdenkc6097192002-11-03 00:24:07 +0000270
wdenk90e7e422002-12-04 23:39:58 +0000271/* -------------------------------------------------------------------- */
wdenkc6097192002-11-03 00:24:07 +0000272
273#if (CONFIG_COMMANDS & CFG_CMD_PCMCIA)
274
wdenke5d61c72003-05-18 11:30:09 +0000275#ifdef CONFIG_I82365
276static int pcmcia_off (void)
277{
278 printf ("Disable PCMCIA " PCMCIA_SLOT_MSG "\n");
279
280 i82365_exit();
281
282 return 0;
283}
284#else
wdenkc6097192002-11-03 00:24:07 +0000285static int pcmcia_off (void)
286{
287 int i;
288 pcmcia_win_t *win;
289
290 printf ("Disable PCMCIA " PCMCIA_SLOT_MSG "\n");
291
292 /* clear interrupt state, and disable interrupts */
293 ((immap_t *)CFG_IMMR)->im_pcmcia.pcmc_pscr = PCMCIA_MASK(_slot_);
294 ((immap_t *)CFG_IMMR)->im_pcmcia.pcmc_per &= ~PCMCIA_MASK(_slot_);
295
296 /* turn off interrupt and disable CxOE */
297 PCMCIA_PGCRX(_slot_) = __MY_PCMCIA_GCRX_CXOE;
298
299 /* turn off memory windows */
300 win = (pcmcia_win_t *)(&((immap_t *)CFG_IMMR)->im_pcmcia.pcmc_pbr0);
301
302 for (i=0; i<PCMCIA_MEM_WIN_NO; ++i) {
303 /* disable memory window */
304 win->or = 0;
305 ++win;
306 }
307
308 /* turn off voltage */
309 voltage_set(_slot_, 0, 0);
310
311 /* disable external hardware */
312 printf ("Shutdown and Poweroff " PCMCIA_SLOT_MSG "\n");
313 hardware_disable(_slot_);
314 return 0;
315}
wdenke5d61c72003-05-18 11:30:09 +0000316#endif /* CONFIG_I82365 */
wdenkc6097192002-11-03 00:24:07 +0000317
318#endif /* CFG_CMD_PCMCIA */
319
wdenk90e7e422002-12-04 23:39:58 +0000320/* -------------------------------------------------------------------- */
wdenkc6097192002-11-03 00:24:07 +0000321
322#ifdef CONFIG_IDE_8xx_PCCARD
323
324#define MAX_TUPEL_SZ 512
325#define MAX_FEATURES 4
326
wdenk4fc95692003-02-28 00:49:47 +0000327int ide_devices_found;
wdenk2029f4d2002-11-21 23:11:29 +0000328static int check_ide_device (int slot)
wdenkc6097192002-11-03 00:24:07 +0000329{
330 volatile uchar *ident = NULL;
331 volatile uchar *feature_p[MAX_FEATURES];
wdenk2029f4d2002-11-21 23:11:29 +0000332 volatile uchar *p, *start, *addr;
wdenkc6097192002-11-03 00:24:07 +0000333 int n_features = 0;
334 uchar func_id = ~0;
335 uchar code, len;
336 ushort config_base = 0;
337 int found = 0;
338 int i;
339
wdenk90e7e422002-12-04 23:39:58 +0000340 addr = (volatile uchar *)(CFG_PCMCIA_MEM_ADDR +
341 CFG_PCMCIA_MEM_SIZE * (slot * 4));
wdenke7f34c62003-01-11 09:48:40 +0000342 debug ("PCMCIA MEM: %08lX\n", (ulong)addr);
wdenkc6097192002-11-03 00:24:07 +0000343
wdenk2029f4d2002-11-21 23:11:29 +0000344 start = p = (volatile uchar *) addr;
wdenkc6097192002-11-03 00:24:07 +0000345
346 while ((p - start) < MAX_TUPEL_SZ) {
347
348 code = *p; p += 2;
349
350 if (code == 0xFF) { /* End of chain */
351 break;
352 }
353
354 len = *p; p += 2;
355#if defined(DEBUG) && (DEBUG > 1)
356 { volatile uchar *q = p;
357 printf ("\nTuple code %02x length %d\n\tData:",
358 code, len);
359
360 for (i = 0; i < len; ++i) {
361 printf (" %02x", *q);
362 q+= 2;
363 }
364 }
365#endif /* DEBUG */
366 switch (code) {
367 case CISTPL_VERS_1:
368 ident = p + 4;
369 break;
370 case CISTPL_FUNCID:
371 /* Fix for broken SanDisk which may have 0x80 bit set */
372 func_id = *p & 0x7F;
373 break;
374 case CISTPL_FUNCE:
375 if (n_features < MAX_FEATURES)
376 feature_p[n_features++] = p;
377 break;
378 case CISTPL_CONFIG:
379 config_base = (*(p+6) << 8) + (*(p+4));
380 debug ("\n## Config_base = %04x ###\n", config_base);
381 default:
382 break;
383 }
384 p += 2 * len;
385 }
386
387 found = identify (ident);
388
389 if (func_id != ((uchar)~0)) {
390 print_funcid (func_id);
391
392 if (func_id == CISTPL_FUNCID_FIXED)
393 found = 1;
394 else
395 return (1); /* no disk drive */
396 }
397
398 for (i=0; i<n_features; ++i) {
399 print_fixed (feature_p[i]);
400 }
401
402 if (!found) {
403 printf ("unknown card type\n");
404 return (1);
405 }
406
wdenk4fc95692003-02-28 00:49:47 +0000407 ide_devices_found |= (1 << slot);
408
wdenkc6097192002-11-03 00:24:07 +0000409 /* set I/O area in config reg -> only valid for ARGOSY D5!!! */
wdenk2029f4d2002-11-21 23:11:29 +0000410 *((uchar *)(addr + config_base)) = 1;
wdenkc6097192002-11-03 00:24:07 +0000411
412 return (0);
413}
414#endif /* CONFIG_IDE_8xx_PCCARD */
415
wdenk90e7e422002-12-04 23:39:58 +0000416/* -------------------------------------------------------------------- */
wdenkc6097192002-11-03 00:24:07 +0000417
418
wdenk90e7e422002-12-04 23:39:58 +0000419/* -------------------------------------------------------------------- */
420/* board specific stuff: */
421/* voltage_set(), hardware_enable() and hardware_disable() */
422/* -------------------------------------------------------------------- */
wdenkc6097192002-11-03 00:24:07 +0000423
wdenk90e7e422002-12-04 23:39:58 +0000424/* -------------------------------------------------------------------- */
425/* RPX Boards from Embedded Planet */
426/* -------------------------------------------------------------------- */
wdenkc6097192002-11-03 00:24:07 +0000427
428#if defined(CONFIG_RPXCLASSIC) || defined(CONFIG_RPXLITE)
429
430/* The RPX boards seems to have it's bus monitor timeout set to 6*8 clocks.
431 * SYPCR is write once only, therefore must the slowest memory be faster
432 * than the bus monitor or we will get a machine check due to the bus timeout.
433 */
434
435#define PCMCIA_BOARD_MSG "RPX CLASSIC or RPX LITE"
436
437#undef PCMCIA_BMT_LIMIT
438#define PCMCIA_BMT_LIMIT (6*8)
439
440static int voltage_set(int slot, int vcc, int vpp)
441{
442 u_long reg = 0;
443
444 switch(vcc) {
445 case 0: break;
446 case 33: reg |= BCSR1_PCVCTL4; break;
447 case 50: reg |= BCSR1_PCVCTL5; break;
448 default: return 1;
449 }
450
451 switch(vpp) {
452 case 0: break;
453 case 33:
454 case 50:
455 if(vcc == vpp)
456 reg |= BCSR1_PCVCTL6;
457 else
458 return 1;
459 break;
460 case 120:
461 reg |= BCSR1_PCVCTL7;
462 default: return 1;
463 }
464
465 if(vcc == 120)
466 return 1;
467
468 /* first, turn off all power */
469
470 *((uint *)RPX_CSR_ADDR) &= ~(BCSR1_PCVCTL4 | BCSR1_PCVCTL5
471 | BCSR1_PCVCTL6 | BCSR1_PCVCTL7);
472
473 /* enable new powersettings */
474
475 *((uint *)RPX_CSR_ADDR) |= reg;
476
477 return 0;
478}
479
480#define socket_get(_slot_) PCMCIA_SOCKET_KEY_5V
481static int hardware_enable (int slot)
482{
483 return 0; /* No hardware to enable */
484}
485#if (CONFIG_COMMANDS & CFG_CMD_PCMCIA)
486static int hardware_disable(int slot)
487{
488 return 0; /* No hardware to disable */
489}
490#endif /* CFG_CMD_PCMCIA */
491#endif /* CONFIG_RPXCLASSIC */
492
wdenk90e7e422002-12-04 23:39:58 +0000493/* -------------------------------------------------------------------- */
494/* (F)ADS Boards from Motorola */
495/* -------------------------------------------------------------------- */
wdenkc6097192002-11-03 00:24:07 +0000496
497#if defined(CONFIG_ADS) || defined(CONFIG_FADS)
498
499#ifdef CONFIG_ADS
500#define PCMCIA_BOARD_MSG "ADS"
501#define PCMCIA_GLITCHY_CD /* My ADS board needs this */
502#else
503#define PCMCIA_BOARD_MSG "FADS"
504#endif
505
506static int voltage_set(int slot, int vcc, int vpp)
507{
508 u_long reg = 0;
509
510 switch(vpp) {
511 case 0: reg = 0; break;
512 case 50: reg = 1; break;
513 case 120: reg = 2; break;
514 default: return 1;
515 }
516
517 switch(vcc) {
518 case 0: reg = 0; break;
519#ifdef CONFIG_ADS
520 case 50: reg = BCSR1_PCCVCCON; break;
521#endif
522#ifdef CONFIG_FADS
523 case 33: reg = BCSR1_PCCVCC0 | BCSR1_PCCVCC1; break;
524 case 50: reg = BCSR1_PCCVCC1; break;
525#endif
526 default: return 1;
527 }
528
529 /* first, turn off all power */
530
531#ifdef CONFIG_ADS
532 *((uint *)BCSR1) |= BCSR1_PCCVCCON;
533#endif
534#ifdef CONFIG_FADS
535 *((uint *)BCSR1) &= ~(BCSR1_PCCVCC0 | BCSR1_PCCVCC1);
536#endif
537 *((uint *)BCSR1) &= ~BCSR1_PCCVPP_MASK;
538
539 /* enable new powersettings */
540
541#ifdef CONFIG_ADS
542 *((uint *)BCSR1) &= ~reg;
543#endif
544#ifdef CONFIG_FADS
545 *((uint *)BCSR1) |= reg;
546#endif
547
548 *((uint *)BCSR1) |= reg << 20;
549
550 return 0;
551}
552
553#define socket_get(_slot_) PCMCIA_SOCKET_KEY_5V
554
555static int hardware_enable(int slot)
556{
557 *((uint *)BCSR1) &= ~BCSR1_PCCEN;
558 return 0;
559}
560
561#if (CONFIG_COMMANDS & CFG_CMD_PCMCIA)
562static int hardware_disable(int slot)
563{
564 *((uint *)BCSR1) &= ~BCSR1_PCCEN;
565 return 0;
566}
567#endif /* CFG_CMD_PCMCIA */
568
569#endif /* (F)ADS */
570
wdenk90e7e422002-12-04 23:39:58 +0000571/* -------------------------------------------------------------------- */
572/* TQM8xxL Boards by TQ Components */
wdenkc8434db2003-03-26 06:55:25 +0000573/* SC8xx Boards by SinoVee Microsystems */
wdenk90e7e422002-12-04 23:39:58 +0000574/* -------------------------------------------------------------------- */
wdenkc6097192002-11-03 00:24:07 +0000575
wdenkc8434db2003-03-26 06:55:25 +0000576#if defined(CONFIG_TQM8xxL) || defined(CONFIG_SVM_SC8xx)
wdenkc6097192002-11-03 00:24:07 +0000577
wdenkc8434db2003-03-26 06:55:25 +0000578#if defined(CONFIG_TQM8xxL)
wdenkc6097192002-11-03 00:24:07 +0000579#define PCMCIA_BOARD_MSG "TQM8xxL"
wdenkc8434db2003-03-26 06:55:25 +0000580#endif
581#if defined(CONFIG_SVM_SC8xx)
582#define PCMCIA_BOARD_MSG "SC8xx"
583#endif
wdenkc6097192002-11-03 00:24:07 +0000584
585static int hardware_enable(int slot)
586{
587 volatile immap_t *immap;
588 volatile cpm8xx_t *cp;
589 volatile pcmconf8xx_t *pcmp;
590 volatile sysconf8xx_t *sysp;
591 uint reg, mask;
592
593 debug ("hardware_enable: " PCMCIA_BOARD_MSG " Slot %c\n", 'A'+slot);
594
595 udelay(10000);
596
597 immap = (immap_t *)CFG_IMMR;
598 sysp = (sysconf8xx_t *)(&(((immap_t *)CFG_IMMR)->im_siu_conf));
599 pcmp = (pcmconf8xx_t *)(&(((immap_t *)CFG_IMMR)->im_pcmcia));
600 cp = (cpm8xx_t *)(&(((immap_t *)CFG_IMMR)->im_cpm));
601
602 /*
603 * Configure SIUMCR to enable PCMCIA port B
604 * (VFLS[0:1] are not used for debugging, we connect FRZ# instead)
605 */
606 sysp->sc_siumcr &= ~SIUMCR_DBGC11; /* set DBGC to 00 */
607
608 /* clear interrupt state, and disable interrupts */
dzub02ed682003-10-19 21:43:26 +0000609 pcmp->pcmc_pscr = PCMCIA_MASK(slot);
610 pcmp->pcmc_per &= ~PCMCIA_MASK(slot);
wdenkc6097192002-11-03 00:24:07 +0000611
wdenkc6097192002-11-03 00:24:07 +0000612 /*
wdenk90e7e422002-12-04 23:39:58 +0000613 * Disable interrupts, DMA, and PCMCIA buffers
614 * (isolate the interface) and assert RESET signal
wdenkc6097192002-11-03 00:24:07 +0000615 */
616 debug ("Disable PCMCIA buffers and assert RESET\n");
wdenk90e7e422002-12-04 23:39:58 +0000617 reg = 0;
618 reg |= __MY_PCMCIA_GCRX_CXRESET; /* active high */
dzub02ed682003-10-19 21:43:26 +0000619#ifndef NSCU_OE_INV
wdenk90e7e422002-12-04 23:39:58 +0000620 reg |= __MY_PCMCIA_GCRX_CXOE; /* active low */
dzub02ed682003-10-19 21:43:26 +0000621#endif
622 PCMCIA_PGCRX(slot) = reg;
wdenkc6097192002-11-03 00:24:07 +0000623 udelay(500);
624
wdenk2f99a692004-01-04 22:51:12 +0000625#ifndef CONFIG_BMS2003
dzub02ed682003-10-19 21:43:26 +0000626#ifndef CONFIG_NSCU
wdenkc6097192002-11-03 00:24:07 +0000627 /*
628 * Configure Port C pins for
629 * 5 Volts Enable and 3 Volts enable
630 */
631 immap->im_ioport.iop_pcpar &= ~(0x0002 | 0x0004);
632 immap->im_ioport.iop_pcso &= ~(0x0002 | 0x0004);
633 /* remove all power */
634
635 immap->im_ioport.iop_pcdat &= ~(0x0002 | 0x0004);
dzub02ed682003-10-19 21:43:26 +0000636#endif
wdenk2f99a692004-01-04 22:51:12 +0000637#else /* CONFIG_BMS2003 */
638 /*
639 * Configure Port B pins for
640 * 5 Volts Enable and 3 Volts enable
641 */
642 immap->im_cpm.cp_pbpar &= ~(0x00000300);
643
644 /* remove all power */
645 immap->im_cpm.cp_pbdat |= 0x00000300;
646#endif /* CONFIG_BMS2003 */
wdenkc6097192002-11-03 00:24:07 +0000647
648 /*
649 * Make sure there is a card in the slot, then configure the interface.
650 */
651 udelay(10000);
652 debug ("[%d] %s: PIPR(%p)=0x%x\n",
653 __LINE__,__FUNCTION__,
654 &(pcmp->pcmc_pipr),pcmp->pcmc_pipr);
wdenk2f99a692004-01-04 22:51:12 +0000655#ifndef CONFIG_BMS2003
wdenk2029f4d2002-11-21 23:11:29 +0000656 if (pcmp->pcmc_pipr & (0x18000000 >> (slot << 4))) {
wdenk2f99a692004-01-04 22:51:12 +0000657#else
658 if (pcmp->pcmc_pipr & (0x10000000 >> (slot << 4))) {
659#endif /* CONFIG_BMS2003 */
wdenkc6097192002-11-03 00:24:07 +0000660 printf (" No Card found\n");
661 return (1);
662 }
663
664 /*
665 * Power On.
666 */
667 mask = PCMCIA_VS1(slot) | PCMCIA_VS2(slot);
668 reg = pcmp->pcmc_pipr;
669 debug ("PIPR: 0x%x ==> VS1=o%s, VS2=o%s\n",
670 reg,
671 (reg&PCMCIA_VS1(slot))?"n":"ff",
672 (reg&PCMCIA_VS2(slot))?"n":"ff");
dzub02ed682003-10-19 21:43:26 +0000673#ifndef CONFIG_NSCU
wdenkc6097192002-11-03 00:24:07 +0000674 if ((reg & mask) == mask) {
wdenk2f99a692004-01-04 22:51:12 +0000675#ifndef CONFIG_BMS2003
wdenkc6097192002-11-03 00:24:07 +0000676 immap->im_ioport.iop_pcdat |= 0x0004;
wdenk2f99a692004-01-04 22:51:12 +0000677#else
678 immap->im_cpm.cp_pbdat &= ~(0x0000100);
679#endif /* CONFIG_BMS2003 */
wdenkc6097192002-11-03 00:24:07 +0000680 puts (" 5.0V card found: ");
681 } else {
wdenk2f99a692004-01-04 22:51:12 +0000682#ifndef CONFIG_BMS2003
wdenkc6097192002-11-03 00:24:07 +0000683 immap->im_ioport.iop_pcdat |= 0x0002;
wdenk2f99a692004-01-04 22:51:12 +0000684#else
685 immap->im_cpm.cp_pbdat &= ~(0x0000200);
686#endif /* CONFIG_BMS2003 */
wdenkc6097192002-11-03 00:24:07 +0000687 puts (" 3.3V card found: ");
688 }
wdenk2f99a692004-01-04 22:51:12 +0000689#ifndef CONFIG_BMS2003
wdenk90e7e422002-12-04 23:39:58 +0000690 immap->im_ioport.iop_pcdir |= (0x0002 | 0x0004);
dzub02ed682003-10-19 21:43:26 +0000691#else
wdenk2f99a692004-01-04 22:51:12 +0000692 immap->im_cpm.cp_pbdir |= 0x00000300;
693#endif /* CONFIG_BMS2003 */
694#else
dzub02ed682003-10-19 21:43:26 +0000695 if ((reg & mask) == mask) {
696 puts (" 5.0V card found: ");
697 } else {
698 puts (" 3.3V card found: ");
699 }
700#endif
wdenkc6097192002-11-03 00:24:07 +0000701#if 0
702 /* VCC switch error flag, PCMCIA slot INPACK_ pin */
703 cp->cp_pbdir &= ~(0x0020 | 0x0010);
704 cp->cp_pbpar &= ~(0x0020 | 0x0010);
705 udelay(500000);
706#endif
707 udelay(1000);
708 debug ("Enable PCMCIA buffers and stop RESET\n");
dzub02ed682003-10-19 21:43:26 +0000709 reg = PCMCIA_PGCRX(slot);
wdenkc6097192002-11-03 00:24:07 +0000710 reg &= ~__MY_PCMCIA_GCRX_CXRESET; /* active high */
dzub02ed682003-10-19 21:43:26 +0000711#ifndef NSCU_OE_INV
wdenkc6097192002-11-03 00:24:07 +0000712 reg &= ~__MY_PCMCIA_GCRX_CXOE; /* active low */
dzub02ed682003-10-19 21:43:26 +0000713#else
714 reg |= __MY_PCMCIA_GCRX_CXOE; /* active low */
715#endif
716 PCMCIA_PGCRX(slot) = reg;
wdenkc6097192002-11-03 00:24:07 +0000717
718 udelay(250000); /* some cards need >150 ms to come up :-( */
719
720 debug ("# hardware_enable done\n");
721
722 return (0);
723}
724
725
wdenkc6097192002-11-03 00:24:07 +0000726#if (CONFIG_COMMANDS & CFG_CMD_PCMCIA)
727static int hardware_disable(int slot)
728{
729 volatile immap_t *immap;
730 volatile pcmconf8xx_t *pcmp;
731 u_long reg;
732
733 debug ("hardware_disable: " PCMCIA_BOARD_MSG " Slot %c\n", 'A'+slot);
734
735 immap = (immap_t *)CFG_IMMR;
736 pcmp = (pcmconf8xx_t *)(&(((immap_t *)CFG_IMMR)->im_pcmcia));
737
wdenk2f99a692004-01-04 22:51:12 +0000738#ifndef CONFIG_BMS2003
dzub02ed682003-10-19 21:43:26 +0000739#ifndef CONFIG_NSCU
wdenkc6097192002-11-03 00:24:07 +0000740 /* remove all power */
741 immap->im_ioport.iop_pcdat &= ~(0x0002 | 0x0004);
dzub02ed682003-10-19 21:43:26 +0000742#endif
wdenk2f99a692004-01-04 22:51:12 +0000743#else /* CONFIG_BMS2003 */
744 immap->im_cpm.cp_pbdat |= 0x00000300;
745#endif /* CONFIG_BMS2003 */
wdenkc6097192002-11-03 00:24:07 +0000746
wdenkc6097192002-11-03 00:24:07 +0000747 debug ("Disable PCMCIA buffers and assert RESET\n");
wdenk90e7e422002-12-04 23:39:58 +0000748 reg = 0;
wdenkc6097192002-11-03 00:24:07 +0000749 reg |= __MY_PCMCIA_GCRX_CXRESET; /* active high */
dzub02ed682003-10-19 21:43:26 +0000750#ifndef NSCU_OE_INV
wdenkc6097192002-11-03 00:24:07 +0000751 reg |= __MY_PCMCIA_GCRX_CXOE; /* active low */
dzub02ed682003-10-19 21:43:26 +0000752#endif
753 PCMCIA_PGCRX(slot) = reg;
wdenkc6097192002-11-03 00:24:07 +0000754
755 udelay(10000);
756
757 return (0);
758}
759#endif /* CFG_CMD_PCMCIA */
760
dzub02ed682003-10-19 21:43:26 +0000761#ifdef CONFIG_NSCU
wdenkc6097192002-11-03 00:24:07 +0000762static int voltage_set(int slot, int vcc, int vpp)
763{
dzub02ed682003-10-19 21:43:26 +0000764 return 0;
765}
766#else
767static int voltage_set(int slot, int vcc, int vpp)
768{
wdenkc6097192002-11-03 00:24:07 +0000769 volatile immap_t *immap;
770 volatile pcmconf8xx_t *pcmp;
771 u_long reg;
772
773 debug ("voltage_set: "
774 PCMCIA_BOARD_MSG
775 " Slot %c, Vcc=%d.%d, Vpp=%d.%d\n",
776 'A'+slot, vcc/10, vcc%10, vpp/10, vcc%10);
777
778 immap = (immap_t *)CFG_IMMR;
779 pcmp = (pcmconf8xx_t *)(&(((immap_t *)CFG_IMMR)->im_pcmcia));
780 /*
781 * Disable PCMCIA buffers (isolate the interface)
782 * and assert RESET signal
783 */
784 debug ("Disable PCMCIA buffers and assert RESET\n");
dzub02ed682003-10-19 21:43:26 +0000785 reg = PCMCIA_PGCRX(slot);
wdenk90e7e422002-12-04 23:39:58 +0000786 reg |= __MY_PCMCIA_GCRX_CXRESET; /* active high */
dzub02ed682003-10-19 21:43:26 +0000787#ifndef NSCU_OE_INV
wdenk90e7e422002-12-04 23:39:58 +0000788 reg |= __MY_PCMCIA_GCRX_CXOE; /* active low */
dzub02ed682003-10-19 21:43:26 +0000789#else
790 reg &= ~__MY_PCMCIA_GCRX_CXOE; /* active low */
791#endif
792 PCMCIA_PGCRX(slot) = reg;
wdenkc6097192002-11-03 00:24:07 +0000793 udelay(500);
794
wdenk2f99a692004-01-04 22:51:12 +0000795#ifndef CONFIG_BMS2003
wdenkc6097192002-11-03 00:24:07 +0000796 /*
797 * Configure Port C pins for
798 * 5 Volts Enable and 3 Volts enable,
799 * Turn off all power
800 */
801 debug ("PCMCIA power OFF\n");
802 immap->im_ioport.iop_pcpar &= ~(0x0002 | 0x0004);
803 immap->im_ioport.iop_pcso &= ~(0x0002 | 0x0004);
804 immap->im_ioport.iop_pcdat &= ~(0x0002 | 0x0004);
805
806 reg = 0;
807 switch(vcc) {
808 case 0: break;
809 case 33: reg |= 0x0002; break;
810 case 50: reg |= 0x0004; break;
811 default: goto done;
812 }
wdenk2f99a692004-01-04 22:51:12 +0000813#else /* CONFIG_BMS2003 */
814 /*
815 * Configure Port B pins for
816 * 5 Volts Enable and 3 Volts enable,
817 * Turn off all power
818 */
819 debug ("PCMCIA power OFF\n");
820 immap->im_cpm.cp_pbpar &= ~(0x00000300);
821 /* remove all power */
822
823 immap->im_cpm.cp_pbdat |= 0x00000300;
824
825 reg = 0;
826 switch(vcc) {
827 case 0: break;
828 case 33: reg |= 0x00000200; break;
829 case 50: reg |= 0x00000100; break;
830 default: goto done;
831}
832#endif /* CONFIG_BMS2003 */
wdenkc6097192002-11-03 00:24:07 +0000833
834 /* Checking supported voltages */
835
836 debug ("PIPR: 0x%x --> %s\n",
837 pcmp->pcmc_pipr,
838 (pcmp->pcmc_pipr & 0x00008000) ? "only 5 V" : "can do 3.3V");
839
wdenk2f99a692004-01-04 22:51:12 +0000840#ifndef CONFIG_BMS2003
wdenkc6097192002-11-03 00:24:07 +0000841 immap->im_ioport.iop_pcdat |= reg;
wdenk90e7e422002-12-04 23:39:58 +0000842 immap->im_ioport.iop_pcdir |= (0x0002 | 0x0004);
wdenk2f99a692004-01-04 22:51:12 +0000843#else
844 immap->im_cpm.cp_pbdat &= !reg;
845 immap->im_cpm.cp_pbdir |= 0x00000300;
846#endif /* CONFIG_BMS2003 */
wdenkc6097192002-11-03 00:24:07 +0000847 if (reg) {
wdenk2f99a692004-01-04 22:51:12 +0000848#ifndef CONFIG_BMS2003
wdenkc6097192002-11-03 00:24:07 +0000849 debug ("PCMCIA powered at %sV\n",
850 (reg&0x0004) ? "5.0" : "3.3");
wdenk2f99a692004-01-04 22:51:12 +0000851#else
852 debug ("PCMCIA powered at %sV\n",
853 (reg&0x00000200) ? "5.0" : "3.3");
854#endif /* CONFIG_BMS2003 */
wdenkc6097192002-11-03 00:24:07 +0000855 } else {
856 debug ("PCMCIA powered down\n");
857 }
858
859done:
860 debug ("Enable PCMCIA buffers and stop RESET\n");
dzub02ed682003-10-19 21:43:26 +0000861 reg = PCMCIA_PGCRX(slot);
wdenkc6097192002-11-03 00:24:07 +0000862 reg &= ~__MY_PCMCIA_GCRX_CXRESET; /* active high */
dzub02ed682003-10-19 21:43:26 +0000863#ifndef NSCU_OE_INV
wdenkc6097192002-11-03 00:24:07 +0000864 reg &= ~__MY_PCMCIA_GCRX_CXOE; /* active low */
dzub02ed682003-10-19 21:43:26 +0000865#else
866 reg |= __MY_PCMCIA_GCRX_CXOE; /* active low */
867#endif
868 PCMCIA_PGCRX(slot) = reg;
wdenkc6097192002-11-03 00:24:07 +0000869 udelay(500);
870
871 debug ("voltage_set: " PCMCIA_BOARD_MSG " Slot %c, DONE\n",
872 slot+'A');
873 return (0);
874}
dzub02ed682003-10-19 21:43:26 +0000875#endif
wdenkc6097192002-11-03 00:24:07 +0000876
877#endif /* TQM8xxL */
878
879
wdenk90e7e422002-12-04 23:39:58 +0000880/* -------------------------------------------------------------------- */
881/* LWMON Board */
882/* -------------------------------------------------------------------- */
wdenkc6097192002-11-03 00:24:07 +0000883
884#if defined(CONFIG_LWMON)
885
886#define PCMCIA_BOARD_MSG "LWMON"
887
888/* #define's for MAX1604 Power Switch */
889#define MAX1604_OP_SUS 0x80
890#define MAX1604_VCCBON 0x40
891#define MAX1604_VCC_35 0x20
892#define MAX1604_VCCBHIZ 0x10
893#define MAX1604_VPPBON 0x08
894#define MAX1604_VPPBPBPGM 0x04
895#define MAX1604_VPPBHIZ 0x02
896/* reserved 0x01 */
897
898static int hardware_enable(int slot)
899{
900 volatile immap_t *immap;
901 volatile cpm8xx_t *cp;
902 volatile pcmconf8xx_t *pcmp;
903 volatile sysconf8xx_t *sysp;
904 uint reg, mask;
905 uchar val;
906
907
908 debug ("hardware_enable: " PCMCIA_BOARD_MSG " Slot %c\n", 'A'+slot);
909
910 /* Switch on PCMCIA port in PIC register 0x60 */
911 reg = pic_read (0x60);
912 debug ("[%d] PIC read: reg_60 = 0x%02x\n", __LINE__, reg);
913 reg &= ~0x10;
wdenk90e7e422002-12-04 23:39:58 +0000914 /* reg |= 0x08; Vpp not needed */
wdenkc6097192002-11-03 00:24:07 +0000915 pic_write (0x60, reg);
916#ifdef DEBUG
917 reg = pic_read (0x60);
918 printf ("[%d] PIC read: reg_60 = 0x%02x\n", __LINE__, reg);
919#endif
920 udelay(10000);
921
922 immap = (immap_t *)CFG_IMMR;
923 sysp = (sysconf8xx_t *)(&(((immap_t *)CFG_IMMR)->im_siu_conf));
924 pcmp = (pcmconf8xx_t *)(&(((immap_t *)CFG_IMMR)->im_pcmcia));
925 cp = (cpm8xx_t *)(&(((immap_t *)CFG_IMMR)->im_cpm));
926
927 /*
928 * Configure SIUMCR to enable PCMCIA port B
929 * (VFLS[0:1] are not used for debugging, we connect FRZ# instead)
930 */
931 sysp->sc_siumcr &= ~SIUMCR_DBGC11; /* set DBGC to 00 */
932
933 /* clear interrupt state, and disable interrupts */
934 pcmp->pcmc_pscr = PCMCIA_MASK(_slot_);
935 pcmp->pcmc_per &= ~PCMCIA_MASK(_slot_);
936
wdenkc6097192002-11-03 00:24:07 +0000937 /*
wdenk90e7e422002-12-04 23:39:58 +0000938 * Disable interrupts, DMA, and PCMCIA buffers
939 * (isolate the interface) and assert RESET signal
wdenkc6097192002-11-03 00:24:07 +0000940 */
941 debug ("Disable PCMCIA buffers and assert RESET\n");
wdenk90e7e422002-12-04 23:39:58 +0000942 reg = 0;
943 reg |= __MY_PCMCIA_GCRX_CXRESET; /* active high */
944 reg |= __MY_PCMCIA_GCRX_CXOE; /* active low */
wdenkc6097192002-11-03 00:24:07 +0000945 PCMCIA_PGCRX(_slot_) = reg;
946 udelay(500);
947
948 /*
949 * Make sure there is a card in the slot, then configure the interface.
950 */
951 udelay(10000);
952 debug ("[%d] %s: PIPR(%p)=0x%x\n",
953 __LINE__,__FUNCTION__,
954 &(pcmp->pcmc_pipr),pcmp->pcmc_pipr);
wdenk2029f4d2002-11-21 23:11:29 +0000955 if (pcmp->pcmc_pipr & (0x18000000 >> (slot << 4))) {
wdenkc6097192002-11-03 00:24:07 +0000956 printf (" No Card found\n");
957 return (1);
958 }
959
960 /*
961 * Power On.
962 */
963 mask = PCMCIA_VS1(slot) | PCMCIA_VS2(slot);
964 reg = pcmp->pcmc_pipr;
965 debug ("PIPR: 0x%x ==> VS1=o%s, VS2=o%s\n",
966 reg,
967 (reg&PCMCIA_VS1(slot))?"n":"ff",
968 (reg&PCMCIA_VS2(slot))?"n":"ff");
969 if ((reg & mask) == mask) {
970 val = 0; /* VCCB3/5 = 0 ==> use Vx = 5.0 V */
971 puts (" 5.0V card found: ");
972 } else {
973 val = MAX1604_VCC_35; /* VCCB3/5 = 1 ==> use Vy = 3.3 V */
974 puts (" 3.3V card found: ");
975 }
976
977 /* switch VCC on */
wdenk90e7e422002-12-04 23:39:58 +0000978 val |= MAX1604_OP_SUS | MAX1604_VCCBON;
wdenkc6097192002-11-03 00:24:07 +0000979 i2c_init (CFG_I2C_SPEED, CFG_I2C_SLAVE);
980 i2c_write (CFG_I2C_POWER_A_ADDR, 0, 0, &val, 1);
981
982 udelay(500000);
983
984 debug ("Enable PCMCIA buffers and stop RESET\n");
985 reg = PCMCIA_PGCRX(_slot_);
986 reg &= ~__MY_PCMCIA_GCRX_CXRESET; /* active high */
987 reg &= ~__MY_PCMCIA_GCRX_CXOE; /* active low */
988 PCMCIA_PGCRX(_slot_) = reg;
989
990 udelay(250000); /* some cards need >150 ms to come up :-( */
991
992 debug ("# hardware_enable done\n");
993
994 return (0);
995}
996
997
wdenkc6097192002-11-03 00:24:07 +0000998#if (CONFIG_COMMANDS & CFG_CMD_PCMCIA)
999static int hardware_disable(int slot)
1000{
1001 volatile immap_t *immap;
1002 volatile pcmconf8xx_t *pcmp;
1003 u_long reg;
1004 uchar val;
1005
1006 debug ("hardware_disable: " PCMCIA_BOARD_MSG " Slot %c\n", 'A'+slot);
1007
1008 immap = (immap_t *)CFG_IMMR;
1009 pcmp = (pcmconf8xx_t *)(&(((immap_t *)CFG_IMMR)->im_pcmcia));
1010
1011 /* remove all power, put output in high impedance state */
1012 val = MAX1604_VCCBHIZ | MAX1604_VPPBHIZ;
1013 i2c_init (CFG_I2C_SPEED, CFG_I2C_SLAVE);
1014 i2c_write (CFG_I2C_POWER_A_ADDR, 0, 0, &val, 1);
1015
1016 /* Configure PCMCIA General Control Register */
wdenkc6097192002-11-03 00:24:07 +00001017 debug ("Disable PCMCIA buffers and assert RESET\n");
wdenk90e7e422002-12-04 23:39:58 +00001018 reg = 0;
wdenkc6097192002-11-03 00:24:07 +00001019 reg |= __MY_PCMCIA_GCRX_CXRESET; /* active high */
1020 reg |= __MY_PCMCIA_GCRX_CXOE; /* active low */
1021 PCMCIA_PGCRX(_slot_) = reg;
1022
1023 /* Switch off PCMCIA port in PIC register 0x60 */
1024 reg = pic_read (0x60);
1025 debug ("[%d] PIC read: reg_60 = 0x%02x\n", __LINE__, reg);
1026 reg |= 0x10;
1027 reg &= ~0x08;
1028 pic_write (0x60, reg);
1029#ifdef DEBUG
1030 reg = pic_read (0x60);
1031 printf ("[%d] PIC read: reg_60 = 0x%02x\n", __LINE__, reg);
1032#endif
1033 udelay(10000);
1034
1035 return (0);
1036}
1037#endif /* CFG_CMD_PCMCIA */
1038
1039
wdenkc6097192002-11-03 00:24:07 +00001040static int voltage_set(int slot, int vcc, int vpp)
1041{
1042 volatile immap_t *immap;
1043 volatile pcmconf8xx_t *pcmp;
1044 u_long reg;
1045 uchar val;
1046
1047 debug ("voltage_set: "
1048 PCMCIA_BOARD_MSG
1049 " Slot %c, Vcc=%d.%d, Vpp=%d.%d\n",
1050 'A'+slot, vcc/10, vcc%10, vpp/10, vcc%10);
1051
1052 immap = (immap_t *)CFG_IMMR;
1053 pcmp = (pcmconf8xx_t *)(&(((immap_t *)CFG_IMMR)->im_pcmcia));
1054 /*
1055 * Disable PCMCIA buffers (isolate the interface)
1056 * and assert RESET signal
1057 */
1058 debug ("Disable PCMCIA buffers and assert RESET\n");
wdenk90e7e422002-12-04 23:39:58 +00001059 reg = PCMCIA_PGCRX(_slot_);
1060 reg |= __MY_PCMCIA_GCRX_CXRESET; /* active high */
1061 reg |= __MY_PCMCIA_GCRX_CXOE; /* active low */
wdenkc6097192002-11-03 00:24:07 +00001062 PCMCIA_PGCRX(_slot_) = reg;
1063 udelay(500);
1064
1065 /*
1066 * Turn off all power (switch to high impedance)
1067 */
1068 debug ("PCMCIA power OFF\n");
1069 val = MAX1604_VCCBHIZ | MAX1604_VPPBHIZ;
1070 i2c_init (CFG_I2C_SPEED, CFG_I2C_SLAVE);
1071 i2c_write (CFG_I2C_POWER_A_ADDR, 0, 0, &val, 1);
1072
1073 val = 0;
1074 switch(vcc) {
1075 case 0: break;
1076 case 33: val = MAX1604_VCC_35; break;
1077 case 50: break;
1078 default: goto done;
1079 }
1080
1081 /* Checking supported voltages */
1082
1083 debug ("PIPR: 0x%x --> %s\n",
1084 pcmp->pcmc_pipr,
1085 (pcmp->pcmc_pipr & 0x00008000) ? "only 5 V" : "can do 3.3V");
1086
1087 i2c_write (CFG_I2C_POWER_A_ADDR, 0, 0, &val, 1);
1088 if (val) {
1089 debug ("PCMCIA powered at %sV\n",
1090 (val & MAX1604_VCC_35) ? "3.3" : "5.0");
1091 } else {
1092 debug ("PCMCIA powered down\n");
1093 }
1094
1095done:
1096 debug ("Enable PCMCIA buffers and stop RESET\n");
1097 reg = PCMCIA_PGCRX(_slot_);
1098 reg &= ~__MY_PCMCIA_GCRX_CXRESET; /* active high */
1099 reg &= ~__MY_PCMCIA_GCRX_CXOE; /* active low */
1100 PCMCIA_PGCRX(_slot_) = reg;
1101 udelay(500);
1102
1103 debug ("voltage_set: " PCMCIA_BOARD_MSG " Slot %c, DONE\n",
1104 slot+'A');
1105 return (0);
1106}
1107
1108#endif /* LWMON */
1109
wdenk90e7e422002-12-04 23:39:58 +00001110/* -------------------------------------------------------------------- */
1111/* GTH board by Corelatus AB */
1112/* -------------------------------------------------------------------- */
wdenkc6097192002-11-03 00:24:07 +00001113#if defined(CONFIG_GTH)
1114
1115#define PCMCIA_BOARD_MSG "GTH COMPACT FLASH"
1116
wdenk90e7e422002-12-04 23:39:58 +00001117static int voltage_set (int slot, int vcc, int vpp)
1118{ /* Do nothing */
1119 return 0;
wdenkc6097192002-11-03 00:24:07 +00001120}
1121
1122static int hardware_enable (int slot)
1123{
wdenk90e7e422002-12-04 23:39:58 +00001124 volatile immap_t *immap;
1125 volatile cpm8xx_t *cp;
1126 volatile pcmconf8xx_t *pcmp;
1127 volatile sysconf8xx_t *sysp;
1128 uint reg, mask;
wdenkc6097192002-11-03 00:24:07 +00001129
wdenk90e7e422002-12-04 23:39:58 +00001130 debug ("hardware_enable: GTH Slot %c\n", 'A' + slot);
wdenkc6097192002-11-03 00:24:07 +00001131
wdenk90e7e422002-12-04 23:39:58 +00001132 immap = (immap_t *) CFG_IMMR;
1133 sysp = (sysconf8xx_t *) (&(((immap_t *) CFG_IMMR)->im_siu_conf));
1134 pcmp = (pcmconf8xx_t *) (&(((immap_t *) CFG_IMMR)->im_pcmcia));
1135 cp = (cpm8xx_t *) (&(((immap_t *) CFG_IMMR)->im_cpm));
wdenkc6097192002-11-03 00:24:07 +00001136
wdenk90e7e422002-12-04 23:39:58 +00001137 /* clear interrupt state, and disable interrupts */
1138 pcmp->pcmc_pscr = PCMCIA_MASK (_slot_);
1139 pcmp->pcmc_per &= ~PCMCIA_MASK (_slot_);
wdenkc6097192002-11-03 00:24:07 +00001140
wdenk90e7e422002-12-04 23:39:58 +00001141 /*
1142 * Disable interrupts, DMA, and PCMCIA buffers
1143 * (isolate the interface) and assert RESET signal
1144 */
1145 debug ("Disable PCMCIA buffers and assert RESET\n");
1146 reg = 0;
1147 reg |= __MY_PCMCIA_GCRX_CXRESET; /* active high */
1148 reg |= __MY_PCMCIA_GCRX_CXOE; /* active low */
1149 PCMCIA_PGCRX (_slot_) = reg;
1150 udelay (500);
wdenkc6097192002-11-03 00:24:07 +00001151
wdenk90e7e422002-12-04 23:39:58 +00001152 /*
1153 * Make sure there is a card in the slot,
1154 * then configure the interface.
1155 */
1156 udelay (10000);
1157 debug ("[%d] %s: PIPR(%p)=0x%x\n",
1158 __LINE__, __FUNCTION__,
1159 &(pcmp->pcmc_pipr), pcmp->pcmc_pipr);
1160 if (pcmp->pcmc_pipr & 0x98000000) {
1161 printf (" No Card found\n");
1162 return (1);
1163 }
wdenkc6097192002-11-03 00:24:07 +00001164
wdenk90e7e422002-12-04 23:39:58 +00001165 mask = PCMCIA_VS1 (slot) | PCMCIA_VS2 (slot);
1166 reg = pcmp->pcmc_pipr;
1167 debug ("PIPR: 0x%x ==> VS1=o%s, VS2=o%s\n",
1168 reg,
1169 (reg & PCMCIA_VS1 (slot)) ? "n" : "ff",
1170 (reg & PCMCIA_VS2 (slot)) ? "n" : "ff");
wdenkc6097192002-11-03 00:24:07 +00001171
wdenk90e7e422002-12-04 23:39:58 +00001172 debug ("Enable PCMCIA buffers and stop RESET\n");
1173 reg = PCMCIA_PGCRX (_slot_);
1174 reg &= ~__MY_PCMCIA_GCRX_CXRESET; /* active high */
1175 reg &= ~__MY_PCMCIA_GCRX_CXOE; /* active low */
1176 PCMCIA_PGCRX (_slot_) = reg;
wdenkc6097192002-11-03 00:24:07 +00001177
wdenk90e7e422002-12-04 23:39:58 +00001178 udelay (250000); /* some cards need >150 ms to come up :-( */
wdenkc6097192002-11-03 00:24:07 +00001179
wdenk90e7e422002-12-04 23:39:58 +00001180 debug ("# hardware_enable done\n");
wdenkc6097192002-11-03 00:24:07 +00001181
wdenk90e7e422002-12-04 23:39:58 +00001182 return 0;
wdenkc6097192002-11-03 00:24:07 +00001183}
1184#if (CONFIG_COMMANDS & CFG_CMD_PCMCIA)
1185static int hardware_disable(int slot)
1186{
1187 return 0; /* No hardware to disable */
1188}
1189#endif /* CFG_CMD_PCMCIA */
1190#endif /* CONFIG_GTH */
1191
wdenk90e7e422002-12-04 23:39:58 +00001192/* -------------------------------------------------------------------- */
1193/* ICU862 Boards by Cambridge Broadband Ltd. */
1194/* -------------------------------------------------------------------- */
wdenkc6097192002-11-03 00:24:07 +00001195
1196#if defined(CONFIG_ICU862)
1197
1198#define PCMCIA_BOARD_MSG "ICU862"
1199
1200static void cfg_port_B (void);
1201
1202static int hardware_enable(int slot)
1203{
1204 volatile immap_t *immap;
1205 volatile cpm8xx_t *cp;
1206 volatile pcmconf8xx_t *pcmp;
1207 volatile sysconf8xx_t *sysp;
1208 uint reg, pipr, mask;
1209 int i;
1210
1211 debug ("hardware_enable: " PCMCIA_BOARD_MSG " Slot %c\n", 'A'+slot);
1212
1213 udelay(10000);
1214
1215 immap = (immap_t *)CFG_IMMR;
1216 sysp = (sysconf8xx_t *)(&(((immap_t *)CFG_IMMR)->im_siu_conf));
1217 pcmp = (pcmconf8xx_t *)(&(((immap_t *)CFG_IMMR)->im_pcmcia));
1218 cp = (cpm8xx_t *)(&(((immap_t *)CFG_IMMR)->im_cpm));
1219
1220 /* Configure Port B for TPS2205 PC-Card Power-Interface Switch */
1221 cfg_port_B ();
1222
1223 /*
1224 * Configure SIUMCR to enable PCMCIA port B
1225 * (VFLS[0:1] are not used for debugging, we connect FRZ# instead)
1226 */
1227 sysp->sc_siumcr &= ~SIUMCR_DBGC11; /* set DBGC to 00 */
1228
1229 /* clear interrupt state, and disable interrupts */
1230 pcmp->pcmc_pscr = PCMCIA_MASK(_slot_);
1231 pcmp->pcmc_per &= ~PCMCIA_MASK(_slot_);
1232
wdenkc6097192002-11-03 00:24:07 +00001233 /*
wdenk90e7e422002-12-04 23:39:58 +00001234 * Disable interrupts, DMA, and PCMCIA buffers
1235 * (isolate the interface) and assert RESET signal
wdenkc6097192002-11-03 00:24:07 +00001236 */
1237 debug ("Disable PCMCIA buffers and assert RESET\n");
wdenk90e7e422002-12-04 23:39:58 +00001238 reg = 0;
1239 reg |= __MY_PCMCIA_GCRX_CXRESET; /* active high */
1240 reg |= __MY_PCMCIA_GCRX_CXOE; /* active low */
wdenkc6097192002-11-03 00:24:07 +00001241 PCMCIA_PGCRX(_slot_) = reg;
1242 udelay(500);
1243
1244 /*
1245 * Make sure there is a card in the slot, then configure the interface.
1246 */
1247 udelay(10000);
1248 debug ("[%d] %s: PIPR(%p)=0x%x\n",
1249 __LINE__,__FUNCTION__,
1250 &(pcmp->pcmc_pipr),pcmp->pcmc_pipr);
wdenk2029f4d2002-11-21 23:11:29 +00001251 if (pcmp->pcmc_pipr & (0x18000000 >> (slot << 4))) {
wdenkc6097192002-11-03 00:24:07 +00001252 printf (" No Card found\n");
1253 return (1);
1254 }
1255
1256 /*
1257 * Power On: Set VAVCC to 3.3V or 5V, set VAVPP to Hi-Z
1258 */
1259 mask = PCMCIA_VS1(slot) | PCMCIA_VS2(slot);
1260 pipr = pcmp->pcmc_pipr;
1261 debug ("PIPR: 0x%x ==> VS1=o%s, VS2=o%s\n",
1262 pipr,
1263 (reg&PCMCIA_VS1(slot))?"n":"ff",
1264 (reg&PCMCIA_VS2(slot))?"n":"ff");
1265
1266 reg = cp->cp_pbdat;
1267 if ((pipr & mask) == mask) {
wdenk90e7e422002-12-04 23:39:58 +00001268 reg |= (TPS2205_VPP_PGM | TPS2205_VPP_VCC | /* VAVPP => Hi-Z */
1269 TPS2205_VCC3); /* 3V off */
wdenkc6097192002-11-03 00:24:07 +00001270 reg &= ~(TPS2205_VCC5); /* 5V on */
1271 puts (" 5.0V card found: ");
1272 } else {
wdenk90e7e422002-12-04 23:39:58 +00001273 reg |= (TPS2205_VPP_PGM | TPS2205_VPP_VCC | /* VAVPP => Hi-Z */
1274 TPS2205_VCC5); /* 5V off */
wdenkc6097192002-11-03 00:24:07 +00001275 reg &= ~(TPS2205_VCC3); /* 3V on */
1276 puts (" 3.3V card found: ");
1277 }
1278
1279 debug ("\nPB DAT: %08x -> 3.3V %s 5.0V %s VPP_PGM %s VPP_VCC %s\n",
1280 reg,
1281 (reg & TPS2205_VCC3) ? "off" : "on",
1282 (reg & TPS2205_VCC5) ? "off" : "on",
1283 (reg & TPS2205_VPP_PGM) ? "off" : "on",
1284 (reg & TPS2205_VPP_VCC) ? "off" : "on" );
1285
1286 cp->cp_pbdat = reg;
1287
1288 /* Wait 500 ms; use this to check for over-current */
1289 for (i=0; i<5000; ++i) {
1290 if ((cp->cp_pbdat & TPS2205_OC) == 0) {
1291 printf (" *** Overcurrent - Safety shutdown ***\n");
1292 cp->cp_pbdat &= ~(TPS2205_SHDN);
1293 return (1);
1294 }
1295 udelay (100);
1296 }
1297
1298 debug ("Enable PCMCIA buffers and stop RESET\n");
1299 reg = PCMCIA_PGCRX(_slot_);
1300 reg &= ~__MY_PCMCIA_GCRX_CXRESET; /* active high */
1301 reg &= ~__MY_PCMCIA_GCRX_CXOE; /* active low */
1302 PCMCIA_PGCRX(_slot_) = reg;
1303
1304 udelay(250000); /* some cards need >150 ms to come up :-( */
1305
1306 debug ("# hardware_enable done\n");
1307
1308 return (0);
1309}
1310
1311
wdenkc6097192002-11-03 00:24:07 +00001312#if (CONFIG_COMMANDS & CFG_CMD_PCMCIA)
1313static int hardware_disable(int slot)
1314{
1315 volatile immap_t *immap;
1316 volatile cpm8xx_t *cp;
1317 volatile pcmconf8xx_t *pcmp;
1318 u_long reg;
1319
1320 debug ("hardware_disable: " PCMCIA_BOARD_MSG " Slot %c\n", 'A'+slot);
1321
1322 immap = (immap_t *)CFG_IMMR;
1323 cp = (cpm8xx_t *)(&(((immap_t *)CFG_IMMR)->im_cpm));
1324 pcmp = (pcmconf8xx_t *)(&(((immap_t *)CFG_IMMR)->im_pcmcia));
1325
1326 /* Shut down */
1327 cp->cp_pbdat &= ~(TPS2205_SHDN);
1328
1329 /* Configure PCMCIA General Control Register */
wdenkc6097192002-11-03 00:24:07 +00001330 debug ("Disable PCMCIA buffers and assert RESET\n");
wdenk90e7e422002-12-04 23:39:58 +00001331 reg = 0;
wdenkc6097192002-11-03 00:24:07 +00001332 reg |= __MY_PCMCIA_GCRX_CXRESET; /* active high */
1333 reg |= __MY_PCMCIA_GCRX_CXOE; /* active low */
1334 PCMCIA_PGCRX(_slot_) = reg;
1335
1336 udelay(10000);
1337
1338 return (0);
1339}
1340#endif /* CFG_CMD_PCMCIA */
1341
1342
wdenkc6097192002-11-03 00:24:07 +00001343static int voltage_set(int slot, int vcc, int vpp)
1344{
1345 volatile immap_t *immap;
1346 volatile cpm8xx_t *cp;
1347 volatile pcmconf8xx_t *pcmp;
1348 u_long reg;
1349
1350 debug ("voltage_set: "
1351 PCMCIA_BOARD_MSG
1352 " Slot %c, Vcc=%d.%d, Vpp=%d.%d\n",
1353 'A'+slot, vcc/10, vcc%10, vpp/10, vcc%10);
1354
1355 immap = (immap_t *)CFG_IMMR;
1356 cp = (cpm8xx_t *)(&(((immap_t *)CFG_IMMR)->im_cpm));
1357 pcmp = (pcmconf8xx_t *)(&(((immap_t *)CFG_IMMR)->im_pcmcia));
1358 /*
1359 * Disable PCMCIA buffers (isolate the interface)
1360 * and assert RESET signal
1361 */
1362 debug ("Disable PCMCIA buffers and assert RESET\n");
wdenk90e7e422002-12-04 23:39:58 +00001363 reg = PCMCIA_PGCRX(_slot_);
1364 reg |= __MY_PCMCIA_GCRX_CXRESET; /* active high */
1365 reg |= __MY_PCMCIA_GCRX_CXOE; /* active low */
wdenkc6097192002-11-03 00:24:07 +00001366 PCMCIA_PGCRX(_slot_) = reg;
1367 udelay(500);
1368
1369 /*
1370 * Configure Port C pins for
1371 * 5 Volts Enable and 3 Volts enable,
1372 * Turn all power pins to Hi-Z
1373 */
1374 debug ("PCMCIA power OFF\n");
1375 cfg_port_B (); /* Enables switch, but all in Hi-Z */
1376
1377 reg = cp->cp_pbdat;
1378
1379 switch(vcc) {
1380 case 0: break; /* Switch off */
1381 case 33: reg &= ~TPS2205_VCC3; break; /* Switch on 3.3V */
1382 case 50: reg &= ~TPS2205_VCC5; break; /* Switch on 5.0V */
1383 default: goto done;
1384 }
1385
1386 /* Checking supported voltages */
1387
1388 debug ("PIPR: 0x%x --> %s\n",
1389 pcmp->pcmc_pipr,
1390 (pcmp->pcmc_pipr & 0x00008000) ? "only 5 V" : "can do 3.3V");
1391
1392 cp->cp_pbdat = reg;
1393
1394#ifdef DEBUG
1395 {
1396 char *s;
1397
1398 if ((reg & TPS2205_VCC3) == 0) {
1399 s = "at 3.3V";
1400 } else if ((reg & TPS2205_VCC5) == 0) {
1401 s = "at 5.0V";
1402 } else {
1403 s = "down";
1404 }
1405 printf ("PCMCIA powered %s\n", s);
1406 }
1407#endif
1408
1409done:
1410 debug ("Enable PCMCIA buffers and stop RESET\n");
1411 reg = PCMCIA_PGCRX(_slot_);
1412 reg &= ~__MY_PCMCIA_GCRX_CXRESET; /* active high */
1413 reg &= ~__MY_PCMCIA_GCRX_CXOE; /* active low */
1414 PCMCIA_PGCRX(_slot_) = reg;
1415 udelay(500);
1416
1417 debug ("voltage_set: " PCMCIA_BOARD_MSG " Slot %c, DONE\n",
1418 slot+'A');
1419 return (0);
1420}
1421
1422static void cfg_port_B (void)
1423{
1424 volatile immap_t *immap;
1425 volatile cpm8xx_t *cp;
1426 uint reg;
1427
1428 immap = (immap_t *)CFG_IMMR;
1429 cp = (cpm8xx_t *)(&(((immap_t *)CFG_IMMR)->im_cpm));
1430
1431 /*
1432 * Configure Port B for TPS2205 PC-Card Power-Interface Switch
1433 *
1434 * Switch off all voltages, assert shutdown
1435 */
1436 reg = cp->cp_pbdat;
wdenk90e7e422002-12-04 23:39:58 +00001437 reg |= (TPS2205_VPP_PGM | TPS2205_VPP_VCC | /* VAVPP => Hi-Z */
1438 TPS2205_VCC3 | TPS2205_VCC5 | /* VAVCC => Hi-Z */
1439 TPS2205_SHDN); /* enable switch */
wdenkc6097192002-11-03 00:24:07 +00001440 cp->cp_pbdat = reg;
1441
1442 cp->cp_pbpar &= ~(TPS2205_INPUTS | TPS2205_OUTPUTS);
1443
1444 reg = cp->cp_pbdir & ~(TPS2205_INPUTS);
1445 cp->cp_pbdir = reg | TPS2205_OUTPUTS;
1446
1447 debug ("Set Port B: PAR: %08x DIR: %08x DAT: %08x\n",
1448 cp->cp_pbpar, cp->cp_pbdir, cp->cp_pbdat);
1449}
1450
1451#endif /* ICU862 */
1452
1453
wdenk90e7e422002-12-04 23:39:58 +00001454/* -------------------------------------------------------------------- */
1455/* C2MON Boards by TTTech Computertechnik AG */
1456/* -------------------------------------------------------------------- */
wdenkc6097192002-11-03 00:24:07 +00001457
1458#if defined(CONFIG_C2MON)
1459
1460#define PCMCIA_BOARD_MSG "C2MON"
1461
1462static void cfg_ports (void);
1463
1464static int hardware_enable(int slot)
1465{
1466 volatile immap_t *immap;
1467 volatile cpm8xx_t *cp;
1468 volatile pcmconf8xx_t *pcmp;
1469 volatile sysconf8xx_t *sysp;
1470 uint reg, pipr, mask;
1471 ushort sreg;
1472 int i;
1473
1474 debug ("hardware_enable: " PCMCIA_BOARD_MSG " Slot %c\n", 'A'+slot);
1475
1476 udelay(10000);
1477
1478 immap = (immap_t *)CFG_IMMR;
1479 sysp = (sysconf8xx_t *)(&(((immap_t *)CFG_IMMR)->im_siu_conf));
1480 pcmp = (pcmconf8xx_t *)(&(((immap_t *)CFG_IMMR)->im_pcmcia));
1481 cp = (cpm8xx_t *)(&(((immap_t *)CFG_IMMR)->im_cpm));
1482
1483 /* Configure Ports for TPS2211A PC-Card Power-Interface Switch */
1484 cfg_ports ();
1485
1486 /*
1487 * Configure SIUMCR to enable PCMCIA port B
1488 * (VFLS[0:1] are not used for debugging, we connect FRZ# instead)
1489 */
1490 sysp->sc_siumcr &= ~SIUMCR_DBGC11; /* set DBGC to 00 */
1491
1492 /* clear interrupt state, and disable interrupts */
1493 pcmp->pcmc_pscr = PCMCIA_MASK(_slot_);
1494 pcmp->pcmc_per &= ~PCMCIA_MASK(_slot_);
1495
wdenkc6097192002-11-03 00:24:07 +00001496 /*
wdenk90e7e422002-12-04 23:39:58 +00001497 * Disable interrupts, DMA, and PCMCIA buffers
1498 * (isolate the interface) and assert RESET signal
wdenkc6097192002-11-03 00:24:07 +00001499 */
1500 debug ("Disable PCMCIA buffers and assert RESET\n");
wdenk90e7e422002-12-04 23:39:58 +00001501 reg = 0;
1502 reg |= __MY_PCMCIA_GCRX_CXRESET; /* active high */
1503 reg |= __MY_PCMCIA_GCRX_CXOE; /* active low */
wdenkc6097192002-11-03 00:24:07 +00001504 PCMCIA_PGCRX(_slot_) = reg;
1505 udelay(500);
1506
1507 /*
1508 * Make sure there is a card in the slot, then configure the interface.
1509 */
1510 udelay(10000);
1511 debug ("[%d] %s: PIPR(%p)=0x%x\n",
1512 __LINE__,__FUNCTION__,
1513 &(pcmp->pcmc_pipr),pcmp->pcmc_pipr);
wdenk2029f4d2002-11-21 23:11:29 +00001514 if (pcmp->pcmc_pipr & (0x18000000 >> (slot << 4))) {
wdenkc6097192002-11-03 00:24:07 +00001515 printf (" No Card found\n");
1516 return (1);
1517 }
1518
1519 /*
1520 * Power On: Set VAVCC to 3.3V or 5V, set VAVPP to Hi-Z
1521 */
1522 mask = PCMCIA_VS1(slot) | PCMCIA_VS2(slot);
1523 pipr = pcmp->pcmc_pipr;
1524 debug ("PIPR: 0x%x ==> VS1=o%s, VS2=o%s\n",
1525 pipr,
1526 (reg&PCMCIA_VS1(slot))?"n":"ff",
1527 (reg&PCMCIA_VS2(slot))?"n":"ff");
1528
1529 sreg = immap->im_ioport.iop_pcdat;
1530 if ((pipr & mask) == mask) {
1531 sreg |= (TPS2211_VPPD0 | TPS2211_VPPD1 | /* VAVPP => Hi-Z */
1532 TPS2211_VCCD1); /* 5V on */
1533 sreg &= ~(TPS2211_VCCD0); /* 3V off */
1534 puts (" 5.0V card found: ");
1535 } else {
1536 sreg |= (TPS2211_VPPD0 | TPS2211_VPPD1 | /* VAVPP => Hi-Z */
1537 TPS2211_VCCD0); /* 3V on */
1538 sreg &= ~(TPS2211_VCCD1); /* 5V off */
1539 puts (" 3.3V card found: ");
1540 }
1541
1542 debug ("\nPC DAT: %04x -> 3.3V %s 5.0V %s\n",
1543 sreg,
1544 ( (sreg & TPS2211_VCCD0) && !(sreg & TPS2211_VCCD1)) ? "on" : "off",
1545 (!(sreg & TPS2211_VCCD0) && (sreg & TPS2211_VCCD1)) ? "on" : "off"
1546 );
1547
1548 immap->im_ioport.iop_pcdat = sreg;
1549
1550 /* Wait 500 ms; use this to check for over-current */
1551 for (i=0; i<5000; ++i) {
1552 if ((cp->cp_pbdat & TPS2211_OC) == 0) {
1553 printf (" *** Overcurrent - Safety shutdown ***\n");
1554 immap->im_ioport.iop_pcdat &= ~(TPS2211_VCCD0|TPS2211_VCCD1);
1555 return (1);
1556 }
1557 udelay (100);
1558 }
1559
1560 debug ("Enable PCMCIA buffers and stop RESET\n");
1561 reg = PCMCIA_PGCRX(_slot_);
1562 reg &= ~__MY_PCMCIA_GCRX_CXRESET; /* active high */
1563 reg &= ~__MY_PCMCIA_GCRX_CXOE; /* active low */
1564 PCMCIA_PGCRX(_slot_) = reg;
1565
1566 udelay(250000); /* some cards need >150 ms to come up :-( */
1567
1568 debug ("# hardware_enable done\n");
1569
1570 return (0);
1571}
1572
1573
wdenkc6097192002-11-03 00:24:07 +00001574#if (CONFIG_COMMANDS & CFG_CMD_PCMCIA)
1575static int hardware_disable(int slot)
1576{
1577 volatile immap_t *immap;
1578 volatile cpm8xx_t *cp;
1579 volatile pcmconf8xx_t *pcmp;
1580 u_long reg;
1581
1582 debug ("hardware_disable: " PCMCIA_BOARD_MSG " Slot %c\n", 'A'+slot);
1583
1584 immap = (immap_t *)CFG_IMMR;
1585 pcmp = (pcmconf8xx_t *)(&(((immap_t *)CFG_IMMR)->im_pcmcia));
1586
1587 /* Configure PCMCIA General Control Register */
wdenkc6097192002-11-03 00:24:07 +00001588 debug ("Disable PCMCIA buffers and assert RESET\n");
wdenk90e7e422002-12-04 23:39:58 +00001589 reg = 0;
wdenkc6097192002-11-03 00:24:07 +00001590 reg |= __MY_PCMCIA_GCRX_CXRESET; /* active high */
1591 reg |= __MY_PCMCIA_GCRX_CXOE; /* active low */
1592 PCMCIA_PGCRX(_slot_) = reg;
1593
1594 /* ALl voltages off / Hi-Z */
1595 immap->im_ioport.iop_pcdat |= (TPS2211_VPPD0 | TPS2211_VPPD1 |
1596 TPS2211_VCCD0 | TPS2211_VCCD1 );
1597
1598 udelay(10000);
1599
1600 return (0);
1601}
1602#endif /* CFG_CMD_PCMCIA */
1603
1604
wdenkc6097192002-11-03 00:24:07 +00001605static int voltage_set(int slot, int vcc, int vpp)
1606{
1607 volatile immap_t *immap;
1608 volatile cpm8xx_t *cp;
1609 volatile pcmconf8xx_t *pcmp;
1610 u_long reg;
1611 ushort sreg;
1612
1613 debug ("voltage_set: "
1614 PCMCIA_BOARD_MSG
1615 " Slot %c, Vcc=%d.%d, Vpp=%d.%d\n",
1616 'A'+slot, vcc/10, vcc%10, vpp/10, vcc%10);
1617
1618 immap = (immap_t *)CFG_IMMR;
1619 cp = (cpm8xx_t *)(&(((immap_t *)CFG_IMMR)->im_cpm));
1620 pcmp = (pcmconf8xx_t *)(&(((immap_t *)CFG_IMMR)->im_pcmcia));
1621 /*
1622 * Disable PCMCIA buffers (isolate the interface)
1623 * and assert RESET signal
1624 */
1625 debug ("Disable PCMCIA buffers and assert RESET\n");
wdenk90e7e422002-12-04 23:39:58 +00001626 reg = PCMCIA_PGCRX(_slot_);
1627 reg |= __MY_PCMCIA_GCRX_CXRESET; /* active high */
1628 reg |= __MY_PCMCIA_GCRX_CXOE; /* active low */
wdenkc6097192002-11-03 00:24:07 +00001629 PCMCIA_PGCRX(_slot_) = reg;
1630 udelay(500);
1631
1632 /*
1633 * Configure Port C pins for
1634 * 5 Volts Enable and 3 Volts enable,
1635 * Turn all power pins to Hi-Z
1636 */
1637 debug ("PCMCIA power OFF\n");
1638 cfg_ports (); /* Enables switch, but all in Hi-Z */
1639
1640 sreg = immap->im_ioport.iop_pcdat;
1641 sreg |= TPS2211_VPPD0 | TPS2211_VPPD1; /* VAVPP always Hi-Z */
1642
1643 switch(vcc) {
1644 case 0: break; /* Switch off */
1645 case 33: sreg |= TPS2211_VCCD0; /* Switch on 3.3V */
1646 sreg &= ~TPS2211_VCCD1;
1647 break;
1648 case 50: sreg &= ~TPS2211_VCCD0; /* Switch on 5.0V */
1649 sreg |= TPS2211_VCCD1;
1650 break;
1651 default: goto done;
1652 }
1653
1654 /* Checking supported voltages */
1655
1656 debug ("PIPR: 0x%x --> %s\n",
1657 pcmp->pcmc_pipr,
1658 (pcmp->pcmc_pipr & 0x00008000) ? "only 5 V" : "can do 3.3V");
1659
1660 immap->im_ioport.iop_pcdat = sreg;
1661
1662#ifdef DEBUG
1663 {
1664 char *s;
1665
1666 if ((sreg & TPS2211_VCCD0) && !(sreg & TPS2211_VCCD1)) {
1667 s = "at 3.3V";
1668 } else if (!(sreg & TPS2211_VCCD0) && (sreg & TPS2211_VCCD1)) {
1669 s = "at 5.0V";
1670 } else {
1671 s = "down";
1672 }
1673 printf ("PCMCIA powered %s\n", s);
1674 }
1675#endif
1676
1677done:
1678 debug ("Enable PCMCIA buffers and stop RESET\n");
1679 reg = PCMCIA_PGCRX(_slot_);
1680 reg &= ~__MY_PCMCIA_GCRX_CXRESET; /* active high */
1681 reg &= ~__MY_PCMCIA_GCRX_CXOE; /* active low */
1682 PCMCIA_PGCRX(_slot_) = reg;
1683 udelay(500);
1684
1685 debug ("voltage_set: " PCMCIA_BOARD_MSG " Slot %c, DONE\n",
1686 slot+'A');
1687 return (0);
1688}
1689
1690static void cfg_ports (void)
1691{
1692 volatile immap_t *immap;
1693 volatile cpm8xx_t *cp;
1694 ushort sreg;
1695
1696 immap = (immap_t *)CFG_IMMR;
1697 cp = (cpm8xx_t *)(&(((immap_t *)CFG_IMMR)->im_cpm));
1698
1699 /*
1700 * Configure Port C for TPS2211 PC-Card Power-Interface Switch
1701 *
1702 * Switch off all voltages, assert shutdown
1703 */
1704 sreg = immap->im_ioport.iop_pcdat;
1705 sreg |= (TPS2211_VPPD0 | TPS2211_VPPD1); /* VAVPP => Hi-Z */
1706 sreg &= ~(TPS2211_VCCD0 | TPS2211_VCCD1); /* 3V and 5V off */
1707 immap->im_ioport.iop_pcdat = sreg;
1708
1709 immap->im_ioport.iop_pcpar &= ~(TPS2211_OUTPUTS);
1710 immap->im_ioport.iop_pcdir |= TPS2211_OUTPUTS;
1711
1712 debug ("Set Port C: PAR: %04x DIR: %04x DAT: %04x\n",
1713 immap->im_ioport.iop_pcpar,
1714 immap->im_ioport.iop_pcdir,
1715 immap->im_ioport.iop_pcdat);
1716
1717 /*
1718 * Configure Port B for TPS2211 PC-Card Power-Interface Switch
1719 *
1720 * Over-Current Input only
1721 */
1722 cp->cp_pbpar &= ~(TPS2211_INPUTS);
1723 cp->cp_pbdir &= ~(TPS2211_INPUTS);
1724
1725 debug ("Set Port B: PAR: %08x DIR: %08x DAT: %08x\n",
1726 cp->cp_pbpar, cp->cp_pbdir, cp->cp_pbdat);
1727}
1728
1729#endif /* C2MON */
1730
wdenk90e7e422002-12-04 23:39:58 +00001731/* -------------------------------------------------------------------- */
1732/* MBX board from Morotola */
1733/* -------------------------------------------------------------------- */
wdenkc6097192002-11-03 00:24:07 +00001734
1735#if defined( CONFIG_MBX )
1736#include <../board/mbx8xx/csr.h>
1737
1738/* A lot of this has been taken from the RPX code in this file it works from me.
1739 I have added the voltage selection for the MBX board. */
1740
1741/* MBX voltage bit in control register #2 */
1742#define CR2_VPP12 ((uchar)0x10)
1743#define CR2_VPPVDD ((uchar)0x20)
1744#define CR2_VDD5 ((uchar)0x40)
1745#define CR2_VDD3 ((uchar)0x80)
1746
1747#define PCMCIA_BOARD_MSG "MBX860"
1748
1749static int voltage_set (int slot, int vcc, int vpp)
1750{
1751 uchar reg = 0;
1752
1753 debug ("voltage_set: PCMCIA_BOARD_MSG Slot %c, Vcc=%d.%d, Vpp=%d.%d\n",
1754 'A' + slot, vcc / 10, vcc % 10, vpp / 10, vcc % 10);
1755
1756 switch (vcc) {
1757 case 0:
1758 break;
1759 case 33:
1760 reg |= CR2_VDD3;
1761 break;
1762 case 50:
1763 reg |= CR2_VDD5;
1764 break;
1765 default:
1766 return 1;
1767 }
1768
1769 switch (vpp) {
1770 case 0:
1771 break;
1772 case 33:
1773 case 50:
1774 if (vcc == vpp) {
1775 reg |= CR2_VPPVDD;
1776 } else {
1777 return 1;
1778 }
1779 break;
1780 case 120:
1781 reg |= CR2_VPP12;
1782 break;
1783 default:
1784 return 1;
1785 }
1786
1787 /* first, turn off all power */
1788 MBX_CSR2 &= ~(CR2_VDDSEL | CR2_VPPSEL);
1789
1790 /* enable new powersettings */
1791 MBX_CSR2 |= reg;
1792 debug ("MBX_CSR2 read = 0x%02x\n", MBX_CSR2);
1793
1794 return (0);
1795}
1796
1797static int hardware_enable (int slot)
1798{
1799 volatile immap_t *immap;
1800 volatile cpm8xx_t *cp;
1801 volatile pcmconf8xx_t *pcmp;
1802 volatile sysconf8xx_t *sysp;
1803 uint reg, mask;
1804
1805 debug ("hardware_enable: " PCMCIA_BOARD_MSG " Slot %c\n",
1806 'A' + slot);
1807
1808 udelay (10000);
1809
1810 immap = (immap_t *) CFG_IMMR;
1811 sysp = (sysconf8xx_t *) (&(((immap_t *) CFG_IMMR)->im_siu_conf));
1812 pcmp = (pcmconf8xx_t *) (&(((immap_t *) CFG_IMMR)->im_pcmcia));
1813 cp = (cpm8xx_t *) (&(((immap_t *) CFG_IMMR)->im_cpm));
1814
1815 /* clear interrupt state, and disable interrupts */
1816 pcmp->pcmc_pscr = PCMCIA_MASK (_slot_);
1817 pcmp->pcmc_per &= ~PCMCIA_MASK (_slot_);
1818
wdenkc6097192002-11-03 00:24:07 +00001819 /*
wdenk90e7e422002-12-04 23:39:58 +00001820 * Disable interrupts, DMA, and PCMCIA buffers
1821 * (isolate the interface) and assert RESET signal
wdenkc6097192002-11-03 00:24:07 +00001822 */
1823 debug ("Disable PCMCIA buffers and assert RESET\n");
wdenk90e7e422002-12-04 23:39:58 +00001824 reg = 0;
wdenkc6097192002-11-03 00:24:07 +00001825 reg |= __MY_PCMCIA_GCRX_CXRESET; /* active high */
1826 reg |= __MY_PCMCIA_GCRX_CXOE; /* active low */
1827 PCMCIA_PGCRX (_slot_) = reg;
1828 udelay (500);
1829
1830 /* remove all power */
1831 voltage_set (slot, 0, 0);
1832 /*
1833 * Make sure there is a card in the slot, then configure the interface.
1834 */
wdenk2029f4d2002-11-21 23:11:29 +00001835 udelay(10000);
1836 debug ("[%d] %s: PIPR(%p)=0x%x\n",
1837 __LINE__,__FUNCTION__,
1838 &(pcmp->pcmc_pipr),pcmp->pcmc_pipr);
wdenk2f99a692004-01-04 22:51:12 +00001839#ifndef CONFIG_BMS2003
wdenk2029f4d2002-11-21 23:11:29 +00001840 if (pcmp->pcmc_pipr & (0x18000000 >> (slot << 4))) {
wdenk2f99a692004-01-04 22:51:12 +00001841#else
1842 if (pcmp->pcmc_pipr & (0x10000000 >> (slot << 4))) {
1843#endif /* CONFIG_BMS2003 */
wdenkc6097192002-11-03 00:24:07 +00001844 printf (" No Card found\n");
1845 return (1);
1846 }
1847
1848 /*
1849 * Power On.
1850 */
1851 mask = PCMCIA_VS1 (_slot_) | PCMCIA_VS2 (_slot_);
1852 reg = pcmp->pcmc_pipr;
1853 debug ("PIPR: 0x%x ==> VS1=o%s, VS2=o%s\n", reg,
1854 (reg & PCMCIA_VS1 (slot)) ? "n" : "ff",
1855 (reg & PCMCIA_VS2 (slot)) ? "n" : "ff");
1856
1857 if ((reg & mask) == mask) {
1858 voltage_set (_slot_, 50, 0);
1859 printf (" 5.0V card found: ");
1860 } else {
1861 voltage_set (_slot_, 33, 0);
1862 printf (" 3.3V card found: ");
1863 }
1864
1865 debug ("Enable PCMCIA buffers and stop RESET\n");
1866 reg = PCMCIA_PGCRX (_slot_);
1867 reg &= ~__MY_PCMCIA_GCRX_CXRESET; /* active high */
1868 reg &= ~__MY_PCMCIA_GCRX_CXOE; /* active low */
1869 PCMCIA_PGCRX (_slot_) = reg;
1870
1871 udelay (250000); /* some cards need >150 ms to come up :-( */
1872
1873 debug ("# hardware_enable done\n");
1874
1875 return (0);
1876}
1877
1878#if (CONFIG_COMMANDS & CFG_CMD_PCMCIA)
1879static int hardware_disable (int slot)
1880{
1881 return 0; /* No hardware to disable */
1882}
1883#endif /* CFG_CMD_PCMCIA */
1884#endif /* CONFIG_MBX */
wdenk90e7e422002-12-04 23:39:58 +00001885/* -------------------------------------------------------------------- */
1886/* R360MPI Board */
1887/* -------------------------------------------------------------------- */
wdenkc6097192002-11-03 00:24:07 +00001888
1889#if defined(CONFIG_R360MPI)
1890
1891#define PCMCIA_BOARD_MSG "R360MPI"
1892
1893
1894static int hardware_enable(int slot)
1895{
1896 volatile immap_t *immap;
1897 volatile cpm8xx_t *cp;
1898 volatile pcmconf8xx_t *pcmp;
1899 volatile sysconf8xx_t *sysp;
1900 uint reg, mask;
1901
1902 debug ("hardware_enable: " PCMCIA_BOARD_MSG " Slot %c\n", 'A'+slot);
1903
1904 udelay(10000);
1905
1906 immap = (immap_t *)CFG_IMMR;
1907 sysp = (sysconf8xx_t *)(&(((immap_t *)CFG_IMMR)->im_siu_conf));
1908 pcmp = (pcmconf8xx_t *)(&(((immap_t *)CFG_IMMR)->im_pcmcia));
1909 cp = (cpm8xx_t *)(&(((immap_t *)CFG_IMMR)->im_cpm));
1910
1911 /*
1912 * Configure SIUMCR to enable PCMCIA port B
1913 * (VFLS[0:1] are not used for debugging, we connect FRZ# instead)
1914 */
1915 sysp->sc_siumcr &= ~SIUMCR_DBGC11; /* set DBGC to 00 */
1916
1917 /* clear interrupt state, and disable interrupts */
1918 pcmp->pcmc_pscr = PCMCIA_MASK(_slot_);
1919 pcmp->pcmc_per &= ~PCMCIA_MASK(_slot_);
1920
wdenkc6097192002-11-03 00:24:07 +00001921 /*
wdenk90e7e422002-12-04 23:39:58 +00001922 * Disable interrupts, DMA, and PCMCIA buffers
1923 * (isolate the interface) and assert RESET signal
wdenkc6097192002-11-03 00:24:07 +00001924 */
1925 debug ("Disable PCMCIA buffers and assert RESET\n");
wdenk90e7e422002-12-04 23:39:58 +00001926 reg = 0;
1927 reg |= __MY_PCMCIA_GCRX_CXRESET; /* active high */
1928 reg |= __MY_PCMCIA_GCRX_CXOE; /* active low */
wdenkc6097192002-11-03 00:24:07 +00001929 PCMCIA_PGCRX(_slot_) = reg;
1930 udelay(500);
1931
1932 /*
1933 * Configure Ports A, B & C pins for
1934 * 5 Volts Enable and 3 Volts enable
1935 */
1936 immap->im_ioport.iop_pcpar &= ~(0x0400);
1937 immap->im_ioport.iop_pcso &= ~(0x0400);/*
1938 immap->im_ioport.iop_pcdir |= 0x0400;*/
1939
1940 immap->im_ioport.iop_papar &= ~(0x0200);/*
1941 immap->im_ioport.iop_padir |= 0x0200;*/
1942#if 0
1943 immap->im_ioport.iop_pbpar &= ~(0xC000);
1944 immap->im_ioport.iop_pbdir &= ~(0xC000);
1945#endif
1946 /* remove all power */
1947
1948 immap->im_ioport.iop_pcdat |= 0x0400;
1949 immap->im_ioport.iop_padat |= 0x0200;
1950
1951 /*
1952 * Make sure there is a card in the slot, then configure the interface.
1953 */
1954 udelay(10000);
1955 debug ("[%d] %s: PIPR(%p)=0x%x\n",
1956 __LINE__,__FUNCTION__,
1957 &(pcmp->pcmc_pipr),pcmp->pcmc_pipr);
wdenk2029f4d2002-11-21 23:11:29 +00001958 if (pcmp->pcmc_pipr & (0x18000000 >> (slot << 4))) {
wdenkc6097192002-11-03 00:24:07 +00001959 printf (" No Card found\n");
1960 return (1);
1961 }
1962
1963 /*
1964 * Power On.
1965 */
1966 mask = PCMCIA_VS1(slot) | PCMCIA_VS2(slot);
1967 reg = pcmp->pcmc_pipr;
1968 debug ("PIPR: 0x%x ==> VS1=o%s, VS2=o%s\n",
1969 reg,
1970 (reg&PCMCIA_VS1(slot))?"n":"ff",
1971 (reg&PCMCIA_VS2(slot))?"n":"ff");
1972 if ((reg & mask) == mask) {
1973 immap->im_ioport.iop_pcdat &= ~(0x4000);
1974 puts (" 5.0V card found: ");
1975 } else {
1976 immap->im_ioport.iop_padat &= ~(0x0002);
1977 puts (" 3.3V card found: ");
1978 }
1979 immap->im_ioport.iop_pcdir |= 0x0400;
1980 immap->im_ioport.iop_padir |= 0x0200;
1981#if 0
1982 /* VCC switch error flag, PCMCIA slot INPACK_ pin */
1983 cp->cp_pbdir &= ~(0x0020 | 0x0010);
1984 cp->cp_pbpar &= ~(0x0020 | 0x0010);
1985 udelay(500000);
1986#endif
1987 debug ("Enable PCMCIA buffers and stop RESET\n");
1988 reg = PCMCIA_PGCRX(_slot_);
1989 reg &= ~__MY_PCMCIA_GCRX_CXRESET; /* active high */
1990 reg &= ~__MY_PCMCIA_GCRX_CXOE; /* active low */
1991 PCMCIA_PGCRX(_slot_) = reg;
1992
1993 udelay(250000); /* some cards need >150 ms to come up :-( */
1994
1995 debug ("# hardware_enable done\n");
1996
1997 return (0);
1998}
1999
2000
wdenkc6097192002-11-03 00:24:07 +00002001#if (CONFIG_COMMANDS & CFG_CMD_PCMCIA)
2002static int hardware_disable(int slot)
2003{
2004 volatile immap_t *immap;
2005 volatile pcmconf8xx_t *pcmp;
2006 u_long reg;
2007
2008 debug ("hardware_disable: " PCMCIA_BOARD_MSG " Slot %c\n", 'A'+slot);
2009
2010 immap = (immap_t *)CFG_IMMR;
2011 pcmp = (pcmconf8xx_t *)(&(((immap_t *)CFG_IMMR)->im_pcmcia));
2012
2013 /* remove all power */
2014 immap->im_ioport.iop_pcdat |= 0x0400;
2015 immap->im_ioport.iop_padat |= 0x0200;
2016
2017 /* Configure PCMCIA General Control Register */
wdenkc6097192002-11-03 00:24:07 +00002018 debug ("Disable PCMCIA buffers and assert RESET\n");
wdenk90e7e422002-12-04 23:39:58 +00002019 reg = 0;
wdenkc6097192002-11-03 00:24:07 +00002020 reg |= __MY_PCMCIA_GCRX_CXRESET; /* active high */
2021 reg |= __MY_PCMCIA_GCRX_CXOE; /* active low */
2022 PCMCIA_PGCRX(_slot_) = reg;
2023
2024 udelay(10000);
2025
2026 return (0);
2027}
2028#endif /* CFG_CMD_PCMCIA */
2029
2030
wdenkc6097192002-11-03 00:24:07 +00002031static int voltage_set(int slot, int vcc, int vpp)
2032{
2033 volatile immap_t *immap;
2034 volatile pcmconf8xx_t *pcmp;
2035 u_long reg;
2036
2037 debug ("voltage_set: "
2038 PCMCIA_BOARD_MSG
2039 " Slot %c, Vcc=%d.%d, Vpp=%d.%d\n",
2040 'A'+slot, vcc/10, vcc%10, vpp/10, vcc%10);
2041
2042 immap = (immap_t *)CFG_IMMR;
2043 pcmp = (pcmconf8xx_t *)(&(((immap_t *)CFG_IMMR)->im_pcmcia));
2044 /*
2045 * Disable PCMCIA buffers (isolate the interface)
2046 * and assert RESET signal
2047 */
2048 debug ("Disable PCMCIA buffers and assert RESET\n");
wdenk90e7e422002-12-04 23:39:58 +00002049 reg = PCMCIA_PGCRX(_slot_);
2050 reg |= __MY_PCMCIA_GCRX_CXRESET; /* active high */
2051 reg |= __MY_PCMCIA_GCRX_CXOE; /* active low */
wdenkc6097192002-11-03 00:24:07 +00002052 PCMCIA_PGCRX(_slot_) = reg;
2053 udelay(500);
2054
2055 /*
2056 * Configure Ports A & C pins for
2057 * 5 Volts Enable and 3 Volts enable,
2058 * Turn off all power
2059 */
2060 debug ("PCMCIA power OFF\n");
2061 immap->im_ioport.iop_pcpar &= ~(0x0400);
2062 immap->im_ioport.iop_pcso &= ~(0x0400);/*
2063 immap->im_ioport.iop_pcdir |= 0x0400;*/
2064
2065 immap->im_ioport.iop_papar &= ~(0x0200);/*
2066 immap->im_ioport.iop_padir |= 0x0200;*/
2067
2068 immap->im_ioport.iop_pcdat |= 0x0400;
2069 immap->im_ioport.iop_padat |= 0x0200;
2070
2071 reg = 0;
2072 switch(vcc) {
2073 case 0: break;
2074 case 33: reg |= 0x0200; break;
2075 case 50: reg |= 0x0400; break;
2076 default: goto done;
2077 }
2078
2079 /* Checking supported voltages */
2080
2081 debug ("PIPR: 0x%x --> %s\n",
2082 pcmp->pcmc_pipr,
2083 (pcmp->pcmc_pipr & 0x00008000) ? "only 5 V" : "can do 3.3V");
2084
2085 if (reg & 0x0200)
2086 immap->im_ioport.iop_pcdat &= !reg;
2087 if (reg & 0x0400)
2088 immap->im_ioport.iop_padat &= !reg;
wdenk90e7e422002-12-04 23:39:58 +00002089 immap->im_ioport.iop_pcdir |= 0x0200;
2090 immap->im_ioport.iop_padir |= 0x0400;
wdenkc6097192002-11-03 00:24:07 +00002091 if (reg) {
2092 debug ("PCMCIA powered at %sV\n",
2093 (reg&0x0400) ? "5.0" : "3.3");
2094 } else {
2095 debug ("PCMCIA powered down\n");
2096 }
2097
2098done:
2099 debug ("Enable PCMCIA buffers and stop RESET\n");
2100 reg = PCMCIA_PGCRX(_slot_);
2101 reg &= ~__MY_PCMCIA_GCRX_CXRESET; /* active high */
2102 reg &= ~__MY_PCMCIA_GCRX_CXOE; /* active low */
2103 PCMCIA_PGCRX(_slot_) = reg;
2104 udelay(500);
2105
2106 debug ("voltage_set: " PCMCIA_BOARD_MSG " Slot %c, DONE\n",
2107 slot+'A');
2108 return (0);
2109}
2110
2111#endif /* R360MPI */
2112
wdenk90e7e422002-12-04 23:39:58 +00002113/* -------------------------------------------------------------------- */
2114/* KUP4K Board */
2115/* -------------------------------------------------------------------- */
wdenk56f94be2002-11-05 16:35:14 +00002116#if defined(CONFIG_KUP4K)
2117
2118#define PCMCIA_BOARD_MSG "KUP4K"
2119
2120#define KUP4K_PCMCIA_B_3V3 (0x00020000)
2121
2122static int hardware_enable(int slot)
2123{
2124 volatile immap_t *immap;
2125 volatile cpm8xx_t *cp;
2126 volatile pcmconf8xx_t *pcmp;
2127 volatile sysconf8xx_t *sysp;
2128 uint reg, mask;
2129
2130 debug ("hardware_enable: " PCMCIA_BOARD_MSG " Slot %c\n", 'A'+slot);
2131
2132 udelay(10000);
2133
2134 immap = (immap_t *)CFG_IMMR;
2135 sysp = (sysconf8xx_t *)(&(((immap_t *)CFG_IMMR)->im_siu_conf));
2136 pcmp = (pcmconf8xx_t *)(&(((immap_t *)CFG_IMMR)->im_pcmcia));
2137 cp = (cpm8xx_t *)(&(((immap_t *)CFG_IMMR)->im_cpm));
2138
2139 /*
2140 * Configure SIUMCR to enable PCMCIA port B
2141 * (VFLS[0:1] are not used for debugging, we connect FRZ# instead)
2142 */
2143 sysp->sc_siumcr &= ~SIUMCR_DBGC11; /* set DBGC to 00 */
2144
2145 /* clear interrupt state, and disable interrupts */
wdenk2029f4d2002-11-21 23:11:29 +00002146 pcmp->pcmc_pscr = PCMCIA_MASK(slot);
2147 pcmp->pcmc_per &= ~PCMCIA_MASK(slot);
wdenk56f94be2002-11-05 16:35:14 +00002148
wdenk56f94be2002-11-05 16:35:14 +00002149 /*
wdenk90e7e422002-12-04 23:39:58 +00002150 * Disable interrupts, DMA, and PCMCIA buffers
2151 * (isolate the interface) and assert RESET signal
wdenk56f94be2002-11-05 16:35:14 +00002152 */
2153 debug ("Disable PCMCIA buffers and assert RESET\n");
wdenk90e7e422002-12-04 23:39:58 +00002154 reg = 0;
2155 reg |= __MY_PCMCIA_GCRX_CXRESET; /* active high */
2156 reg |= __MY_PCMCIA_GCRX_CXOE; /* active low */
wdenk2029f4d2002-11-21 23:11:29 +00002157 PCMCIA_PGCRX(slot) = reg;
2158 udelay(2500);
wdenk56f94be2002-11-05 16:35:14 +00002159
2160 /*
2161 * Configure Port B pins for
2162 * 3 Volts enable
2163 */
wdenk2029f4d2002-11-21 23:11:29 +00002164 if (slot) { /* Slot A is built-in */
2165 cp->cp_pbdir |= KUP4K_PCMCIA_B_3V3;
2166 cp->cp_pbpar &= ~KUP4K_PCMCIA_B_3V3;
2167 /* remove all power */
2168 cp->cp_pbdat |= KUP4K_PCMCIA_B_3V3; /* active low */
2169 }
wdenk56f94be2002-11-05 16:35:14 +00002170 /*
2171 * Make sure there is a card in the slot, then configure the interface.
2172 */
2173 udelay(10000);
2174 debug ("[%d] %s: PIPR(%p)=0x%x\n",
2175 __LINE__,__FUNCTION__,
2176 &(pcmp->pcmc_pipr),pcmp->pcmc_pipr);
wdenk2029f4d2002-11-21 23:11:29 +00002177 if (pcmp->pcmc_pipr & (0x18000000 >> (slot << 4))) {
wdenk56f94be2002-11-05 16:35:14 +00002178 printf (" No Card found\n");
2179 return (1);
2180 }
2181
2182 /*
2183 * Power On.
2184 */
wdenk9dd2b882002-12-03 21:28:10 +00002185 printf("%s Slot %c:", slot ? "" : "\n", 'A' + slot);
wdenk56f94be2002-11-05 16:35:14 +00002186 mask = PCMCIA_VS1(slot) | PCMCIA_VS2(slot);
2187 reg = pcmp->pcmc_pipr;
2188 debug ("PIPR: 0x%x ==> VS1=o%s, VS2=o%s\n",
2189 reg,
2190 (reg&PCMCIA_VS1(slot))?"n":"ff",
2191 (reg&PCMCIA_VS2(slot))?"n":"ff");
2192 if ((reg & mask) == mask) {
2193 puts (" 5.0V card found: NOT SUPPORTED !!!\n");
2194 } else {
wdenk2029f4d2002-11-21 23:11:29 +00002195 if(slot)
2196 cp->cp_pbdat &= ~KUP4K_PCMCIA_B_3V3;
wdenk56f94be2002-11-05 16:35:14 +00002197 puts (" 3.3V card found: ");
2198 }
2199#if 0
2200 /* VCC switch error flag, PCMCIA slot INPACK_ pin */
2201 cp->cp_pbdir &= ~(0x0020 | 0x0010);
2202 cp->cp_pbpar &= ~(0x0020 | 0x0010);
2203 udelay(500000);
2204#endif
2205 debug ("Enable PCMCIA buffers and stop RESET\n");
wdenk2029f4d2002-11-21 23:11:29 +00002206 reg = PCMCIA_PGCRX(slot);
wdenk56f94be2002-11-05 16:35:14 +00002207 reg &= ~__MY_PCMCIA_GCRX_CXRESET; /* active high */
2208 reg &= ~__MY_PCMCIA_GCRX_CXOE; /* active low */
wdenk2029f4d2002-11-21 23:11:29 +00002209 PCMCIA_PGCRX(slot) = reg;
wdenk56f94be2002-11-05 16:35:14 +00002210
2211 udelay(250000); /* some cards need >150 ms to come up :-( */
2212
2213 debug ("# hardware_enable done\n");
2214
2215 return (0);
2216}
2217
2218
wdenk56f94be2002-11-05 16:35:14 +00002219#if (CONFIG_COMMANDS & CFG_CMD_PCMCIA)
2220static int hardware_disable(int slot)
2221{
2222 volatile immap_t *immap;
2223 volatile cpm8xx_t *cp;
2224 volatile pcmconf8xx_t *pcmp;
2225 u_long reg;
2226
2227 debug ("hardware_disable: " PCMCIA_BOARD_MSG " Slot %c\n", 'A'+slot);
2228
2229 immap = (immap_t *)CFG_IMMR;
2230 pcmp = (pcmconf8xx_t *)(&(((immap_t *)CFG_IMMR)->im_pcmcia));
2231 cp = (cpm8xx_t *)(&(((immap_t *)CFG_IMMR)->im_cpm));
wdenk90e7e422002-12-04 23:39:58 +00002232
wdenk56f94be2002-11-05 16:35:14 +00002233 /* remove all power */
wdenk2029f4d2002-11-21 23:11:29 +00002234 if (slot)
2235 cp->cp_pbdat |= KUP4K_PCMCIA_B_3V3;
wdenk56f94be2002-11-05 16:35:14 +00002236
2237 /* Configure PCMCIA General Control Register */
wdenk56f94be2002-11-05 16:35:14 +00002238 debug ("Disable PCMCIA buffers and assert RESET\n");
wdenk90e7e422002-12-04 23:39:58 +00002239 reg = 0;
wdenk56f94be2002-11-05 16:35:14 +00002240 reg |= __MY_PCMCIA_GCRX_CXRESET; /* active high */
2241 reg |= __MY_PCMCIA_GCRX_CXOE; /* active low */
wdenk2029f4d2002-11-21 23:11:29 +00002242 PCMCIA_PGCRX(slot) = reg;
wdenk56f94be2002-11-05 16:35:14 +00002243
2244 udelay(10000);
2245
2246 return (0);
2247}
2248#endif /* CFG_CMD_PCMCIA */
2249
2250
wdenk56f94be2002-11-05 16:35:14 +00002251static int voltage_set(int slot, int vcc, int vpp)
2252{
2253 volatile immap_t *immap;
2254 volatile cpm8xx_t *cp;
2255 volatile pcmconf8xx_t *pcmp;
2256 u_long reg;
2257
2258 debug ("voltage_set: " \
2259 PCMCIA_BOARD_MSG \
2260 " Slot %c, Vcc=%d.%d, Vpp=%d.%d\n",
2261 'A'+slot, vcc/10, vcc%10, vpp/10, vcc%10);
2262
wdenk2029f4d2002-11-21 23:11:29 +00002263 if (!slot) /* Slot A is not configurable */
2264 return 0;
2265
wdenk56f94be2002-11-05 16:35:14 +00002266 immap = (immap_t *)CFG_IMMR;
2267 pcmp = (pcmconf8xx_t *)(&(((immap_t *)CFG_IMMR)->im_pcmcia));
2268 cp = (cpm8xx_t *)(&(((immap_t *)CFG_IMMR)->im_cpm));
2269
2270 /*
2271 * Disable PCMCIA buffers (isolate the interface)
2272 * and assert RESET signal
2273 */
2274 debug ("Disable PCMCIA buffers and assert RESET\n");
wdenk90e7e422002-12-04 23:39:58 +00002275 reg = PCMCIA_PGCRX(slot);
2276 reg |= __MY_PCMCIA_GCRX_CXRESET; /* active high */
2277 reg |= __MY_PCMCIA_GCRX_CXOE; /* active low */
wdenk2029f4d2002-11-21 23:11:29 +00002278 PCMCIA_PGCRX(slot) = reg;
wdenk56f94be2002-11-05 16:35:14 +00002279 udelay(500);
2280
2281 debug ("PCMCIA power OFF\n");
2282 /*
2283 * Configure Port B pins for
2284 * 3 Volts enable
2285 */
2286 cp->cp_pbdir |= KUP4K_PCMCIA_B_3V3;
2287 cp->cp_pbpar &= ~KUP4K_PCMCIA_B_3V3;
2288 /* remove all power */
2289 cp->cp_pbdat |= KUP4K_PCMCIA_B_3V3; /* active low */
2290
2291 switch(vcc) {
2292 case 0: break;
2293 case 33:
2294 cp->cp_pbdat &= ~KUP4K_PCMCIA_B_3V3;
2295 debug ("PCMCIA powered at 3.3V\n");
2296 break;
2297 case 50:
2298 debug ("PCMCIA: 5Volt vcc not supported\n");
2299 break;
2300 default:
2301 puts("PCMCIA: vcc not supported");
2302 break;
2303 }
wdenk2029f4d2002-11-21 23:11:29 +00002304 udelay(10000);
wdenk56f94be2002-11-05 16:35:14 +00002305 /* Checking supported voltages */
2306
2307 debug ("PIPR: 0x%x --> %s\n",
2308 pcmp->pcmc_pipr,
wdenk2029f4d2002-11-21 23:11:29 +00002309 (pcmp->pcmc_pipr & (0x80000000 >> (slot << 4)))
wdenk56f94be2002-11-05 16:35:14 +00002310 ? "only 5 V --> NOT SUPPORTED"
2311 : "can do 3.3V");
2312
2313
2314 debug ("Enable PCMCIA buffers and stop RESET\n");
wdenk2029f4d2002-11-21 23:11:29 +00002315 reg = PCMCIA_PGCRX(slot);
wdenk56f94be2002-11-05 16:35:14 +00002316 reg &= ~__MY_PCMCIA_GCRX_CXRESET; /* active high */
2317 reg &= ~__MY_PCMCIA_GCRX_CXOE; /* active low */
wdenk2029f4d2002-11-21 23:11:29 +00002318 PCMCIA_PGCRX(slot) = reg;
wdenk56f94be2002-11-05 16:35:14 +00002319 udelay(500);
2320
2321 debug ("voltage_set: " PCMCIA_BOARD_MSG " Slot %c, DONE\n",
2322 slot+'A');
2323 return (0);
2324}
2325
2326#endif /* KUP4K */
2327
2328
wdenk90e7e422002-12-04 23:39:58 +00002329/* -------------------------------------------------------------------- */
2330/* End of Board Specific Stuff */
2331/* -------------------------------------------------------------------- */
wdenkc6097192002-11-03 00:24:07 +00002332
2333
wdenk90e7e422002-12-04 23:39:58 +00002334/* -------------------------------------------------------------------- */
2335/* MPC8xx Specific Stuff - should go to MPC8xx directory */
2336/* -------------------------------------------------------------------- */
wdenkc6097192002-11-03 00:24:07 +00002337
2338/*
2339 * Search this table to see if the windowsize is
2340 * supported...
2341 */
2342
2343#define M8XX_SIZES_NO 32
2344
2345static const u_int m8xx_size_to_gray[M8XX_SIZES_NO] =
2346{ 0x00000001, 0x00000002, 0x00000008, 0x00000004,
2347 0x00000080, 0x00000040, 0x00000010, 0x00000020,
2348 0x00008000, 0x00004000, 0x00001000, 0x00002000,
2349 0x00000100, 0x00000200, 0x00000800, 0x00000400,
2350
2351 0x0fffffff, 0xffffffff, 0xffffffff, 0xffffffff,
2352 0x01000000, 0x02000000, 0xffffffff, 0x04000000,
2353 0x00010000, 0x00020000, 0x00080000, 0x00040000,
2354 0x00800000, 0x00400000, 0x00100000, 0x00200000 };
2355
2356
wdenk90e7e422002-12-04 23:39:58 +00002357/* -------------------------------------------------------------------- */
wdenkc6097192002-11-03 00:24:07 +00002358
wdenk0893c472003-05-20 14:25:27 +00002359#ifndef CONFIG_I82365
2360
wdenkc6097192002-11-03 00:24:07 +00002361static u_int m8xx_get_graycode(u_int size)
2362{
2363 u_int k;
2364
2365 for (k = 0; k < M8XX_SIZES_NO; k++) {
2366 if(m8xx_size_to_gray[k] == size)
2367 break;
2368 }
2369
2370 if((k == M8XX_SIZES_NO) || (m8xx_size_to_gray[k] == -1))
2371 k = -1;
2372
2373 return k;
2374}
2375
wdenk0893c472003-05-20 14:25:27 +00002376#endif /* CONFIG_I82365 */
2377
wdenk90e7e422002-12-04 23:39:58 +00002378/* -------------------------------------------------------------------- */
wdenkc6097192002-11-03 00:24:07 +00002379
2380#if 0
2381static u_int m8xx_get_speed(u_int ns, u_int is_io)
2382{
2383 u_int reg, clocks, psst, psl, psht;
2384
2385 if(!ns) {
2386
2387 /*
2388 * We get called with IO maps setup to 0ns
2389 * if not specified by the user.
2390 * They should be 255ns.
2391 */
2392
2393 if(is_io)
2394 ns = 255;
2395 else
2396 ns = 100; /* fast memory if 0 */
2397 }
2398
2399 /*
2400 * In PSST, PSL, PSHT fields we tell the controller
2401 * timing parameters in CLKOUT clock cycles.
2402 * CLKOUT is the same as GCLK2_50.
2403 */
2404
2405/* how we want to adjust the timing - in percent */
2406
2407#define ADJ 180 /* 80 % longer accesstime - to be sure */
2408
2409 clocks = ((M8XX_BUSFREQ / 1000) * ns) / 1000;
2410 clocks = (clocks * ADJ) / (100*1000);
2411
2412 if(clocks >= PCMCIA_BMT_LIMIT) {
2413 DEBUG(0, "Max access time limit reached\n");
2414 clocks = PCMCIA_BMT_LIMIT-1;
2415 }
2416
2417 psst = clocks / 7; /* setup time */
2418 psht = clocks / 7; /* hold time */
2419 psl = (clocks * 5) / 7; /* strobe length */
2420
2421 psst += clocks - (psst + psht + psl);
2422
2423 reg = psst << 12;
2424 reg |= psl << 7;
2425 reg |= psht << 16;
2426
2427 return reg;
2428}
2429#endif
2430
wdenk90e7e422002-12-04 23:39:58 +00002431/* -------------------------------------------------------------------- */
wdenkc6097192002-11-03 00:24:07 +00002432
2433#ifdef CONFIG_IDE_8xx_PCCARD
2434static void print_funcid (int func)
2435{
2436 puts (indent);
2437 switch (func) {
2438 case CISTPL_FUNCID_MULTI:
2439 puts (" Multi-Function");
2440 break;
2441 case CISTPL_FUNCID_MEMORY:
2442 puts (" Memory");
2443 break;
2444 case CISTPL_FUNCID_SERIAL:
2445 puts (" Serial Port");
2446 break;
2447 case CISTPL_FUNCID_PARALLEL:
2448 puts (" Parallel Port");
2449 break;
2450 case CISTPL_FUNCID_FIXED:
2451 puts (" Fixed Disk");
2452 break;
2453 case CISTPL_FUNCID_VIDEO:
2454 puts (" Video Adapter");
2455 break;
2456 case CISTPL_FUNCID_NETWORK:
2457 puts (" Network Adapter");
2458 break;
2459 case CISTPL_FUNCID_AIMS:
2460 puts (" AIMS Card");
2461 break;
2462 case CISTPL_FUNCID_SCSI:
2463 puts (" SCSI Adapter");
2464 break;
2465 default:
2466 puts (" Unknown");
2467 break;
2468 }
2469 puts (" Card\n");
2470}
2471#endif /* CONFIG_IDE_8xx_PCCARD */
2472
wdenk90e7e422002-12-04 23:39:58 +00002473/* -------------------------------------------------------------------- */
wdenkc6097192002-11-03 00:24:07 +00002474
2475#ifdef CONFIG_IDE_8xx_PCCARD
2476static void print_fixed (volatile uchar *p)
2477{
2478 if (p == NULL)
2479 return;
2480
2481 puts(indent);
2482
2483 switch (*p) {
2484 case CISTPL_FUNCE_IDE_IFACE:
2485 { uchar iface = *(p+2);
2486
2487 puts ((iface == CISTPL_IDE_INTERFACE) ? " IDE" : " unknown");
2488 puts (" interface ");
2489 break;
2490 }
2491 case CISTPL_FUNCE_IDE_MASTER:
2492 case CISTPL_FUNCE_IDE_SLAVE:
2493 { uchar f1 = *(p+2);
2494 uchar f2 = *(p+4);
2495
2496 puts ((f1 & CISTPL_IDE_SILICON) ? " [silicon]" : " [rotating]");
2497
2498 if (f1 & CISTPL_IDE_UNIQUE)
2499 puts (" [unique]");
2500
2501 puts ((f1 & CISTPL_IDE_DUAL) ? " [dual]" : " [single]");
2502
2503 if (f2 & CISTPL_IDE_HAS_SLEEP)
2504 puts (" [sleep]");
2505
2506 if (f2 & CISTPL_IDE_HAS_STANDBY)
2507 puts (" [standby]");
2508
2509 if (f2 & CISTPL_IDE_HAS_IDLE)
2510 puts (" [idle]");
2511
2512 if (f2 & CISTPL_IDE_LOW_POWER)
2513 puts (" [low power]");
2514
2515 if (f2 & CISTPL_IDE_REG_INHIBIT)
2516 puts (" [reg inhibit]");
2517
2518 if (f2 & CISTPL_IDE_HAS_INDEX)
2519 puts (" [index]");
2520
2521 if (f2 & CISTPL_IDE_IOIS16)
2522 puts (" [IOis16]");
2523
2524 break;
2525 }
2526 }
2527 putc ('\n');
2528}
2529#endif /* CONFIG_IDE_8xx_PCCARD */
2530
wdenk90e7e422002-12-04 23:39:58 +00002531/* -------------------------------------------------------------------- */
wdenkc6097192002-11-03 00:24:07 +00002532
2533#ifdef CONFIG_IDE_8xx_PCCARD
2534
2535#define MAX_IDENT_CHARS 64
2536#define MAX_IDENT_FIELDS 4
2537
2538static uchar *known_cards[] = {
2539 "ARGOSY PnPIDE D5",
2540 NULL
2541};
2542
2543static int identify (volatile uchar *p)
2544{
2545 uchar id_str[MAX_IDENT_CHARS];
2546 uchar data;
2547 uchar *t;
2548 uchar **card;
2549 int i, done;
2550
2551 if (p == NULL)
2552 return (0); /* Don't know */
2553
2554 t = id_str;
2555 done =0;
2556
2557 for (i=0; i<=4 && !done; ++i, p+=2) {
2558 while ((data = *p) != '\0') {
2559 if (data == 0xFF) {
2560 done = 1;
2561 break;
2562 }
2563 *t++ = data;
2564 if (t == &id_str[MAX_IDENT_CHARS-1]) {
2565 done = 1;
2566 break;
2567 }
2568 p += 2;
2569 }
2570 if (!done)
2571 *t++ = ' ';
2572 }
2573 *t = '\0';
2574 while (--t > id_str) {
2575 if (*t == ' ')
2576 *t = '\0';
2577 else
2578 break;
2579 }
2580 puts (id_str);
2581 putc ('\n');
2582
2583 for (card=known_cards; *card; ++card) {
2584 debug ("## Compare against \"%s\"\n", *card);
2585 if (strcmp(*card, id_str) == 0) { /* found! */
2586 debug ("## CARD FOUND ##\n");
2587 return (1);
2588 }
2589 }
2590
2591 return (0); /* don't know */
2592}
2593#endif /* CONFIG_IDE_8xx_PCCARD */
2594
wdenk90e7e422002-12-04 23:39:58 +00002595/* -------------------------------------------------------------------- */
wdenkc6097192002-11-03 00:24:07 +00002596
2597#endif /* CFG_CMD_PCMCIA || (CFG_CMD_IDE && CONFIG_IDE_8xx_PCCARD) */
wdenk57b2d802003-06-27 21:31:46 +00002598
2599/**************************************************/
2600
2601#if (CONFIG_COMMANDS & CFG_CMD_PCMCIA)
wdenkf287a242003-07-01 21:06:45 +00002602U_BOOT_CMD(
2603 pinit, 2, 1, do_pinit,
wdenk57b2d802003-06-27 21:31:46 +00002604 "pinit - PCMCIA sub-system\n",
2605 "on - power on PCMCIA socket\n"
2606 "pinit off - power off PCMCIA socket\n"
2607);
2608#endif