Merge with /home/wd/git/u-boot/custodian/u-boot-ppc4xx
[platform/kernel/u-boot.git] / drivers / mpc8xx_pcmcia.c
1 #include <common.h>
2 #if defined(CONFIG_8xx)
3 #include <mpc8xx.h>
4 #endif
5 #include <pcmcia.h>
6
7 #undef  CONFIG_PCMCIA
8
9 #if     (CONFIG_COMMANDS & CFG_CMD_PCMCIA)
10 #define CONFIG_PCMCIA
11 #endif
12
13 #if     (CONFIG_COMMANDS & CFG_CMD_IDE) && defined(CONFIG_IDE_8xx_PCCARD)
14 #define CONFIG_PCMCIA
15 #endif
16
17 #if defined(CONFIG_8xx) && defined(CONFIG_PCMCIA)
18
19 #if     defined(CONFIG_IDE_8xx_PCCARD)
20 extern int check_ide_device (int slot);
21 #endif
22
23 extern int pcmcia_hardware_enable (int slot);
24 extern int pcmcia_voltage_set(int slot, int vcc, int vpp);
25
26 #if     (CONFIG_COMMANDS & CFG_CMD_PCMCIA)
27 extern int pcmcia_hardware_disable(int slot);
28 #endif
29
30 static u_int m8xx_get_graycode(u_int size);
31 #if 0 /* Disabled */
32 static u_int m8xx_get_speed(u_int ns, u_int is_io);
33 #endif
34
35 /* look up table for pgcrx registers */
36 u_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
48 static 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)   \
64                                 |       PCMCIA_SST(2)   \
65                                 |       PCMCIA_SL(4))
66 #endif
67
68 #if     defined(CONFIG_LWMON) || defined(CONFIG_NSCU)
69 #define CFG_PCMCIA_TIMING       (       PCMCIA_SHT(9)   \
70                                 |       PCMCIA_SST(3)   \
71                                 |       PCMCIA_SL(12))
72 #else
73 #define CFG_PCMCIA_TIMING       (       PCMCIA_SHT(2)   \
74                                 |       PCMCIA_SST(4)   \
75                                 |       PCMCIA_SL(9))
76 #endif
77
78 /* -------------------------------------------------------------------- */
79
80 int 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
192 #if     (CONFIG_COMMANDS & CFG_CMD_PCMCIA)
193 int 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 }
224 #endif  /* CFG_CMD_PCMCIA */
225
226
227 static 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
254 static 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 */