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_PXA_PCMCIA) 87 #define CHECK_IDE_DEVICE 88 #endif 89 90 #ifdef CHECK_IDE_DEVICE 91 92 int ide_devices_found; 93 static uchar *known_cards[] = { 94 (uchar *)"ARGOSY PnPIDE D5", 95 NULL 96 }; 97 98 #define MAX_TUPEL_SZ 512 99 #define MAX_FEATURES 4 100 101 #define MAX_IDENT_CHARS 64 102 #define MAX_IDENT_FIELDS 4 103 104 #define indent "\t " 105 106 static void print_funcid (int func) 107 { 108 puts (indent); 109 switch (func) { 110 case CISTPL_FUNCID_MULTI: 111 puts (" Multi-Function"); 112 break; 113 case CISTPL_FUNCID_MEMORY: 114 puts (" Memory"); 115 break; 116 case CISTPL_FUNCID_SERIAL: 117 puts (" Serial Port"); 118 break; 119 case CISTPL_FUNCID_PARALLEL: 120 puts (" Parallel Port"); 121 break; 122 case CISTPL_FUNCID_FIXED: 123 puts (" Fixed Disk"); 124 break; 125 case CISTPL_FUNCID_VIDEO: 126 puts (" Video Adapter"); 127 break; 128 case CISTPL_FUNCID_NETWORK: 129 puts (" Network Adapter"); 130 break; 131 case CISTPL_FUNCID_AIMS: 132 puts (" AIMS Card"); 133 break; 134 case CISTPL_FUNCID_SCSI: 135 puts (" SCSI Adapter"); 136 break; 137 default: 138 puts (" Unknown"); 139 break; 140 } 141 puts (" Card\n"); 142 } 143 144 static void print_fixed (volatile uchar *p) 145 { 146 if (p == NULL) 147 return; 148 149 puts(indent); 150 151 switch (*p) { 152 case CISTPL_FUNCE_IDE_IFACE: 153 { uchar iface = *(p+2); 154 155 puts ((iface == CISTPL_IDE_INTERFACE) ? " IDE" : " unknown"); 156 puts (" interface "); 157 break; 158 } 159 case CISTPL_FUNCE_IDE_MASTER: 160 case CISTPL_FUNCE_IDE_SLAVE: 161 { uchar f1 = *(p+2); 162 uchar f2 = *(p+4); 163 164 puts ((f1 & CISTPL_IDE_SILICON) ? " [silicon]" : " [rotating]"); 165 166 if (f1 & CISTPL_IDE_UNIQUE) 167 puts (" [unique]"); 168 169 puts ((f1 & CISTPL_IDE_DUAL) ? " [dual]" : " [single]"); 170 171 if (f2 & CISTPL_IDE_HAS_SLEEP) 172 puts (" [sleep]"); 173 174 if (f2 & CISTPL_IDE_HAS_STANDBY) 175 puts (" [standby]"); 176 177 if (f2 & CISTPL_IDE_HAS_IDLE) 178 puts (" [idle]"); 179 180 if (f2 & CISTPL_IDE_LOW_POWER) 181 puts (" [low power]"); 182 183 if (f2 & CISTPL_IDE_REG_INHIBIT) 184 puts (" [reg inhibit]"); 185 186 if (f2 & CISTPL_IDE_HAS_INDEX) 187 puts (" [index]"); 188 189 if (f2 & CISTPL_IDE_IOIS16) 190 puts (" [IOis16]"); 191 192 break; 193 } 194 } 195 putc ('\n'); 196 } 197 198 static int identify (volatile uchar *p) 199 { 200 uchar id_str[MAX_IDENT_CHARS]; 201 uchar data; 202 uchar *t; 203 uchar **card; 204 int i, done; 205 206 if (p == NULL) 207 return (0); /* Don't know */ 208 209 t = id_str; 210 done =0; 211 212 for (i=0; i<=4 && !done; ++i, p+=2) { 213 while ((data = *p) != '\0') { 214 if (data == 0xFF) { 215 done = 1; 216 break; 217 } 218 *t++ = data; 219 if (t == &id_str[MAX_IDENT_CHARS-1]) { 220 done = 1; 221 break; 222 } 223 p += 2; 224 } 225 if (!done) 226 *t++ = ' '; 227 } 228 *t = '\0'; 229 while (--t > id_str) { 230 if (*t == ' ') 231 *t = '\0'; 232 else 233 break; 234 } 235 puts ((char *)id_str); 236 putc ('\n'); 237 238 for (card=known_cards; *card; ++card) { 239 debug ("## Compare against \"%s\"\n", *card); 240 if (strcmp((char *)*card, (char *)id_str) == 0) { /* found! */ 241 debug ("## CARD FOUND ##\n"); 242 return (1); 243 } 244 } 245 246 return (0); /* don't know */ 247 } 248 249 int check_ide_device (int slot) 250 { 251 volatile uchar *ident = NULL; 252 volatile uchar *feature_p[MAX_FEATURES]; 253 volatile uchar *p, *start, *addr; 254 int n_features = 0; 255 uchar func_id = ~0; 256 uchar code, len; 257 ushort config_base = 0; 258 int found = 0; 259 int i; 260 261 addr = (volatile uchar *)(CONFIG_SYS_PCMCIA_MEM_ADDR + 262 CONFIG_SYS_PCMCIA_MEM_SIZE * (slot * 4)); 263 debug ("PCMCIA MEM: %08lX\n", (ulong)addr); 264 265 start = p = (volatile uchar *) addr; 266 267 while ((p - start) < MAX_TUPEL_SZ) { 268 269 code = *p; p += 2; 270 271 if (code == 0xFF) { /* End of chain */ 272 break; 273 } 274 275 len = *p; p += 2; 276 #if defined(DEBUG) && (DEBUG > 1) 277 { volatile uchar *q = p; 278 printf ("\nTuple code %02x length %d\n\tData:", 279 code, len); 280 281 for (i = 0; i < len; ++i) { 282 printf (" %02x", *q); 283 q+= 2; 284 } 285 } 286 #endif /* DEBUG */ 287 switch (code) { 288 case CISTPL_VERS_1: 289 ident = p + 4; 290 break; 291 case CISTPL_FUNCID: 292 /* Fix for broken SanDisk which may have 0x80 bit set */ 293 func_id = *p & 0x7F; 294 break; 295 case CISTPL_FUNCE: 296 if (n_features < MAX_FEATURES) 297 feature_p[n_features++] = p; 298 break; 299 case CISTPL_CONFIG: 300 config_base = (*(p+6) << 8) + (*(p+4)); 301 debug ("\n## Config_base = %04x ###\n", config_base); 302 default: 303 break; 304 } 305 p += 2 * len; 306 } 307 308 found = identify (ident); 309 310 if (func_id != ((uchar)~0)) { 311 print_funcid (func_id); 312 313 if (func_id == CISTPL_FUNCID_FIXED) 314 found = 1; 315 else 316 return (1); /* no disk drive */ 317 } 318 319 for (i=0; i<n_features; ++i) { 320 print_fixed (feature_p[i]); 321 } 322 323 if (!found) { 324 printf ("unknown card type\n"); 325 return (1); 326 } 327 328 ide_devices_found |= (1 << slot); 329 330 /* set I/O area in config reg -> only valid for ARGOSY D5!!! */ 331 *((uchar *)(addr + config_base)) = 1; 332 #if 0 333 printf("\n## Config_base = %04x ###\n", config_base); 334 printf("Configuration Option Register: %02x @ %x\n", readb(addr + config_base), addr + config_base); 335 printf("Card Configuration and Status Register: %02x\n", readb(addr + config_base + 2)); 336 printf("Pin Replacement Register Register: %02x\n", readb(addr + config_base + 4)); 337 printf("Socket and Copy Register: %02x\n", readb(addr + config_base + 6)); 338 #endif 339 return (0); 340 } 341 342 #endif /* CHECK_IDE_DEVICE */ 343