uboot/board/icu862/pcmcia.c
<<
>>
Prefs
   1#include <common.h>
   2#include <mpc8xx.h>
   3#include <pcmcia.h>
   4
   5#undef  CONFIG_PCMCIA
   6
   7#if defined(CONFIG_CMD_PCMCIA)
   8#define CONFIG_PCMCIA
   9#endif
  10
  11#if defined(CONFIG_CMD_IDE) && defined(CONFIG_IDE_8xx_PCCARD)
  12#define CONFIG_PCMCIA
  13#endif
  14
  15#ifdef  CONFIG_PCMCIA
  16
  17#define PCMCIA_BOARD_MSG "ICU862"
  18
  19static void cfg_port_B (void)
  20{
  21        volatile immap_t        *immap;
  22        volatile cpm8xx_t       *cp;
  23        uint reg;
  24
  25        immap = (immap_t *)CONFIG_SYS_IMMR;
  26        cp    = (cpm8xx_t *)(&(((immap_t *)CONFIG_SYS_IMMR)->im_cpm));
  27
  28        /*
  29        * Configure Port B for TPS2205 PC-Card Power-Interface Switch
  30        *
  31        * Switch off all voltages, assert shutdown
  32        */
  33        reg  = cp->cp_pbdat;
  34        reg |= (TPS2205_VPP_PGM | TPS2205_VPP_VCC |     /* VAVPP => Hi-Z */
  35                        TPS2205_VCC3    | TPS2205_VCC5    |     /* VAVCC => Hi-Z */
  36                        TPS2205_SHDN);                          /* enable switch */
  37        cp->cp_pbdat = reg;
  38
  39        cp->cp_pbpar &= ~(TPS2205_INPUTS | TPS2205_OUTPUTS);
  40
  41        reg = cp->cp_pbdir & ~(TPS2205_INPUTS);
  42        cp->cp_pbdir = reg | TPS2205_OUTPUTS;
  43
  44        debug ("Set Port B: PAR: %08x DIR: %08x DAT: %08x\n",
  45               cp->cp_pbpar, cp->cp_pbdir, cp->cp_pbdat);
  46}
  47
  48int pcmcia_hardware_enable(int slot)
  49{
  50        volatile immap_t        *immap;
  51        volatile cpm8xx_t       *cp;
  52        volatile pcmconf8xx_t   *pcmp;
  53        volatile sysconf8xx_t   *sysp;
  54        uint reg, pipr, mask;
  55        int i;
  56
  57        debug ("hardware_enable: " PCMCIA_BOARD_MSG " Slot %c\n", 'A'+slot);
  58
  59        udelay(10000);
  60
  61        immap = (immap_t *)CONFIG_SYS_IMMR;
  62        sysp  = (sysconf8xx_t *)(&(((immap_t *)CONFIG_SYS_IMMR)->im_siu_conf));
  63        pcmp  = (pcmconf8xx_t *)(&(((immap_t *)CONFIG_SYS_IMMR)->im_pcmcia));
  64        cp    = (cpm8xx_t *)(&(((immap_t *)CONFIG_SYS_IMMR)->im_cpm));
  65
  66        /* Configure Port B for TPS2205 PC-Card Power-Interface Switch */
  67        cfg_port_B ();
  68
  69        /*
  70        * Configure SIUMCR to enable PCMCIA port B
  71        * (VFLS[0:1] are not used for debugging, we connect FRZ# instead)
  72        */
  73        sysp->sc_siumcr &= ~SIUMCR_DBGC11;      /* set DBGC to 00 */
  74
  75        /* clear interrupt state, and disable interrupts */
  76        pcmp->pcmc_pscr =  PCMCIA_MASK(_slot_);
  77        pcmp->pcmc_per &= ~PCMCIA_MASK(_slot_);
  78
  79        /*
  80        * Disable interrupts, DMA, and PCMCIA buffers
  81        * (isolate the interface) and assert RESET signal
  82        */
  83        debug ("Disable PCMCIA buffers and assert RESET\n");
  84        reg  = 0;
  85        reg |= __MY_PCMCIA_GCRX_CXRESET;        /* active high */
  86        reg |= __MY_PCMCIA_GCRX_CXOE;           /* active low  */
  87        PCMCIA_PGCRX(_slot_) = reg;
  88        udelay(500);
  89
  90        /*
  91        * Make sure there is a card in the slot, then configure the interface.
  92        */
  93        udelay(10000);
  94        debug ("[%d] %s: PIPR(%p)=0x%x\n",
  95               __LINE__,__FUNCTION__,
  96               &(pcmp->pcmc_pipr),pcmp->pcmc_pipr);
  97        if (pcmp->pcmc_pipr & (0x18000000 >> (slot << 4))) {
  98                printf ("   No Card found\n");
  99                return (1);
 100        }
 101
 102        /*
 103        * Power On: Set VAVCC to 3.3V or 5V, set VAVPP to Hi-Z
 104        */
 105        mask = PCMCIA_VS1(slot) | PCMCIA_VS2(slot);
 106        pipr = pcmp->pcmc_pipr;
 107        debug ("PIPR: 0x%x ==> VS1=o%s, VS2=o%s\n",
 108               pipr,
 109               (reg&PCMCIA_VS1(slot))?"n":"ff",
 110               (reg&PCMCIA_VS2(slot))?"n":"ff");
 111
 112        reg  = cp->cp_pbdat;
 113        if ((pipr & mask) == mask) {
 114                reg |= (TPS2205_VPP_PGM | TPS2205_VPP_VCC |     /* VAVPP => Hi-Z */
 115                                TPS2205_VCC3);                          /* 3V off       */
 116                reg &= ~(TPS2205_VCC5);                         /* 5V on        */
 117                puts (" 5.0V card found: ");
 118        } else {
 119                reg |= (TPS2205_VPP_PGM | TPS2205_VPP_VCC |     /* VAVPP => Hi-Z */
 120                                TPS2205_VCC5);                          /* 5V off       */
 121                reg &= ~(TPS2205_VCC3);                         /* 3V on        */
 122                puts (" 3.3V card found: ");
 123        }
 124
 125        debug ("\nPB DAT: %08x -> 3.3V %s 5.0V %s VPP_PGM %s VPP_VCC %s\n",
 126               reg,
 127               (reg & TPS2205_VCC3)    ? "off" : "on",
 128               (reg & TPS2205_VCC5)    ? "off" : "on",
 129               (reg & TPS2205_VPP_PGM) ? "off" : "on",
 130               (reg & TPS2205_VPP_VCC) ? "off" : "on" );
 131
 132        cp->cp_pbdat = reg;
 133
 134        /*  Wait 500 ms; use this to check for over-current */
 135        for (i=0; i<5000; ++i) {
 136                if ((cp->cp_pbdat & TPS2205_OC) == 0) {
 137                        printf ("   *** Overcurrent - Safety shutdown ***\n");
 138                        cp->cp_pbdat &= ~(TPS2205_SHDN);
 139                        return (1);
 140                }
 141                udelay (100);
 142        }
 143
 144        debug ("Enable PCMCIA buffers and stop RESET\n");
 145        reg  =  PCMCIA_PGCRX(_slot_);
 146        reg &= ~__MY_PCMCIA_GCRX_CXRESET;       /* active high */
 147        reg &= ~__MY_PCMCIA_GCRX_CXOE;          /* active low  */
 148        PCMCIA_PGCRX(_slot_) = reg;
 149
 150        udelay(250000); /* some cards need >150 ms to come up :-( */
 151
 152        debug ("# hardware_enable done\n");
 153
 154        return (0);
 155}
 156
 157
 158#if defined(CONFIG_CMD_PCMCIA)
 159int pcmcia_hardware_disable(int slot)
 160{
 161        volatile immap_t        *immap;
 162        volatile cpm8xx_t       *cp;
 163        volatile pcmconf8xx_t   *pcmp;
 164        u_long reg;
 165
 166        debug ("hardware_disable: " PCMCIA_BOARD_MSG " Slot %c\n", 'A'+slot);
 167
 168        immap = (immap_t *)CONFIG_SYS_IMMR;
 169        cp    = (cpm8xx_t *)(&(((immap_t *)CONFIG_SYS_IMMR)->im_cpm));
 170        pcmp  = (pcmconf8xx_t *)(&(((immap_t *)CONFIG_SYS_IMMR)->im_pcmcia));
 171
 172        /* Shut down */
 173        cp->cp_pbdat &= ~(TPS2205_SHDN);
 174
 175        /* Configure PCMCIA General Control Register */
 176        debug ("Disable PCMCIA buffers and assert RESET\n");
 177        reg  = 0;
 178        reg |= __MY_PCMCIA_GCRX_CXRESET;        /* active high */
 179        reg |= __MY_PCMCIA_GCRX_CXOE;           /* active low  */
 180        PCMCIA_PGCRX(_slot_) = reg;
 181
 182        udelay(10000);
 183
 184        return (0);
 185}
 186#endif
 187
 188
 189int pcmcia_voltage_set(int slot, int vcc, int vpp)
 190{
 191        volatile immap_t        *immap;
 192        volatile cpm8xx_t       *cp;
 193        volatile pcmconf8xx_t   *pcmp;
 194        u_long reg;
 195
 196        debug ("voltage_set: "
 197                        PCMCIA_BOARD_MSG
 198                        " Slot %c, Vcc=%d.%d, Vpp=%d.%d\n",
 199        'A'+slot, vcc/10, vcc%10, vpp/10, vcc%10);
 200
 201        immap = (immap_t *)CONFIG_SYS_IMMR;
 202        cp    = (cpm8xx_t *)(&(((immap_t *)CONFIG_SYS_IMMR)->im_cpm));
 203        pcmp  = (pcmconf8xx_t *)(&(((immap_t *)CONFIG_SYS_IMMR)->im_pcmcia));
 204        /*
 205        * Disable PCMCIA buffers (isolate the interface)
 206        * and assert RESET signal
 207        */
 208        debug ("Disable PCMCIA buffers and assert RESET\n");
 209        reg  = PCMCIA_PGCRX(_slot_);
 210        reg |= __MY_PCMCIA_GCRX_CXRESET;        /* active high */
 211        reg |= __MY_PCMCIA_GCRX_CXOE;           /* active low  */
 212        PCMCIA_PGCRX(_slot_) = reg;
 213        udelay(500);
 214
 215        /*
 216        * Configure Port C pins for
 217        * 5 Volts Enable and 3 Volts enable,
 218        * Turn all power pins to Hi-Z
 219        */
 220        debug ("PCMCIA power OFF\n");
 221        cfg_port_B ();  /* Enables switch, but all in Hi-Z */
 222
 223        reg  = cp->cp_pbdat;
 224
 225        switch(vcc) {
 226                case  0:                        break;  /* Switch off           */
 227                case 33: reg &= ~TPS2205_VCC3;  break;  /* Switch on 3.3V       */
 228                case 50: reg &= ~TPS2205_VCC5;  break;  /* Switch on 5.0V       */
 229                default:                        goto done;
 230        }
 231
 232        /* Checking supported voltages */
 233
 234        debug ("PIPR: 0x%x --> %s\n",
 235               pcmp->pcmc_pipr,
 236               (pcmp->pcmc_pipr & 0x00008000) ? "only 5 V" : "can do 3.3V");
 237
 238        cp->cp_pbdat = reg;
 239
 240#ifdef DEBUG
 241{
 242        char *s;
 243
 244        if ((reg & TPS2205_VCC3) == 0) {
 245                s = "at 3.3V";
 246        } else if ((reg & TPS2205_VCC5) == 0) {
 247                s = "at 5.0V";
 248        } else {
 249                s = "down";
 250        }
 251        printf ("PCMCIA powered %s\n", s);
 252}
 253#endif
 254
 255done:
 256        debug ("Enable PCMCIA buffers and stop RESET\n");
 257        reg  =  PCMCIA_PGCRX(_slot_);
 258        reg &= ~__MY_PCMCIA_GCRX_CXRESET;       /* active high */
 259        reg &= ~__MY_PCMCIA_GCRX_CXOE;          /* active low  */
 260        PCMCIA_PGCRX(_slot_) = reg;
 261        udelay(500);
 262
 263        debug ("voltage_set: " PCMCIA_BOARD_MSG " Slot %c, DONE\n",
 264               slot+'A');
 265        return (0);
 266}
 267
 268#endif  /* CONFIG_PCMCIA */
 269