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