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