blob: ca1a9fe151d15fad7d21823cbf27291ab99328af [file] [log] [blame]
Wolfgang Denk50440e72006-07-10 23:07:28 +02001/* -------------------------------------------------------------------- */
2/* TQM8xxL Boards by TQ Components */
3/* SC8xx Boards by SinoVee Microsystems */
4/* -------------------------------------------------------------------- */
5#include <common.h>
Wolfgang Denk31560d12006-07-21 15:24:56 +02006#ifdef CONFIG_8xx
Wolfgang Denk50440e72006-07-10 23:07:28 +02007#include <mpc8xx.h>
Wolfgang Denk31560d12006-07-21 15:24:56 +02008#endif
Wolfgang Denk50440e72006-07-10 23:07:28 +02009#include <pcmcia.h>
10
11#undef CONFIG_PCMCIA
12
Jon Loeliger82ecaad2007-07-09 17:39:42 -050013#if defined(CONFIG_CMD_PCMCIA)
Wolfgang Denk50440e72006-07-10 23:07:28 +020014#define CONFIG_PCMCIA
15#endif
16
Jon Loeliger82ecaad2007-07-09 17:39:42 -050017#if defined(CONFIG_CMD_IDE) && defined(CONFIG_IDE_8xx_PCCARD)
Wolfgang Denk50440e72006-07-10 23:07:28 +020018#define CONFIG_PCMCIA
19#endif
20
21#if defined(CONFIG_PCMCIA) \
22 && (defined(CONFIG_TQM8xxL) || defined(CONFIG_SVM_SC8xx))
23
24#if defined(CONFIG_VIRTLAB2)
25#define PCMCIA_BOARD_MSG "Virtlab2"
26#elif defined(CONFIG_TQM8xxL)
27#define PCMCIA_BOARD_MSG "TQM8xxL"
28#elif defined(CONFIG_SVM_SC8xx)
29#define PCMCIA_BOARD_MSG "SC8xx"
30#endif
31
32#if defined(CONFIG_NSCU)
33
34#define power_config(slot) do {} while (0)
35#define power_off(slot) do {} while (0)
36#define power_on_5_0(slot) do {} while (0)
37#define power_on_3_3(slot) do {} while (0)
38
Wolfgang Denk50440e72006-07-10 23:07:28 +020039#elif defined(CONFIG_VIRTLAB2)
40
41#define power_config(slot) do {} while (0)
42static inline void power_off(int slot)
43{
44 volatile unsigned char *powerctl =
45 (volatile unsigned char *)PCMCIA_CTRL;
46 *powerctl = 0;
47}
48
49static inline void power_on_5_0(int slot)
50{
51 volatile unsigned char *powerctl =
52 (volatile unsigned char *)PCMCIA_CTRL;
53 *powerctl = 2; /* Enable 5V Vccout */
54}
55
56static inline void power_on_3_3(int slot)
57{
58 volatile unsigned char *powerctl =
59 (volatile unsigned char *)PCMCIA_CTRL;
60 *powerctl = 1; /* Enable 3.3V Vccout */
61}
62
63#else
64
65static inline void power_config(int slot)
66{
Jean-Christophe PLAGNIOL-VILLARD03836942008-10-16 15:01:15 +020067 volatile immap_t *immap = (immap_t *)CONFIG_SYS_IMMR;
Wolfgang Denk50440e72006-07-10 23:07:28 +020068 /*
69 * Configure Port C pins for
70 * 5 Volts Enable and 3 Volts enable
71 */
72 immap->im_ioport.iop_pcpar &= ~(0x0002 | 0x0004);
73 immap->im_ioport.iop_pcso &= ~(0x0002 | 0x0004);
74}
75
76static inline void power_off(int slot)
77{
Jean-Christophe PLAGNIOL-VILLARD03836942008-10-16 15:01:15 +020078 volatile immap_t *immap = (immap_t *)CONFIG_SYS_IMMR;
Wolfgang Denk50440e72006-07-10 23:07:28 +020079 immap->im_ioport.iop_pcdat &= ~(0x0002 | 0x0004);
80}
81
82static inline void power_on_5_0(int slot)
83{
Jean-Christophe PLAGNIOL-VILLARD03836942008-10-16 15:01:15 +020084 volatile immap_t *immap = (immap_t *)CONFIG_SYS_IMMR;
Wolfgang Denk50440e72006-07-10 23:07:28 +020085 immap->im_ioport.iop_pcdat |= 0x0004;
86 immap->im_ioport.iop_pcdir |= (0x0002 | 0x0004);
87}
88
89static inline void power_on_3_3(int slot)
90{
Jean-Christophe PLAGNIOL-VILLARD03836942008-10-16 15:01:15 +020091 volatile immap_t *immap = (immap_t *)CONFIG_SYS_IMMR;
Wolfgang Denk50440e72006-07-10 23:07:28 +020092 immap->im_ioport.iop_pcdat |= 0x0002;
93 immap->im_ioport.iop_pcdir |= (0x0002 | 0x0004);
94}
95
96#endif
97
Wolfgang Denk50440e72006-07-10 23:07:28 +020098static inline int check_card_is_absent(int slot)
99{
100 volatile pcmconf8xx_t *pcmp =
Jean-Christophe PLAGNIOL-VILLARD03836942008-10-16 15:01:15 +0200101 (pcmconf8xx_t *)(&(((immap_t *)CONFIG_SYS_IMMR)->im_pcmcia));
Wolfgang Denk50440e72006-07-10 23:07:28 +0200102 return pcmp->pcmc_pipr & (0x18000000 >> (slot << 4));
103}
Wolfgang Denk50440e72006-07-10 23:07:28 +0200104
105#ifdef NSCU_OE_INV
106#define NSCU_GCRX_CXOE 0
107#else
108#define NSCU_GCRX_CXOE __MY_PCMCIA_GCRX_CXOE
109#endif
110
111int pcmcia_hardware_enable(int slot)
112{
113 volatile pcmconf8xx_t *pcmp =
Jean-Christophe PLAGNIOL-VILLARD03836942008-10-16 15:01:15 +0200114 (pcmconf8xx_t *)(&(((immap_t *)CONFIG_SYS_IMMR)->im_pcmcia));
Wolfgang Denk50440e72006-07-10 23:07:28 +0200115 volatile sysconf8xx_t *sysp =
Jean-Christophe PLAGNIOL-VILLARD03836942008-10-16 15:01:15 +0200116 (sysconf8xx_t *)(&(((immap_t *)CONFIG_SYS_IMMR)->im_siu_conf));
Wolfgang Denk50440e72006-07-10 23:07:28 +0200117 uint reg, mask;
118
119 debug ("hardware_enable: " PCMCIA_BOARD_MSG " Slot %c\n", 'A'+slot);
120
121 udelay(10000);
122
123 /*
124 * Configure SIUMCR to enable PCMCIA port B
125 * (VFLS[0:1] are not used for debugging, we connect FRZ# instead)
126 */
127 sysp->sc_siumcr &= ~SIUMCR_DBGC11; /* set DBGC to 00 */
128
129 /* clear interrupt state, and disable interrupts */
130 pcmp->pcmc_pscr = PCMCIA_MASK(slot);
131 pcmp->pcmc_per &= ~PCMCIA_MASK(slot);
132
133 /*
134 * Disable interrupts, DMA, and PCMCIA buffers
135 * (isolate the interface) and assert RESET signal
136 */
137 debug ("Disable PCMCIA buffers and assert RESET\n");
138 reg = 0;
139 reg |= __MY_PCMCIA_GCRX_CXRESET; /* active high */
140 reg |= NSCU_GCRX_CXOE;
141
142 PCMCIA_PGCRX(slot) = reg;
143 udelay(500);
144
145 power_config(slot);
146 power_off(slot);
147
148 /*
149 * Make sure there is a card in the slot, then configure the interface.
150 */
151 udelay(10000);
152 debug ("[%d] %s: PIPR(%p)=0x%x\n", __LINE__,__FUNCTION__,
153 &(pcmp->pcmc_pipr),pcmp->pcmc_pipr);
Wolfgang Denkba940932006-07-19 13:50:38 +0200154
Wolfgang Denk50440e72006-07-10 23:07:28 +0200155 if (check_card_is_absent(slot)) {
156 printf (" No Card found\n");
157 return (1);
158 }
159
160 /*
161 * Power On.
162 */
163 mask = PCMCIA_VS1(slot) | PCMCIA_VS2(slot);
164 reg = pcmp->pcmc_pipr;
165 debug ("PIPR: 0x%x ==> VS1=o%s, VS2=o%s\n",
166 reg,
167 (reg&PCMCIA_VS1(slot))?"n":"ff",
168 (reg&PCMCIA_VS2(slot))?"n":"ff");
Wolfgang Denkba940932006-07-19 13:50:38 +0200169
Wolfgang Denk50440e72006-07-10 23:07:28 +0200170 if ((reg & mask) == mask) {
171 power_on_5_0(slot);
172 puts (" 5.0V card found: ");
173 } else {
174 power_on_3_3(slot);
175 puts (" 3.3V card found: ");
176 }
177
178#if 0
179 /* VCC switch error flag, PCMCIA slot INPACK_ pin */
180 cp->cp_pbdir &= ~(0x0020 | 0x0010);
181 cp->cp_pbpar &= ~(0x0020 | 0x0010);
182 udelay(500000);
183#endif
184
185 udelay(1000);
186 debug ("Enable PCMCIA buffers and stop RESET\n");
187 reg = PCMCIA_PGCRX(slot);
188 reg &= ~__MY_PCMCIA_GCRX_CXRESET; /* active high */
189 reg |= __MY_PCMCIA_GCRX_CXOE; /* active low */
190 reg &= ~NSCU_GCRX_CXOE;
Wolfgang Denkba940932006-07-19 13:50:38 +0200191
Wolfgang Denk50440e72006-07-10 23:07:28 +0200192 PCMCIA_PGCRX(slot) = reg;
193
194 udelay(250000); /* some cards need >150 ms to come up :-( */
195
196 debug ("# hardware_enable done\n");
197
198 return (0);
199}
200
201
Jon Loeliger82ecaad2007-07-09 17:39:42 -0500202#if defined(CONFIG_CMD_PCMCIA)
Wolfgang Denk50440e72006-07-10 23:07:28 +0200203int pcmcia_hardware_disable(int slot)
204{
Wolfgang Denk50440e72006-07-10 23:07:28 +0200205 u_long reg;
206
207 debug ("hardware_disable: " PCMCIA_BOARD_MSG " Slot %c\n", 'A'+slot);
208
209
210 /* remove all power */
211 power_off(slot);
212
213 debug ("Disable PCMCIA buffers and assert RESET\n");
214 reg = 0;
215 reg |= __MY_PCMCIA_GCRX_CXRESET; /* active high */
216 reg |= NSCU_GCRX_CXOE; /* active low */
217
218 PCMCIA_PGCRX(slot) = reg;
219
220 udelay(10000);
221
222 return (0);
223}
Jon Loeliger30c2f242007-07-10 11:13:21 -0500224#endif
Wolfgang Denk50440e72006-07-10 23:07:28 +0200225
226int pcmcia_voltage_set(int slot, int vcc, int vpp)
227{
228#ifndef CONFIG_NSCU
Wolfgang Denk31560d12006-07-21 15:24:56 +0200229 u_long reg;
230# ifdef DEBUG
Wolfgang Denk50440e72006-07-10 23:07:28 +0200231 volatile pcmconf8xx_t *pcmp =
Jean-Christophe PLAGNIOL-VILLARD03836942008-10-16 15:01:15 +0200232 (pcmconf8xx_t *)(&(((immap_t *)CONFIG_SYS_IMMR)->im_pcmcia));
Wolfgang Denk31560d12006-07-21 15:24:56 +0200233# endif
Wolfgang Denk50440e72006-07-10 23:07:28 +0200234
235 debug ("voltage_set: " PCMCIA_BOARD_MSG
236 " Slot %c, Vcc=%d.%d, Vpp=%d.%d\n",
237 'A'+slot, vcc/10, vcc%10, vpp/10, vcc%10);
238
239 /*
240 * Disable PCMCIA buffers (isolate the interface)
241 * and assert RESET signal
242 */
243 debug ("Disable PCMCIA buffers and assert RESET\n");
244 reg = PCMCIA_PGCRX(slot);
245 reg |= __MY_PCMCIA_GCRX_CXRESET; /* active high */
246 reg &= ~__MY_PCMCIA_GCRX_CXOE; /* active low */
247 reg |= NSCU_GCRX_CXOE; /* active low */
Wolfgang Denkba940932006-07-19 13:50:38 +0200248
Wolfgang Denk50440e72006-07-10 23:07:28 +0200249 PCMCIA_PGCRX(slot) = reg;
250 udelay(500);
251
252 debug ("PCMCIA power OFF\n");
253 power_config(slot);
254 power_off(slot);
255
256 switch(vcc) {
Wolfgang Denka1be4762008-05-20 16:00:29 +0200257 case 0: break;
Wolfgang Denk50440e72006-07-10 23:07:28 +0200258 case 33: power_on_3_3(slot); break;
259 case 50: power_on_5_0(slot); break;
Wolfgang Denka1be4762008-05-20 16:00:29 +0200260 default: goto done;
Wolfgang Denk50440e72006-07-10 23:07:28 +0200261 }
262
263 /* Checking supported voltages */
264
265 debug("PIPR: 0x%x --> %s\n", pcmp->pcmc_pipr,
266 (pcmp->pcmc_pipr & 0x00008000) ? "only 5 V" : "can do 3.3V");
267
268 if (vcc)
269 debug("PCMCIA powered at %sV\n", (vcc == 50) ? "5.0" : "3.3");
270 else
271 debug("PCMCIA powered down\n");
272
273done:
274 debug("Enable PCMCIA buffers and stop RESET\n");
275 reg = PCMCIA_PGCRX(slot);
276 reg &= ~__MY_PCMCIA_GCRX_CXRESET; /* active high */
277 reg |= __MY_PCMCIA_GCRX_CXOE; /* active low */
278 reg &= ~NSCU_GCRX_CXOE; /* active low */
279
280 PCMCIA_PGCRX(slot) = reg;
281 udelay(500);
282
283 debug("voltage_set: " PCMCIA_BOARD_MSG " Slot %c, DONE\n", slot+'A');
284#endif /* CONFIG_NSCU */
285 return (0);
286}
287
288#endif /* CONFIG_PCMCIA && (CONFIG_TQM8xxL || CONFIG_SVM_SC8xx) */