uboot/drivers/pcmcia/mpc8xx_pcmcia.c
<<
>>
Prefs
   1#include <common.h>
   2#include <mpc8xx.h>
   3#include <pcmcia.h>
   4#include <linux/compiler.h>
   5
   6#undef  CONFIG_PCMCIA
   7
   8#if defined(CONFIG_CMD_PCMCIA)
   9#define CONFIG_PCMCIA
  10#endif
  11
  12#if defined(CONFIG_CMD_IDE) && defined(CONFIG_IDE_8xx_PCCARD)
  13#define CONFIG_PCMCIA
  14#endif
  15
  16#if defined(CONFIG_PCMCIA)
  17
  18#if     defined(CONFIG_IDE_8xx_PCCARD)
  19extern int check_ide_device (int slot);
  20#endif
  21
  22extern int pcmcia_hardware_enable (int slot);
  23extern int pcmcia_voltage_set(int slot, int vcc, int vpp);
  24
  25#if defined(CONFIG_CMD_PCMCIA)
  26extern int pcmcia_hardware_disable(int slot);
  27#endif
  28
  29static u_int m8xx_get_graycode(u_int size);
  30#if 0 /* Disabled */
  31static u_int m8xx_get_speed(u_int ns, u_int is_io);
  32#endif
  33
  34/* look up table for pgcrx registers */
  35u_int *pcmcia_pgcrx[2] = {
  36        &((immap_t *)CONFIG_SYS_IMMR)->im_pcmcia.pcmc_pgcra,
  37        &((immap_t *)CONFIG_SYS_IMMR)->im_pcmcia.pcmc_pgcrb,
  38};
  39
  40/*
  41 * Search this table to see if the windowsize is
  42 * supported...
  43 */
  44
  45#define M8XX_SIZES_NO 32
  46
  47static const u_int m8xx_size_to_gray[M8XX_SIZES_NO] =
  48{ 0x00000001, 0x00000002, 0x00000008, 0x00000004,
  49  0x00000080, 0x00000040, 0x00000010, 0x00000020,
  50  0x00008000, 0x00004000, 0x00001000, 0x00002000,
  51  0x00000100, 0x00000200, 0x00000800, 0x00000400,
  52
  53  0x0fffffff, 0xffffffff, 0xffffffff, 0xffffffff,
  54  0x01000000, 0x02000000, 0xffffffff, 0x04000000,
  55  0x00010000, 0x00020000, 0x00080000, 0x00040000,
  56  0x00800000, 0x00400000, 0x00100000, 0x00200000 };
  57
  58
  59/* -------------------------------------------------------------------- */
  60
  61#define CONFIG_SYS_PCMCIA_TIMING        (       PCMCIA_SHT(2)   \
  62                                |       PCMCIA_SST(4)   \
  63                                |       PCMCIA_SL(9))
  64
  65/* -------------------------------------------------------------------- */
  66
  67int pcmcia_on (void)
  68{
  69        u_long reg, base;
  70        pcmcia_win_t *win;
  71        u_int rc, slot;
  72        __maybe_unused u_int slotbit;
  73        int i;
  74
  75        debug ("Enable PCMCIA " PCMCIA_SLOT_MSG "\n");
  76
  77        /* intialize the fixed memory windows */
  78        win = (pcmcia_win_t *)(&((immap_t *)CONFIG_SYS_IMMR)->im_pcmcia.pcmc_pbr0);
  79        base = CONFIG_SYS_PCMCIA_MEM_ADDR;
  80
  81        if((reg = m8xx_get_graycode(CONFIG_SYS_PCMCIA_MEM_SIZE)) == -1) {
  82                printf ("Cannot set window size to 0x%08x\n",
  83                        CONFIG_SYS_PCMCIA_MEM_SIZE);
  84                return (1);
  85        }
  86
  87        slotbit = PCMCIA_SLOT_x;
  88        for (i=0; i<PCMCIA_MEM_WIN_NO; ++i) {
  89                win->br = base;
  90
  91#if     (PCMCIA_SOCKETS_NO == 2)
  92                if (i == 4) /* Another slot starting from win 4 */
  93                        slotbit = (slotbit ? PCMCIA_PSLOT_A : PCMCIA_PSLOT_B);
  94#endif
  95                switch (i) {
  96#ifdef  CONFIG_IDE_8xx_PCCARD
  97                case 4:
  98                case 0: {       /* map attribute memory */
  99                        win->or = (     PCMCIA_BSIZE_64M
 100                                |       PCMCIA_PPS_8
 101                                |       PCMCIA_PRS_ATTR
 102                                |       slotbit
 103                                |       PCMCIA_PV
 104                                |       CONFIG_SYS_PCMCIA_TIMING );
 105                        break;
 106                }
 107                case 5:
 108                case 1: {       /* map I/O window for data reg */
 109                        win->or = (     PCMCIA_BSIZE_1K
 110                                |       PCMCIA_PPS_16
 111                                |       PCMCIA_PRS_IO
 112                                |       slotbit
 113                                |       PCMCIA_PV
 114                                |       CONFIG_SYS_PCMCIA_TIMING );
 115                        break;
 116                }
 117                case 6:
 118                case 2: {       /* map I/O window for cmd/ctrl reg block */
 119                        win->or = (     PCMCIA_BSIZE_1K
 120                                |       PCMCIA_PPS_8
 121                                |       PCMCIA_PRS_IO
 122                                |       slotbit
 123                                |       PCMCIA_PV
 124                                |       CONFIG_SYS_PCMCIA_TIMING );
 125                        break;
 126                }
 127#endif  /* CONFIG_IDE_8xx_PCCARD */
 128                default:        /* set to not valid */
 129                        win->or = 0;
 130                        break;
 131                }
 132
 133                debug ("MemWin %d: PBR 0x%08lX  POR %08lX\n",
 134                       i, win->br, win->or);
 135                base += CONFIG_SYS_PCMCIA_MEM_SIZE;
 136                ++win;
 137        }
 138
 139        for (i=0, rc=0, slot=_slot_; i<PCMCIA_SOCKETS_NO; i++, slot = !slot) {
 140                /* turn off voltage */
 141                if ((rc = pcmcia_voltage_set(slot, 0, 0)))
 142                        continue;
 143
 144                /* Enable external hardware */
 145                if ((rc = pcmcia_hardware_enable(slot)))
 146                        continue;
 147
 148#ifdef  CONFIG_IDE_8xx_PCCARD
 149                if ((rc = check_ide_device(i)))
 150                        continue;
 151#endif
 152        }
 153        return rc;
 154}
 155
 156#if defined(CONFIG_CMD_PCMCIA)
 157int pcmcia_off (void)
 158{
 159        int i;
 160        pcmcia_win_t *win;
 161
 162        printf ("Disable PCMCIA " PCMCIA_SLOT_MSG "\n");
 163
 164        /* clear interrupt state, and disable interrupts */
 165        ((immap_t *)CONFIG_SYS_IMMR)->im_pcmcia.pcmc_pscr =  PCMCIA_MASK(_slot_);
 166        ((immap_t *)CONFIG_SYS_IMMR)->im_pcmcia.pcmc_per &= ~PCMCIA_MASK(_slot_);
 167
 168        /* turn off interrupt and disable CxOE */
 169        PCMCIA_PGCRX(_slot_) = __MY_PCMCIA_GCRX_CXOE;
 170
 171        /* turn off memory windows */
 172        win = (pcmcia_win_t *)(&((immap_t *)CONFIG_SYS_IMMR)->im_pcmcia.pcmc_pbr0);
 173
 174        for (i=0; i<PCMCIA_MEM_WIN_NO; ++i) {
 175                /* disable memory window */
 176                win->or = 0;
 177                ++win;
 178        }
 179
 180        /* turn off voltage */
 181        pcmcia_voltage_set(_slot_, 0, 0);
 182
 183        /* disable external hardware */
 184        printf ("Shutdown and Poweroff " PCMCIA_SLOT_MSG "\n");
 185        pcmcia_hardware_disable(_slot_);
 186        return 0;
 187}
 188#endif
 189
 190
 191static u_int m8xx_get_graycode(u_int size)
 192{
 193        u_int k;
 194
 195        for (k = 0; k < M8XX_SIZES_NO; k++) {
 196                if(m8xx_size_to_gray[k] == size)
 197                        break;
 198        }
 199
 200        if((k == M8XX_SIZES_NO) || (m8xx_size_to_gray[k] == -1))
 201                k = -1;
 202
 203        return k;
 204}
 205
 206#if     0
 207
 208static u_int m8xx_get_speed(u_int ns, u_int is_io)
 209{
 210        u_int reg, clocks, psst, psl, psht;
 211
 212        if(!ns) {
 213
 214                /*
 215                * We get called with IO maps setup to 0ns
 216                * if not specified by the user.
 217                * They should be 255ns.
 218                */
 219
 220                if(is_io)
 221                        ns = 255;
 222                else
 223                        ns = 100;  /* fast memory if 0 */
 224        }
 225
 226        /*
 227        * In PSST, PSL, PSHT fields we tell the controller
 228        * timing parameters in CLKOUT clock cycles.
 229        * CLKOUT is the same as GCLK2_50.
 230        */
 231
 232        /* how we want to adjust the timing - in percent */
 233
 234#define ADJ 180 /* 80 % longer accesstime - to be sure */
 235
 236        clocks = ((M8XX_BUSFREQ / 1000) * ns) / 1000;
 237        clocks = (clocks * ADJ) / (100*1000);
 238
 239        if(clocks >= PCMCIA_BMT_LIMIT) {
 240                DEBUG(0, "Max access time limit reached\n");
 241                clocks = PCMCIA_BMT_LIMIT-1;
 242        }
 243
 244        psst = clocks / 7;          /* setup time */
 245        psht = clocks / 7;          /* hold time */
 246        psl  = (clocks * 5) / 7;    /* strobe length */
 247
 248        psst += clocks - (psst + psht + psl);
 249
 250        reg =  psst << 12;
 251        reg |= psl  << 7;
 252        reg |= psht << 16;
 253
 254        return reg;
 255}
 256#endif  /* 0 */
 257
 258#endif  /* CONFIG_PCMCIA */
 259