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