1 /* 2 * (C) Copyright 2000-2006 3 * Wolfgang Denk, DENX Software Engineering, wd@denx.de. 4 * 5 * SPDX-License-Identifier: GPL-2.0+ 6 * 7 ******************************************************************** 8 * 9 * Lots of code copied from: 10 * 11 * m8xx_pcmcia.c - Linux PCMCIA socket driver for the mpc8xx series. 12 * (C) 1999-2000 Magnus Damm <damm@bitsmart.com> 13 * 14 * "The ExCA standard specifies that socket controllers should provide 15 * two IO and five memory windows per socket, which can be independently 16 * configured and positioned in the host address space and mapped to 17 * arbitrary segments of card address space. " - David A Hinds. 1999 18 * 19 * This controller does _not_ meet the ExCA standard. 20 * 21 * m8xx pcmcia controller brief info: 22 * + 8 windows (attrib, mem, i/o) 23 * + up to two slots (SLOT_A and SLOT_B) 24 * + inputpins, outputpins, event and mask registers. 25 * - no offset register. sigh. 26 * 27 * Because of the lacking offset register we must map the whole card. 28 * We assign each memory window PCMCIA_MEM_WIN_SIZE address space. 29 * Make sure there is (PCMCIA_MEM_WIN_SIZE * PCMCIA_MEM_WIN_NO 30 * * PCMCIA_SOCKETS_NO) bytes at PCMCIA_MEM_WIN_BASE. 31 * The i/o windows are dynamically allocated at PCMCIA_IO_WIN_BASE. 32 * They are maximum 64KByte each... 33 */ 34 35 /* #define DEBUG 1 */ 36 37 /* 38 * PCMCIA support 39 */ 40 #include <common.h> 41 #include <command.h> 42 #include <config.h> 43 #include <pcmcia.h> 44 #include <asm/io.h> 45 46 /* -------------------------------------------------------------------- */ 47 48 #if defined(CONFIG_CMD_PCMCIA) 49 50 extern int pcmcia_on (void); 51 extern int pcmcia_off (void); 52 53 int do_pinit (cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) 54 { 55 int rcode = 0; 56 57 if (argc != 2) { 58 printf ("Usage: pinit {on | off}\n"); 59 return 1; 60 } 61 if (strcmp(argv[1],"on") == 0) { 62 rcode = pcmcia_on (); 63 } else if (strcmp(argv[1],"off") == 0) { 64 rcode = pcmcia_off (); 65 } else { 66 printf ("Usage: pinit {on | off}\n"); 67 return 1; 68 } 69 70 return rcode; 71 } 72 73 U_BOOT_CMD( 74 pinit, 2, 0, do_pinit, 75 "PCMCIA sub-system", 76 "on - power on PCMCIA socket\n" 77 "pinit off - power off PCMCIA socket" 78 ); 79 80 #endif 81 82 /* -------------------------------------------------------------------- */ 83 84 #undef CHECK_IDE_DEVICE 85 86 #if defined(CONFIG_IDE) && defined(CONFIG_IDE_8xx_PCCARD) 87 #define CHECK_IDE_DEVICE 88 #endif 89 90 #if defined(CONFIG_PXA_PCMCIA) 91 #define CHECK_IDE_DEVICE 92 #endif 93 94 #ifdef CHECK_IDE_DEVICE 95 96 int ide_devices_found; 97 static uchar *known_cards[] = { 98 (uchar *)"ARGOSY PnPIDE D5", 99 NULL 100 }; 101 102 #define MAX_TUPEL_SZ 512 103 #define MAX_FEATURES 4 104 105 #define MAX_IDENT_CHARS 64 106 #define MAX_IDENT_FIELDS 4 107 108 #define indent "\t " 109 110 static void print_funcid (int func) 111 { 112 puts (indent); 113 switch (func) { 114 case CISTPL_FUNCID_MULTI: 115 puts (" Multi-Function"); 116 break; 117 case CISTPL_FUNCID_MEMORY: 118 puts (" Memory"); 119 break; 120 case CISTPL_FUNCID_SERIAL: 121 puts (" Serial Port"); 122 break; 123 case CISTPL_FUNCID_PARALLEL: 124 puts (" Parallel Port"); 125 break; 126 case CISTPL_FUNCID_FIXED: 127 puts (" Fixed Disk"); 128 break; 129 case CISTPL_FUNCID_VIDEO: 130 puts (" Video Adapter"); 131 break; 132 case CISTPL_FUNCID_NETWORK: 133 puts (" Network Adapter"); 134 break; 135 case CISTPL_FUNCID_AIMS: 136 puts (" AIMS Card"); 137 break; 138 case CISTPL_FUNCID_SCSI: 139 puts (" SCSI Adapter"); 140 break; 141 default: 142 puts (" Unknown"); 143 break; 144 } 145 puts (" Card\n"); 146 } 147 148 static void print_fixed (volatile uchar *p) 149 { 150 if (p == NULL) 151 return; 152 153 puts(indent); 154 155 switch (*p) { 156 case CISTPL_FUNCE_IDE_IFACE: 157 { uchar iface = *(p+2); 158 159 puts ((iface == CISTPL_IDE_INTERFACE) ? " IDE" : " unknown"); 160 puts (" interface "); 161 break; 162 } 163 case CISTPL_FUNCE_IDE_MASTER: 164 case CISTPL_FUNCE_IDE_SLAVE: 165 { uchar f1 = *(p+2); 166 uchar f2 = *(p+4); 167 168 puts ((f1 & CISTPL_IDE_SILICON) ? " [silicon]" : " [rotating]"); 169 170 if (f1 & CISTPL_IDE_UNIQUE) 171 puts (" [unique]"); 172 173 puts ((f1 & CISTPL_IDE_DUAL) ? " [dual]" : " [single]"); 174 175 if (f2 & CISTPL_IDE_HAS_SLEEP) 176 puts (" [sleep]"); 177 178 if (f2 & CISTPL_IDE_HAS_STANDBY) 179 puts (" [standby]"); 180 181 if (f2 & CISTPL_IDE_HAS_IDLE) 182 puts (" [idle]"); 183 184 if (f2 & CISTPL_IDE_LOW_POWER) 185 puts (" [low power]"); 186 187 if (f2 & CISTPL_IDE_REG_INHIBIT) 188 puts (" [reg inhibit]"); 189 190 if (f2 & CISTPL_IDE_HAS_INDEX) 191 puts (" [index]"); 192 193 if (f2 & CISTPL_IDE_IOIS16) 194 puts (" [IOis16]"); 195 196 break; 197 } 198 } 199 putc ('\n'); 200 } 201 202 static int identify (volatile uchar *p) 203 { 204 uchar id_str[MAX_IDENT_CHARS]; 205 uchar data; 206 uchar *t; 207 uchar **card; 208 int i, done; 209 210 if (p == NULL) 211 return (0); /* Don't know */ 212 213 t = id_str; 214 done =0; 215 216 for (i=0; i<=4 && !done; ++i, p+=2) { 217 while ((data = *p) != '\0') { 218 if (data == 0xFF) { 219 done = 1; 220 break; 221 } 222 *t++ = data; 223 if (t == &id_str[MAX_IDENT_CHARS-1]) { 224 done = 1; 225 break; 226 } 227 p += 2; 228 } 229 if (!done) 230 *t++ = ' '; 231 } 232 *t = '\0'; 233 while (--t > id_str) { 234 if (*t == ' ') 235 *t = '\0'; 236 else 237 break; 238 } 239 puts ((char *)id_str); 240 putc ('\n'); 241 242 for (card=known_cards; *card; ++card) { 243 debug ("## Compare against \"%s\"\n", *card); 244 if (strcmp((char *)*card, (char *)id_str) == 0) { /* found! */ 245 debug ("## CARD FOUND ##\n"); 246 return (1); 247 } 248 } 249 250 return (0); /* don't know */ 251 } 252 253 int check_ide_device (int slot) 254 { 255 volatile uchar *ident = NULL; 256 volatile uchar *feature_p[MAX_FEATURES]; 257 volatile uchar *p, *start, *addr; 258 int n_features = 0; 259 uchar func_id = ~0; 260 uchar code, len; 261 ushort config_base = 0; 262 int found = 0; 263 int i; 264 265 addr = (volatile uchar *)(CONFIG_SYS_PCMCIA_MEM_ADDR + 266 CONFIG_SYS_PCMCIA_MEM_SIZE * (slot * 4)); 267 debug ("PCMCIA MEM: %08lX\n", (ulong)addr); 268 269 start = p = (volatile uchar *) addr; 270 271 while ((p - start) < MAX_TUPEL_SZ) { 272 273 code = *p; p += 2; 274 275 if (code == 0xFF) { /* End of chain */ 276 break; 277 } 278 279 len = *p; p += 2; 280 #if defined(DEBUG) && (DEBUG > 1) 281 { volatile uchar *q = p; 282 printf ("\nTuple code %02x length %d\n\tData:", 283 code, len); 284 285 for (i = 0; i < len; ++i) { 286 printf (" %02x", *q); 287 q+= 2; 288 } 289 } 290 #endif /* DEBUG */ 291 switch (code) { 292 case CISTPL_VERS_1: 293 ident = p + 4; 294 break; 295 case CISTPL_FUNCID: 296 /* Fix for broken SanDisk which may have 0x80 bit set */ 297 func_id = *p & 0x7F; 298 break; 299 case CISTPL_FUNCE: 300 if (n_features < MAX_FEATURES) 301 feature_p[n_features++] = p; 302 break; 303 case CISTPL_CONFIG: 304 config_base = (*(p+6) << 8) + (*(p+4)); 305 debug ("\n## Config_base = %04x ###\n", config_base); 306 default: 307 break; 308 } 309 p += 2 * len; 310 } 311 312 found = identify (ident); 313 314 if (func_id != ((uchar)~0)) { 315 print_funcid (func_id); 316 317 if (func_id == CISTPL_FUNCID_FIXED) 318 found = 1; 319 else 320 return (1); /* no disk drive */ 321 } 322 323 for (i=0; i<n_features; ++i) { 324 print_fixed (feature_p[i]); 325 } 326 327 if (!found) { 328 printf ("unknown card type\n"); 329 return (1); 330 } 331 332 ide_devices_found |= (1 << slot); 333 334 /* set I/O area in config reg -> only valid for ARGOSY D5!!! */ 335 *((uchar *)(addr + config_base)) = 1; 336 #if 0 337 printf("\n## Config_base = %04x ###\n", config_base); 338 printf("Configuration Option Register: %02x @ %x\n", readb(addr + config_base), addr + config_base); 339 printf("Card Configuration and Status Register: %02x\n", readb(addr + config_base + 2)); 340 printf("Pin Replacement Register Register: %02x\n", readb(addr + config_base + 4)); 341 printf("Socket and Copy Register: %02x\n", readb(addr + config_base + 6)); 342 #endif 343 return (0); 344 } 345 346 #endif /* CHECK_IDE_DEVICE */ 347