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