blob: dda7d374450a14899d27c072d811fb98a72db175 [file] [log] [blame]
Wolfgang Denk9d407992006-07-10 23:07:28 +02001/* -------------------------------------------------------------------- */
2/* TQM8xxL Boards by TQ Components */
3/* SC8xx Boards by SinoVee Microsystems */
4/* -------------------------------------------------------------------- */
5#include <common.h>
Marek Vasut6e967032011-10-05 02:51:55 +00006#include <asm/io.h>
Wolfgang Denk966083e2006-07-21 15:24:56 +02007#ifdef CONFIG_8xx
Wolfgang Denk9d407992006-07-10 23:07:28 +02008#include <mpc8xx.h>
Wolfgang Denk966083e2006-07-21 15:24:56 +02009#endif
Wolfgang Denk9d407992006-07-10 23:07:28 +020010#include <pcmcia.h>
11
12#undef CONFIG_PCMCIA
13
Jon Loeligercb51c0b2007-07-09 17:39:42 -050014#if defined(CONFIG_CMD_PCMCIA)
Wolfgang Denk9d407992006-07-10 23:07:28 +020015#define CONFIG_PCMCIA
16#endif
17
Jon Loeligercb51c0b2007-07-09 17:39:42 -050018#if defined(CONFIG_CMD_IDE) && defined(CONFIG_IDE_8xx_PCCARD)
Wolfgang Denk9d407992006-07-10 23:07:28 +020019#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
Marek Vasut6e967032011-10-05 02:51:55 +000035static inline void power_config(int slot) {}
36static inline void power_off(int slot) {}
37static inline void power_on_5_0(int slot) {}
38static inline void power_on_3_3(int slot) {}
Wolfgang Denk9d407992006-07-10 23:07:28 +020039
Wolfgang Denk9d407992006-07-10 23:07:28 +020040#elif defined(CONFIG_VIRTLAB2)
41
Marek Vasut6e967032011-10-05 02:51:55 +000042static inline void power_config(int slot) {}
43
Wolfgang Denk9d407992006-07-10 23:07:28 +020044static inline void power_off(int slot)
45{
Marek Vasut3ebafbf2011-10-21 14:17:24 +000046 volatile unsigned __iomem *addr;
47 addr = (volatile unsigned __iomem *)PCMCIA_CTRL;
48
49 out_be32(addr, 0);
Wolfgang Denk9d407992006-07-10 23:07:28 +020050}
51
52static inline void power_on_5_0(int slot)
53{
Marek Vasut3ebafbf2011-10-21 14:17:24 +000054 volatile unsigned __iomem *addr;
55 addr = (volatile unsigned __iomem *)PCMCIA_CTRL;
56
Marek Vasut6e967032011-10-05 02:51:55 +000057 /* Enable 5V Vccout */
Marek Vasut3ebafbf2011-10-21 14:17:24 +000058 out_be32(addr, 2);
Wolfgang Denk9d407992006-07-10 23:07:28 +020059}
60
61static inline void power_on_3_3(int slot)
62{
Marek Vasut3ebafbf2011-10-21 14:17:24 +000063 volatile unsigned __iomem *addr;
64 addr = (volatile unsigned __iomem *)PCMCIA_CTRL;
65
Marek Vasut6e967032011-10-05 02:51:55 +000066 /* Enable 3.3V Vccout */
Marek Vasut3ebafbf2011-10-21 14:17:24 +000067 out_be32(addr, 1);
Wolfgang Denk9d407992006-07-10 23:07:28 +020068}
69
70#else
71
72static inline void power_config(int slot)
73{
Marek Vasut6e967032011-10-05 02:51:55 +000074 immap_t *immap = (immap_t *)CONFIG_SYS_IMMR;
Wolfgang Denk9d407992006-07-10 23:07:28 +020075 /*
Marek Vasut6e967032011-10-05 02:51:55 +000076 * 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);
Wolfgang Denk9d407992006-07-10 23:07:28 +020081}
82
83static inline void power_off(int slot)
84{
Marek Vasut6e967032011-10-05 02:51:55 +000085 immap_t *immap = (immap_t *)CONFIG_SYS_IMMR;
86 clrbits_be16(&immap->im_ioport.iop_pcdat, 0x0002 | 0x0004);
Wolfgang Denk9d407992006-07-10 23:07:28 +020087}
88
89static inline void power_on_5_0(int slot)
90{
Marek Vasut6e967032011-10-05 02:51:55 +000091 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);
Wolfgang Denk9d407992006-07-10 23:07:28 +020094}
95
96static inline void power_on_3_3(int slot)
97{
Marek Vasut6e967032011-10-05 02:51:55 +000098 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);
Wolfgang Denk9d407992006-07-10 23:07:28 +0200101}
102
103#endif
104
Marek Vasut6e967032011-10-05 02:51:55 +0000105/*
106 * Function to retrieve the PIPR register, used for debuging purposes.
107 */
108static 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
Wolfgang Denk9d407992006-07-10 23:07:28 +0200119static inline int check_card_is_absent(int slot)
120{
Marek Vasut6e967032011-10-05 02:51:55 +0000121 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));
Wolfgang Denk9d407992006-07-10 23:07:28 +0200124}
Wolfgang Denk9d407992006-07-10 23:07:28 +0200125
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
132int pcmcia_hardware_enable(int slot)
133{
Marek Vasut6e967032011-10-05 02:51:55 +0000134 immap_t *immap = (immap_t *)CONFIG_SYS_IMMR;
Wolfgang Denk9d407992006-07-10 23:07:28 +0200135 uint reg, mask;
136
Marek Vasut6e967032011-10-05 02:51:55 +0000137 debug("hardware_enable: " PCMCIA_BOARD_MSG " Slot %c\n", 'A'+slot);
Wolfgang Denk9d407992006-07-10 23:07:28 +0200138
139 udelay(10000);
140
141 /*
Marek Vasut6e967032011-10-05 02:51:55 +0000142 * Configure SIUMCR to enable PCMCIA port B
143 * (VFLS[0:1] are not used for debugging, we connect FRZ# instead)
144 */
Wolfgang Denk9d407992006-07-10 23:07:28 +0200145
Marek Vasut6e967032011-10-05 02:51:55 +0000146 /* 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));
Wolfgang Denk9d407992006-07-10 23:07:28 +0200152
153 /*
Marek Vasut6e967032011-10-05 02:51:55 +0000154 * Disable interrupts, DMA, and PCMCIA buffers
155 * (isolate the interface) and assert RESET signal
156 */
157 debug("Disable PCMCIA buffers and assert RESET\n");
Wolfgang Denk9d407992006-07-10 23:07:28 +0200158 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);
Marek Vasut6e967032011-10-05 02:51:55 +0000172 reg = debug_get_pipr();
173 debug("[%d] %s: PIPR(%p)=0x%x\n", __LINE__, __FUNCTION__,
174 &immap->im_pcmcia.pcmc_pipr, reg);
Wolfgang Denkb87dfd22006-07-19 13:50:38 +0200175
Wolfgang Denk9d407992006-07-10 23:07:28 +0200176 if (check_card_is_absent(slot)) {
177 printf (" No Card found\n");
178 return (1);
179 }
180
181 /*
Marek Vasut6e967032011-10-05 02:51:55 +0000182 * Power On.
183 */
Wolfgang Denk9d407992006-07-10 23:07:28 +0200184 mask = PCMCIA_VS1(slot) | PCMCIA_VS2(slot);
Marek Vasut6e967032011-10-05 02:51:55 +0000185 reg = in_be32(&immap->im_pcmcia.pcmc_pipr);
Wolfgang Denk9d407992006-07-10 23:07:28 +0200186 debug ("PIPR: 0x%x ==> VS1=o%s, VS2=o%s\n",
187 reg,
Marek Vasut6e967032011-10-05 02:51:55 +0000188 (reg & PCMCIA_VS1(slot)) ? "n" : "ff",
189 (reg & PCMCIA_VS2(slot)) ? "n" : "ff");
Wolfgang Denkb87dfd22006-07-19 13:50:38 +0200190
Wolfgang Denk9d407992006-07-10 23:07:28 +0200191 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);
Marek Vasut6e967032011-10-05 02:51:55 +0000207 debug("Enable PCMCIA buffers and stop RESET\n");
Wolfgang Denk9d407992006-07-10 23:07:28 +0200208 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;
Wolfgang Denkb87dfd22006-07-19 13:50:38 +0200212
Wolfgang Denk9d407992006-07-10 23:07:28 +0200213 PCMCIA_PGCRX(slot) = reg;
214
215 udelay(250000); /* some cards need >150 ms to come up :-( */
216
Marek Vasut6e967032011-10-05 02:51:55 +0000217 debug("# hardware_enable done\n");
Wolfgang Denk9d407992006-07-10 23:07:28 +0200218
219 return (0);
220}
221
222
Jon Loeligercb51c0b2007-07-09 17:39:42 -0500223#if defined(CONFIG_CMD_PCMCIA)
Wolfgang Denk9d407992006-07-10 23:07:28 +0200224int pcmcia_hardware_disable(int slot)
225{
Wolfgang Denk9d407992006-07-10 23:07:28 +0200226 u_long reg;
227
Marek Vasut6e967032011-10-05 02:51:55 +0000228 debug("hardware_disable: " PCMCIA_BOARD_MSG " Slot %c\n", 'A'+slot);
Wolfgang Denk9d407992006-07-10 23:07:28 +0200229
230 /* remove all power */
231 power_off(slot);
232
Marek Vasut6e967032011-10-05 02:51:55 +0000233 debug("Disable PCMCIA buffers and assert RESET\n");
Wolfgang Denk9d407992006-07-10 23:07:28 +0200234 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}
Jon Loeligerddb5d86f2007-07-10 11:13:21 -0500244#endif
Wolfgang Denk9d407992006-07-10 23:07:28 +0200245
246int pcmcia_voltage_set(int slot, int vcc, int vpp)
247{
248#ifndef CONFIG_NSCU
Wolfgang Denk966083e2006-07-21 15:24:56 +0200249 u_long reg;
Marek Vasut6e967032011-10-05 02:51:55 +0000250 uint32_t pipr = 0;
Wolfgang Denk9d407992006-07-10 23:07:28 +0200251
Marek Vasut6e967032011-10-05 02:51:55 +0000252 debug("voltage_set: " PCMCIA_BOARD_MSG
Wolfgang Denk9d407992006-07-10 23:07:28 +0200253 " Slot %c, Vcc=%d.%d, Vpp=%d.%d\n",
254 'A'+slot, vcc/10, vcc%10, vpp/10, vcc%10);
255
256 /*
Marek Vasut6e967032011-10-05 02:51:55 +0000257 * Disable PCMCIA buffers (isolate the interface)
258 * and assert RESET signal
259 */
260 debug("Disable PCMCIA buffers and assert RESET\n");
Wolfgang Denk9d407992006-07-10 23:07:28 +0200261 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 */
Wolfgang Denkb87dfd22006-07-19 13:50:38 +0200265
Wolfgang Denk9d407992006-07-10 23:07:28 +0200266 PCMCIA_PGCRX(slot) = reg;
267 udelay(500);
268
Marek Vasut6e967032011-10-05 02:51:55 +0000269 debug("PCMCIA power OFF\n");
Wolfgang Denk9d407992006-07-10 23:07:28 +0200270 power_config(slot);
271 power_off(slot);
272
273 switch(vcc) {
Wolfgang Denk53677ef2008-05-20 16:00:29 +0200274 case 0: break;
Wolfgang Denk9d407992006-07-10 23:07:28 +0200275 case 33: power_on_3_3(slot); break;
276 case 50: power_on_5_0(slot); break;
Wolfgang Denk53677ef2008-05-20 16:00:29 +0200277 default: goto done;
Wolfgang Denk9d407992006-07-10 23:07:28 +0200278 }
279
280 /* Checking supported voltages */
Marek Vasut6e967032011-10-05 02:51:55 +0000281 pipr = debug_get_pipr();
282 debug("PIPR: 0x%x --> %s\n", pipr,
283 (pipr & 0x00008000) ? "only 5 V" : "can do 3.3V");
Wolfgang Denk9d407992006-07-10 23:07:28 +0200284
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
290done:
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 */
Marek Vasut6e967032011-10-05 02:51:55 +0000302 return 0;
Wolfgang Denk9d407992006-07-10 23:07:28 +0200303}
304
305#endif /* CONFIG_PCMCIA && (CONFIG_TQM8xxL || CONFIG_SVM_SC8xx) */