uboot/drivers/pcmcia/tqm8xx_pcmcia.c
<<
>>
Prefs
   1/* -------------------------------------------------------------------- */
   2/* TQM8xxL Boards by TQ Components                                      */
   3/* SC8xx   Boards by SinoVee Microsystems                               */
   4/* -------------------------------------------------------------------- */
   5#include <common.h>
   6#include <asm/io.h>
   7#ifdef CONFIG_8xx
   8#include <mpc8xx.h>
   9#endif
  10#include <pcmcia.h>
  11
  12#undef  CONFIG_PCMCIA
  13
  14#if defined(CONFIG_CMD_PCMCIA)
  15#define CONFIG_PCMCIA
  16#endif
  17
  18#if defined(CONFIG_CMD_IDE) && defined(CONFIG_IDE_8xx_PCCARD)
  19#define CONFIG_PCMCIA
  20#endif
  21
  22#if     defined(CONFIG_PCMCIA)  \
  23        && defined(CONFIG_TQM8xxL)
  24
  25#if     defined(CONFIG_TQM8xxL)
  26#define PCMCIA_BOARD_MSG        "TQM8xxL"
  27#endif
  28
  29static inline void power_config(int slot)
  30{
  31        immap_t *immap = (immap_t *)CONFIG_SYS_IMMR;
  32        /*
  33         * Configure Port C pins for
  34         * 5 Volts Enable and 3 Volts enable
  35         */
  36        clrbits_be16(&immap->im_ioport.iop_pcpar, 0x0002 | 0x0004);
  37        clrbits_be16(&immap->im_ioport.iop_pcso, 0x0002 | 0x0004);
  38}
  39
  40static inline void power_off(int slot)
  41{
  42        immap_t *immap = (immap_t *)CONFIG_SYS_IMMR;
  43        clrbits_be16(&immap->im_ioport.iop_pcdat, 0x0002 | 0x0004);
  44}
  45
  46static inline void power_on_5_0(int slot)
  47{
  48        immap_t *immap = (immap_t *)CONFIG_SYS_IMMR;
  49        setbits_be16(&immap->im_ioport.iop_pcdat, 0x0004);
  50        setbits_be16(&immap->im_ioport.iop_pcdir, 0x0002 | 0x0004);
  51}
  52
  53static inline void power_on_3_3(int slot)
  54{
  55        immap_t *immap = (immap_t *)CONFIG_SYS_IMMR;
  56        setbits_be16(&immap->im_ioport.iop_pcdat, 0x0002);
  57        setbits_be16(&immap->im_ioport.iop_pcdir, 0x0002 | 0x0004);
  58}
  59
  60/*
  61 * Function to retrieve the PIPR register, used for debuging purposes.
  62 */
  63static inline uint32_t debug_get_pipr(void)
  64{
  65        uint32_t pipr = 0;
  66#ifdef  DEBUG
  67        immap_t *immap = (immap_t *)CONFIG_SYS_IMMR;
  68        pipr = in_be32(&immap->im_pcmcia.pcmc_pipr);
  69#endif
  70        return pipr;
  71}
  72
  73
  74static inline int check_card_is_absent(int slot)
  75{
  76        immap_t *immap = (immap_t *)CONFIG_SYS_IMMR;
  77        uint32_t pipr = in_be32(&immap->im_pcmcia.pcmc_pipr);
  78        return pipr & (0x18000000 >> (slot << 4));
  79}
  80
  81#define NSCU_GCRX_CXOE  __MY_PCMCIA_GCRX_CXOE
  82
  83int pcmcia_hardware_enable(int slot)
  84{
  85        immap_t *immap = (immap_t *)CONFIG_SYS_IMMR;
  86        uint reg, mask;
  87
  88        debug("hardware_enable: " PCMCIA_BOARD_MSG " Slot %c\n", 'A'+slot);
  89
  90        udelay(10000);
  91
  92        /*
  93         * Configure SIUMCR to enable PCMCIA port B
  94         * (VFLS[0:1] are not used for debugging, we connect FRZ# instead)
  95         */
  96
  97        /* Set DBGC to 00 */
  98        clrbits_be32(&immap->im_siu_conf.sc_siumcr, SIUMCR_DBGC11);
  99
 100        /* Clear interrupt state, and disable interrupts */
 101        out_be32(&immap->im_pcmcia.pcmc_pscr, PCMCIA_MASK(slot));
 102        clrbits_be32(&immap->im_pcmcia.pcmc_per, PCMCIA_MASK(slot));
 103
 104        /*
 105         * Disable interrupts, DMA, and PCMCIA buffers
 106         * (isolate the interface) and assert RESET signal
 107         */
 108        debug("Disable PCMCIA buffers and assert RESET\n");
 109        reg  = 0;
 110        reg |= __MY_PCMCIA_GCRX_CXRESET;        /* active high */
 111        reg |= NSCU_GCRX_CXOE;
 112
 113        PCMCIA_PGCRX(slot) = reg;
 114        udelay(500);
 115
 116        power_config(slot);
 117        power_off(slot);
 118
 119        /*
 120         * Make sure there is a card in the slot, then configure the interface.
 121        */
 122        udelay(10000);
 123        reg = debug_get_pipr();
 124        debug("[%d] %s: PIPR(%p)=0x%x\n", __LINE__, __FUNCTION__,
 125                &immap->im_pcmcia.pcmc_pipr, reg);
 126
 127        if (check_card_is_absent(slot)) {
 128                printf ("   No Card found\n");
 129                return (1);
 130        }
 131
 132        /*
 133         * Power On.
 134         */
 135        mask = PCMCIA_VS1(slot) | PCMCIA_VS2(slot);
 136        reg = in_be32(&immap->im_pcmcia.pcmc_pipr);
 137        debug ("PIPR: 0x%x ==> VS1=o%s, VS2=o%s\n",
 138               reg,
 139               (reg & PCMCIA_VS1(slot)) ? "n" : "ff",
 140               (reg & PCMCIA_VS2(slot)) ? "n" : "ff");
 141
 142        if ((reg & mask) == mask) {
 143                power_on_5_0(slot);
 144                puts (" 5.0V card found: ");
 145        } else {
 146                power_on_3_3(slot);
 147                puts (" 3.3V card found: ");
 148        }
 149
 150#if 0
 151        /*  VCC switch error flag, PCMCIA slot INPACK_ pin */
 152        cp->cp_pbdir &= ~(0x0020 | 0x0010);
 153        cp->cp_pbpar &= ~(0x0020 | 0x0010);
 154        udelay(500000);
 155#endif
 156
 157        udelay(1000);
 158        debug("Enable PCMCIA buffers and stop RESET\n");
 159        reg  =  PCMCIA_PGCRX(slot);
 160        reg &= ~__MY_PCMCIA_GCRX_CXRESET;       /* active high */
 161        reg |= __MY_PCMCIA_GCRX_CXOE;           /* active low  */
 162        reg &= ~NSCU_GCRX_CXOE;
 163
 164        PCMCIA_PGCRX(slot) = reg;
 165
 166        udelay(250000); /* some cards need >150 ms to come up :-( */
 167
 168        debug("# hardware_enable done\n");
 169
 170        return (0);
 171}
 172
 173
 174#if defined(CONFIG_CMD_PCMCIA)
 175int pcmcia_hardware_disable(int slot)
 176{
 177        u_long reg;
 178
 179        debug("hardware_disable: " PCMCIA_BOARD_MSG " Slot %c\n", 'A'+slot);
 180
 181        /* remove all power */
 182        power_off(slot);
 183
 184        debug("Disable PCMCIA buffers and assert RESET\n");
 185        reg  = 0;
 186        reg |= __MY_PCMCIA_GCRX_CXRESET;        /* active high */
 187        reg |= NSCU_GCRX_CXOE;                  /* active low  */
 188
 189        PCMCIA_PGCRX(slot) = reg;
 190
 191        udelay(10000);
 192
 193        return (0);
 194}
 195#endif
 196
 197int pcmcia_voltage_set(int slot, int vcc, int vpp)
 198{
 199        u_long reg;
 200        uint32_t pipr = 0;
 201
 202        debug("voltage_set: " PCMCIA_BOARD_MSG
 203                " Slot %c, Vcc=%d.%d, Vpp=%d.%d\n",
 204                'A'+slot, vcc/10, vcc%10, vpp/10, vcc%10);
 205
 206        /*
 207         * Disable PCMCIA buffers (isolate the interface)
 208         * and assert RESET signal
 209         */
 210        debug("Disable PCMCIA buffers and assert RESET\n");
 211        reg  = PCMCIA_PGCRX(slot);
 212        reg |= __MY_PCMCIA_GCRX_CXRESET;        /* active high */
 213        reg &= ~__MY_PCMCIA_GCRX_CXOE;          /* active low  */
 214        reg |= NSCU_GCRX_CXOE;                  /* active low  */
 215
 216        PCMCIA_PGCRX(slot) = reg;
 217        udelay(500);
 218
 219        debug("PCMCIA power OFF\n");
 220        power_config(slot);
 221        power_off(slot);
 222
 223        switch(vcc) {
 224                case  0:                        break;
 225                case 33: power_on_3_3(slot);    break;
 226                case 50: power_on_5_0(slot);    break;
 227                default:                        goto done;
 228        }
 229
 230        /* Checking supported voltages */
 231        pipr = debug_get_pipr();
 232        debug("PIPR: 0x%x --> %s\n", pipr,
 233               (pipr & 0x00008000) ? "only 5 V" : "can do 3.3V");
 234
 235        if (vcc)
 236                debug("PCMCIA powered at %sV\n", (vcc == 50) ? "5.0" : "3.3");
 237        else
 238                debug("PCMCIA powered down\n");
 239
 240done:
 241        debug("Enable PCMCIA buffers and stop RESET\n");
 242        reg  =  PCMCIA_PGCRX(slot);
 243        reg &= ~__MY_PCMCIA_GCRX_CXRESET;       /* active high */
 244        reg |= __MY_PCMCIA_GCRX_CXOE;           /* active low  */
 245        reg &= ~NSCU_GCRX_CXOE;                 /* active low  */
 246
 247        PCMCIA_PGCRX(slot) = reg;
 248        udelay(500);
 249
 250        debug("voltage_set: " PCMCIA_BOARD_MSG " Slot %c, DONE\n", slot+'A');
 251        return 0;
 252}
 253
 254#endif  /* CONFIG_PCMCIA && CONFIG_TQM8xxL */
 255