blob: 14477a4487faa326b3931f19e961443f13a2e21a [file] [log] [blame]
Wolfgang Denk9d407992006-07-10 23:07:28 +02001#include <common.h>
Wolfgang Denk966083e2006-07-21 15:24:56 +02002#if defined(CONFIG_8xx)
Wolfgang Denk9d407992006-07-10 23:07:28 +02003#include <mpc8xx.h>
Wolfgang Denk966083e2006-07-21 15:24:56 +02004#endif
Wolfgang Denk9d407992006-07-10 23:07:28 +02005#include <pcmcia.h>
6
7#undef CONFIG_PCMCIA
8
Jon Loeliger07d38a12007-07-09 17:30:01 -05009#if defined(CONFIG_CMD_PCMCIA)
Wolfgang Denk9d407992006-07-10 23:07:28 +020010#define CONFIG_PCMCIA
11#endif
12
Jon Loeliger07d38a12007-07-09 17:30:01 -050013#if defined(CONFIG_CMD_IDE) && defined(CONFIG_IDE_8xx_PCCARD)
Wolfgang Denk9d407992006-07-10 23:07:28 +020014#define CONFIG_PCMCIA
15#endif
16
17#if defined(CONFIG_8xx) && defined(CONFIG_PCMCIA)
18
19#if defined(CONFIG_IDE_8xx_PCCARD)
20extern int check_ide_device (int slot);
21#endif
22
23extern int pcmcia_hardware_enable (int slot);
24extern int pcmcia_voltage_set(int slot, int vcc, int vpp);
25
Jon Loeliger07d38a12007-07-09 17:30:01 -050026#if defined(CONFIG_CMD_PCMCIA)
Wolfgang Denk9d407992006-07-10 23:07:28 +020027extern int pcmcia_hardware_disable(int slot);
28#endif
29
30static u_int m8xx_get_graycode(u_int size);
31#if 0 /* Disabled */
32static u_int m8xx_get_speed(u_int ns, u_int is_io);
33#endif
34
35/* look up table for pgcrx registers */
36u_int *pcmcia_pgcrx[2] = {
37 &((immap_t *)CFG_IMMR)->im_pcmcia.pcmc_pgcra,
38 &((immap_t *)CFG_IMMR)->im_pcmcia.pcmc_pgcrb,
39};
40
41/*
42 * Search this table to see if the windowsize is
43 * supported...
44 */
45
46#define M8XX_SIZES_NO 32
47
48static const u_int m8xx_size_to_gray[M8XX_SIZES_NO] =
49{ 0x00000001, 0x00000002, 0x00000008, 0x00000004,
50 0x00000080, 0x00000040, 0x00000010, 0x00000020,
51 0x00008000, 0x00004000, 0x00001000, 0x00002000,
52 0x00000100, 0x00000200, 0x00000800, 0x00000400,
53
54 0x0fffffff, 0xffffffff, 0xffffffff, 0xffffffff,
55 0x01000000, 0x02000000, 0xffffffff, 0x04000000,
56 0x00010000, 0x00020000, 0x00080000, 0x00040000,
57 0x00800000, 0x00400000, 0x00100000, 0x00200000 };
58
59
60/* -------------------------------------------------------------------- */
61
62#ifdef CONFIG_HMI10
63#define HMI10_FRAM_TIMING ( PCMCIA_SHT(2) \
Wolfgang Denk53677ef2008-05-20 16:00:29 +020064 | PCMCIA_SST(2) \
65 | PCMCIA_SL(4))
Wolfgang Denk9d407992006-07-10 23:07:28 +020066#endif
67
68#if defined(CONFIG_LWMON) || defined(CONFIG_NSCU)
69#define CFG_PCMCIA_TIMING ( PCMCIA_SHT(9) \
Wolfgang Denk53677ef2008-05-20 16:00:29 +020070 | PCMCIA_SST(3) \
71 | PCMCIA_SL(12))
Wolfgang Denk9d407992006-07-10 23:07:28 +020072#else
73#define CFG_PCMCIA_TIMING ( PCMCIA_SHT(2) \
Wolfgang Denk53677ef2008-05-20 16:00:29 +020074 | PCMCIA_SST(4) \
75 | PCMCIA_SL(9))
Wolfgang Denk9d407992006-07-10 23:07:28 +020076#endif
77
78/* -------------------------------------------------------------------- */
79
80int pcmcia_on (void)
81{
82 u_long reg, base;
83 pcmcia_win_t *win;
84 u_int slotbit;
85 u_int rc, slot;
86 int i;
87
88 debug ("Enable PCMCIA " PCMCIA_SLOT_MSG "\n");
89
90 /* intialize the fixed memory windows */
91 win = (pcmcia_win_t *)(&((immap_t *)CFG_IMMR)->im_pcmcia.pcmc_pbr0);
92 base = CFG_PCMCIA_MEM_ADDR;
93
94 if((reg = m8xx_get_graycode(CFG_PCMCIA_MEM_SIZE)) == -1) {
95 printf ("Cannot set window size to 0x%08x\n",
96 CFG_PCMCIA_MEM_SIZE);
97 return (1);
98 }
99
100 slotbit = PCMCIA_SLOT_x;
101 for (i=0; i<PCMCIA_MEM_WIN_NO; ++i) {
102 win->br = base;
103
104#if (PCMCIA_SOCKETS_NO == 2)
105 if (i == 4) /* Another slot starting from win 4 */
106 slotbit = (slotbit ? PCMCIA_PSLOT_A : PCMCIA_PSLOT_B);
107#endif
108 switch (i) {
109#ifdef CONFIG_IDE_8xx_PCCARD
110 case 4:
111#ifdef CONFIG_HMI10
112 { /* map FRAM area */
113 win->or = ( PCMCIA_BSIZE_256K
114 | PCMCIA_PPS_8
115 | PCMCIA_PRS_ATTR
116 | slotbit
117 | PCMCIA_PV
118 | HMI10_FRAM_TIMING );
119 break;
120 }
121#endif
122 case 0: { /* map attribute memory */
123 win->or = ( PCMCIA_BSIZE_64M
124 | PCMCIA_PPS_8
125 | PCMCIA_PRS_ATTR
126 | slotbit
127 | PCMCIA_PV
128 | CFG_PCMCIA_TIMING );
129 break;
130 }
131 case 5:
132 case 1: { /* map I/O window for data reg */
133 win->or = ( PCMCIA_BSIZE_1K
134 | PCMCIA_PPS_16
135 | PCMCIA_PRS_IO
136 | slotbit
137 | PCMCIA_PV
138 | CFG_PCMCIA_TIMING );
139 break;
140 }
141 case 6:
142 case 2: { /* map I/O window for cmd/ctrl reg block */
143 win->or = ( PCMCIA_BSIZE_1K
144 | PCMCIA_PPS_8
145 | PCMCIA_PRS_IO
146 | slotbit
147 | PCMCIA_PV
148 | CFG_PCMCIA_TIMING );
149 break;
150 }
151#endif /* CONFIG_IDE_8xx_PCCARD */
152#ifdef CONFIG_HMI10
153 case 3: { /* map I/O window for 4xUART data/ctrl */
154 win->br += 0x40000;
155 win->or = ( PCMCIA_BSIZE_256K
156 | PCMCIA_PPS_8
157 | PCMCIA_PRS_IO
158 | slotbit
159 | PCMCIA_PV
160 | CFG_PCMCIA_TIMING );
161 break;
162 }
163#endif /* CONFIG_HMI10 */
164 default: /* set to not valid */
165 win->or = 0;
166 break;
167 }
168
169 debug ("MemWin %d: PBR 0x%08lX POR %08lX\n",
170 i, win->br, win->or);
171 base += CFG_PCMCIA_MEM_SIZE;
172 ++win;
173 }
174
175 for (i=0, rc=0, slot=_slot_; i<PCMCIA_SOCKETS_NO; i++, slot = !slot) {
176 /* turn off voltage */
177 if ((rc = pcmcia_voltage_set(slot, 0, 0)))
178 continue;
179
180 /* Enable external hardware */
181 if ((rc = pcmcia_hardware_enable(slot)))
182 continue;
183
184#ifdef CONFIG_IDE_8xx_PCCARD
185 if ((rc = check_ide_device(i)))
186 continue;
187#endif
188 }
189 return rc;
190}
191
Jon Loeliger07d38a12007-07-09 17:30:01 -0500192#if defined(CONFIG_CMD_PCMCIA)
Wolfgang Denk9d407992006-07-10 23:07:28 +0200193int pcmcia_off (void)
194{
195 int i;
196 pcmcia_win_t *win;
197
198 printf ("Disable PCMCIA " PCMCIA_SLOT_MSG "\n");
199
200 /* clear interrupt state, and disable interrupts */
201 ((immap_t *)CFG_IMMR)->im_pcmcia.pcmc_pscr = PCMCIA_MASK(_slot_);
202 ((immap_t *)CFG_IMMR)->im_pcmcia.pcmc_per &= ~PCMCIA_MASK(_slot_);
203
204 /* turn off interrupt and disable CxOE */
205 PCMCIA_PGCRX(_slot_) = __MY_PCMCIA_GCRX_CXOE;
206
207 /* turn off memory windows */
208 win = (pcmcia_win_t *)(&((immap_t *)CFG_IMMR)->im_pcmcia.pcmc_pbr0);
209
210 for (i=0; i<PCMCIA_MEM_WIN_NO; ++i) {
211 /* disable memory window */
212 win->or = 0;
213 ++win;
214 }
215
216 /* turn off voltage */
217 pcmcia_voltage_set(_slot_, 0, 0);
218
219 /* disable external hardware */
220 printf ("Shutdown and Poweroff " PCMCIA_SLOT_MSG "\n");
221 pcmcia_hardware_disable(_slot_);
222 return 0;
223}
Jon Loeligerddb5d86f2007-07-10 11:13:21 -0500224#endif
Wolfgang Denk9d407992006-07-10 23:07:28 +0200225
226
227static u_int m8xx_get_graycode(u_int size)
228{
229 u_int k;
230
231 for (k = 0; k < M8XX_SIZES_NO; k++) {
232 if(m8xx_size_to_gray[k] == size)
233 break;
234 }
235
236 if((k == M8XX_SIZES_NO) || (m8xx_size_to_gray[k] == -1))
237 k = -1;
238
239 return k;
240}
241
242#if 0
243
244#if defined(CONFIG_RPXCLASSIC) || defined(CONFIG_RPXLITE)
245
246/* The RPX boards seems to have it's bus monitor timeout set to 6*8 clocks.
247 * SYPCR is write once only, therefore must the slowest memory be faster
248 * than the bus monitor or we will get a machine check due to the bus timeout.
249 */
250#undef PCMCIA_BMT_LIMIT
251#define PCMCIA_BMT_LIMIT (6*8)
252#endif
253
254static u_int m8xx_get_speed(u_int ns, u_int is_io)
255{
256 u_int reg, clocks, psst, psl, psht;
257
258 if(!ns) {
259
260 /*
261 * We get called with IO maps setup to 0ns
262 * if not specified by the user.
263 * They should be 255ns.
264 */
265
266 if(is_io)
267 ns = 255;
268 else
269 ns = 100; /* fast memory if 0 */
270 }
271
272 /*
273 * In PSST, PSL, PSHT fields we tell the controller
274 * timing parameters in CLKOUT clock cycles.
275 * CLKOUT is the same as GCLK2_50.
276 */
277
278 /* how we want to adjust the timing - in percent */
279
280#define ADJ 180 /* 80 % longer accesstime - to be sure */
281
282 clocks = ((M8XX_BUSFREQ / 1000) * ns) / 1000;
283 clocks = (clocks * ADJ) / (100*1000);
284
285 if(clocks >= PCMCIA_BMT_LIMIT) {
286 DEBUG(0, "Max access time limit reached\n");
287 clocks = PCMCIA_BMT_LIMIT-1;
288 }
289
290 psst = clocks / 7; /* setup time */
291 psht = clocks / 7; /* hold time */
292 psl = (clocks * 5) / 7; /* strobe length */
293
294 psst += clocks - (psst + psht + psl);
295
296 reg = psst << 12;
297 reg |= psl << 7;
298 reg |= psht << 16;
299
300 return reg;
301}
302#endif /* 0 */
303
304#endif /* CONFIG_8xx && CONFIG_PCMCIA */