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