]>
Commit | Line | Data |
---|---|---|
9d407995 WD |
1 | /* -------------------------------------------------------------------- */ |
2 | /* TQM8xxL Boards by TQ Components */ | |
3 | /* SC8xx Boards by SinoVee Microsystems */ | |
4 | /* -------------------------------------------------------------------- */ | |
5 | #include <common.h> | |
6 | #include <mpc8xx.h> | |
7 | #include <pcmcia.h> | |
8 | ||
9 | #undef CONFIG_PCMCIA | |
10 | ||
11 | #if (CONFIG_COMMANDS & CFG_CMD_PCMCIA) | |
12 | #define CONFIG_PCMCIA | |
13 | #endif | |
14 | ||
15 | #if (CONFIG_COMMANDS & CFG_CMD_IDE) && defined(CONFIG_IDE_8xx_PCCARD) | |
16 | #define CONFIG_PCMCIA | |
17 | #endif | |
18 | ||
19 | #if defined(CONFIG_PCMCIA) \ | |
20 | && (defined(CONFIG_TQM8xxL) || defined(CONFIG_SVM_SC8xx)) | |
21 | ||
22 | #if defined(CONFIG_VIRTLAB2) | |
23 | #define PCMCIA_BOARD_MSG "Virtlab2" | |
24 | #elif defined(CONFIG_TQM8xxL) | |
25 | #define PCMCIA_BOARD_MSG "TQM8xxL" | |
26 | #elif defined(CONFIG_SVM_SC8xx) | |
27 | #define PCMCIA_BOARD_MSG "SC8xx" | |
28 | #endif | |
29 | ||
30 | #if defined(CONFIG_NSCU) | |
31 | ||
32 | #define power_config(slot) do {} while (0) | |
33 | #define power_off(slot) do {} while (0) | |
34 | #define power_on_5_0(slot) do {} while (0) | |
35 | #define power_on_3_3(slot) do {} while (0) | |
36 | ||
37 | #elif defined(CONFIG_HMI10) | |
38 | ||
39 | static inline void power_config(int slot) | |
40 | { | |
41 | volatile immap_t *immap = (immap_t *)CFG_IMMR; | |
42 | /* | |
43 | * Configure Port B pins for | |
44 | * 5 Volts Enable and 3 Volts enable | |
45 | */ | |
46 | immap->im_cpm.cp_pbpar &= ~(0x00000300); | |
47 | } | |
48 | ||
49 | static inline void power_off(int slot) | |
50 | { | |
51 | volatile immap_t *immap = (immap_t *)CFG_IMMR; | |
52 | /* remove all power */ | |
53 | immap->im_cpm.cp_pbdat |= 0x00000300; | |
54 | } | |
55 | ||
56 | static inline void power_on_5_0(int slot) | |
57 | { | |
58 | volatile immap_t *immap = (immap_t *)CFG_IMMR; | |
59 | immap->im_cpm.cp_pbdat &= ~(0x0000100); | |
60 | immap->im_cpm.cp_pbdir |= 0x00000300; | |
61 | } | |
62 | ||
63 | static inline void power_on_3_3(int slot) | |
64 | { | |
65 | volatile immap_t *immap = (immap_t *)CFG_IMMR; | |
66 | immap->im_cpm.cp_pbdat &= ~(0x0000200); | |
67 | immap->im_cpm.cp_pbdir |= 0x00000300; | |
68 | } | |
69 | ||
70 | #elif defined(CONFIG_VIRTLAB2) | |
71 | ||
72 | #define power_config(slot) do {} while (0) | |
73 | static inline void power_off(int slot) | |
74 | { | |
75 | volatile unsigned char *powerctl = | |
76 | (volatile unsigned char *)PCMCIA_CTRL; | |
77 | *powerctl = 0; | |
78 | } | |
79 | ||
80 | static inline void power_on_5_0(int slot) | |
81 | { | |
82 | volatile unsigned char *powerctl = | |
83 | (volatile unsigned char *)PCMCIA_CTRL; | |
84 | *powerctl = 2; /* Enable 5V Vccout */ | |
85 | } | |
86 | ||
87 | static inline void power_on_3_3(int slot) | |
88 | { | |
89 | volatile unsigned char *powerctl = | |
90 | (volatile unsigned char *)PCMCIA_CTRL; | |
91 | *powerctl = 1; /* Enable 3.3V Vccout */ | |
92 | } | |
93 | ||
94 | #else | |
95 | ||
96 | static inline void power_config(int slot) | |
97 | { | |
98 | volatile immap_t *immap = (immap_t *)CFG_IMMR; | |
99 | /* | |
100 | * Configure Port C pins for | |
101 | * 5 Volts Enable and 3 Volts enable | |
102 | */ | |
103 | immap->im_ioport.iop_pcpar &= ~(0x0002 | 0x0004); | |
104 | immap->im_ioport.iop_pcso &= ~(0x0002 | 0x0004); | |
105 | } | |
106 | ||
107 | static inline void power_off(int slot) | |
108 | { | |
109 | volatile immap_t *immap = (immap_t *)CFG_IMMR; | |
110 | immap->im_ioport.iop_pcdat &= ~(0x0002 | 0x0004); | |
111 | } | |
112 | ||
113 | static inline void power_on_5_0(int slot) | |
114 | { | |
115 | volatile immap_t *immap = (immap_t *)CFG_IMMR; | |
116 | immap->im_ioport.iop_pcdat |= 0x0004; | |
117 | immap->im_ioport.iop_pcdir |= (0x0002 | 0x0004); | |
118 | } | |
119 | ||
120 | static inline void power_on_3_3(int slot) | |
121 | { | |
122 | volatile immap_t *immap = (immap_t *)CFG_IMMR; | |
123 | immap->im_ioport.iop_pcdat |= 0x0002; | |
124 | immap->im_ioport.iop_pcdir |= (0x0002 | 0x0004); | |
125 | } | |
126 | ||
127 | #endif | |
128 | ||
129 | #ifdef CONFIG_HMI10 | |
130 | static inline int check_card_is_absent(int slot) | |
131 | { | |
132 | volatile pcmconf8xx_t *pcmp = | |
133 | (pcmconf8xx_t *)(&(((immap_t *)CFG_IMMR)->im_pcmcia)); | |
134 | return pcmp->pcmc_pipr & (0x10000000 >> (slot << 4)); | |
135 | } | |
136 | #else | |
137 | static inline int check_card_is_absent(int slot) | |
138 | { | |
139 | volatile pcmconf8xx_t *pcmp = | |
140 | (pcmconf8xx_t *)(&(((immap_t *)CFG_IMMR)->im_pcmcia)); | |
141 | return pcmp->pcmc_pipr & (0x18000000 >> (slot << 4)); | |
142 | } | |
143 | #endif | |
144 | ||
145 | #ifdef NSCU_OE_INV | |
146 | #define NSCU_GCRX_CXOE 0 | |
147 | #else | |
148 | #define NSCU_GCRX_CXOE __MY_PCMCIA_GCRX_CXOE | |
149 | #endif | |
150 | ||
151 | int pcmcia_hardware_enable(int slot) | |
152 | { | |
153 | volatile pcmconf8xx_t *pcmp = | |
154 | (pcmconf8xx_t *)(&(((immap_t *)CFG_IMMR)->im_pcmcia)); | |
155 | volatile sysconf8xx_t *sysp = | |
156 | (sysconf8xx_t *)(&(((immap_t *)CFG_IMMR)->im_siu_conf)); | |
157 | uint reg, mask; | |
158 | ||
159 | debug ("hardware_enable: " PCMCIA_BOARD_MSG " Slot %c\n", 'A'+slot); | |
160 | ||
161 | udelay(10000); | |
162 | ||
163 | /* | |
164 | * Configure SIUMCR to enable PCMCIA port B | |
165 | * (VFLS[0:1] are not used for debugging, we connect FRZ# instead) | |
166 | */ | |
167 | sysp->sc_siumcr &= ~SIUMCR_DBGC11; /* set DBGC to 00 */ | |
168 | ||
169 | /* clear interrupt state, and disable interrupts */ | |
170 | pcmp->pcmc_pscr = PCMCIA_MASK(slot); | |
171 | pcmp->pcmc_per &= ~PCMCIA_MASK(slot); | |
172 | ||
173 | /* | |
174 | * Disable interrupts, DMA, and PCMCIA buffers | |
175 | * (isolate the interface) and assert RESET signal | |
176 | */ | |
177 | debug ("Disable PCMCIA buffers and assert RESET\n"); | |
178 | reg = 0; | |
179 | reg |= __MY_PCMCIA_GCRX_CXRESET; /* active high */ | |
180 | reg |= NSCU_GCRX_CXOE; | |
181 | ||
182 | PCMCIA_PGCRX(slot) = reg; | |
183 | udelay(500); | |
184 | ||
185 | power_config(slot); | |
186 | power_off(slot); | |
187 | ||
188 | /* | |
189 | * Make sure there is a card in the slot, then configure the interface. | |
190 | */ | |
191 | udelay(10000); | |
192 | debug ("[%d] %s: PIPR(%p)=0x%x\n", __LINE__,__FUNCTION__, | |
193 | &(pcmp->pcmc_pipr),pcmp->pcmc_pipr); | |
b87dfd28 | 194 | |
9d407995 WD |
195 | if (check_card_is_absent(slot)) { |
196 | printf (" No Card found\n"); | |
197 | return (1); | |
198 | } | |
199 | ||
200 | /* | |
201 | * Power On. | |
202 | */ | |
203 | mask = PCMCIA_VS1(slot) | PCMCIA_VS2(slot); | |
204 | reg = pcmp->pcmc_pipr; | |
205 | debug ("PIPR: 0x%x ==> VS1=o%s, VS2=o%s\n", | |
206 | reg, | |
207 | (reg&PCMCIA_VS1(slot))?"n":"ff", | |
208 | (reg&PCMCIA_VS2(slot))?"n":"ff"); | |
b87dfd28 | 209 | |
9d407995 WD |
210 | if ((reg & mask) == mask) { |
211 | power_on_5_0(slot); | |
212 | puts (" 5.0V card found: "); | |
213 | } else { | |
214 | power_on_3_3(slot); | |
215 | puts (" 3.3V card found: "); | |
216 | } | |
217 | ||
218 | #if 0 | |
219 | /* VCC switch error flag, PCMCIA slot INPACK_ pin */ | |
220 | cp->cp_pbdir &= ~(0x0020 | 0x0010); | |
221 | cp->cp_pbpar &= ~(0x0020 | 0x0010); | |
222 | udelay(500000); | |
223 | #endif | |
224 | ||
225 | udelay(1000); | |
226 | debug ("Enable PCMCIA buffers and stop RESET\n"); | |
227 | reg = PCMCIA_PGCRX(slot); | |
228 | reg &= ~__MY_PCMCIA_GCRX_CXRESET; /* active high */ | |
229 | reg |= __MY_PCMCIA_GCRX_CXOE; /* active low */ | |
230 | reg &= ~NSCU_GCRX_CXOE; | |
b87dfd28 | 231 | |
9d407995 WD |
232 | PCMCIA_PGCRX(slot) = reg; |
233 | ||
234 | udelay(250000); /* some cards need >150 ms to come up :-( */ | |
235 | ||
236 | debug ("# hardware_enable done\n"); | |
237 | ||
238 | return (0); | |
239 | } | |
240 | ||
241 | ||
242 | #if (CONFIG_COMMANDS & CFG_CMD_PCMCIA) | |
243 | int pcmcia_hardware_disable(int slot) | |
244 | { | |
245 | volatile pcmconf8xx_t *pcmp = | |
246 | (pcmconf8xx_t *)(&(((immap_t *)CFG_IMMR)->im_pcmcia)); | |
247 | u_long reg; | |
248 | ||
249 | debug ("hardware_disable: " PCMCIA_BOARD_MSG " Slot %c\n", 'A'+slot); | |
250 | ||
251 | ||
252 | /* remove all power */ | |
253 | power_off(slot); | |
254 | ||
255 | debug ("Disable PCMCIA buffers and assert RESET\n"); | |
256 | reg = 0; | |
257 | reg |= __MY_PCMCIA_GCRX_CXRESET; /* active high */ | |
258 | reg |= NSCU_GCRX_CXOE; /* active low */ | |
259 | ||
260 | PCMCIA_PGCRX(slot) = reg; | |
261 | ||
262 | udelay(10000); | |
263 | ||
264 | return (0); | |
265 | } | |
266 | #endif /* CFG_CMD_PCMCIA */ | |
267 | ||
268 | int pcmcia_voltage_set(int slot, int vcc, int vpp) | |
269 | { | |
270 | #ifndef CONFIG_NSCU | |
271 | volatile pcmconf8xx_t *pcmp = | |
272 | (pcmconf8xx_t *)(&(((immap_t *)CFG_IMMR)->im_pcmcia)); | |
273 | u_long reg; | |
274 | ||
275 | debug ("voltage_set: " PCMCIA_BOARD_MSG | |
276 | " Slot %c, Vcc=%d.%d, Vpp=%d.%d\n", | |
277 | 'A'+slot, vcc/10, vcc%10, vpp/10, vcc%10); | |
278 | ||
279 | /* | |
280 | * Disable PCMCIA buffers (isolate the interface) | |
281 | * and assert RESET signal | |
282 | */ | |
283 | debug ("Disable PCMCIA buffers and assert RESET\n"); | |
284 | reg = PCMCIA_PGCRX(slot); | |
285 | reg |= __MY_PCMCIA_GCRX_CXRESET; /* active high */ | |
286 | reg &= ~__MY_PCMCIA_GCRX_CXOE; /* active low */ | |
287 | reg |= NSCU_GCRX_CXOE; /* active low */ | |
b87dfd28 | 288 | |
9d407995 WD |
289 | PCMCIA_PGCRX(slot) = reg; |
290 | udelay(500); | |
291 | ||
292 | debug ("PCMCIA power OFF\n"); | |
293 | power_config(slot); | |
294 | power_off(slot); | |
295 | ||
296 | switch(vcc) { | |
297 | case 0: break; | |
298 | case 33: power_on_3_3(slot); break; | |
299 | case 50: power_on_5_0(slot); break; | |
300 | default: goto done; | |
301 | } | |
302 | ||
303 | /* Checking supported voltages */ | |
304 | ||
305 | debug("PIPR: 0x%x --> %s\n", pcmp->pcmc_pipr, | |
306 | (pcmp->pcmc_pipr & 0x00008000) ? "only 5 V" : "can do 3.3V"); | |
307 | ||
308 | if (vcc) | |
309 | debug("PCMCIA powered at %sV\n", (vcc == 50) ? "5.0" : "3.3"); | |
310 | else | |
311 | debug("PCMCIA powered down\n"); | |
312 | ||
313 | done: | |
314 | debug("Enable PCMCIA buffers and stop RESET\n"); | |
315 | reg = PCMCIA_PGCRX(slot); | |
316 | reg &= ~__MY_PCMCIA_GCRX_CXRESET; /* active high */ | |
317 | reg |= __MY_PCMCIA_GCRX_CXOE; /* active low */ | |
318 | reg &= ~NSCU_GCRX_CXOE; /* active low */ | |
319 | ||
320 | PCMCIA_PGCRX(slot) = reg; | |
321 | udelay(500); | |
322 | ||
323 | debug("voltage_set: " PCMCIA_BOARD_MSG " Slot %c, DONE\n", slot+'A'); | |
324 | #endif /* CONFIG_NSCU */ | |
325 | return (0); | |
326 | } | |
327 | ||
328 | #endif /* CONFIG_PCMCIA && (CONFIG_TQM8xxL || CONFIG_SVM_SC8xx) */ |