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