]> git.kernelconcepts.de Git - karo-tx-uboot.git/blob - board/icu862/pcmcia.c
imported Freescale specific U-Boot additions for i.MX28,... release L2.6.31_10.08.01
[karo-tx-uboot.git] / board / icu862 / pcmcia.c
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
19 static 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
48 int 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)
159 int 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
189 int 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
255 done:
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 */