]> git.ipfire.org Git - people/ms/u-boot.git/blame - drivers/pcmcia/i82365.c
mpc8260: remove atc board support
[people/ms/u-boot.git] / drivers / pcmcia / i82365.c
CommitLineData
66fd3d1c 1/*
e799d375 2 * (C) Copyright 2003-2005
66fd3d1c
WD
3 * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
4 *
1a459660 5 * SPDX-License-Identifier: GPL-2.0+
66fd3d1c
WD
6 ********************************************************************
7 *
8 * Lots of code copied from:
9 *
10 * i82365.c 1.352 - Linux driver for Intel 82365 and compatible
11 * PC Card controllers, and Yenta-compatible PCI-to-CardBus controllers.
12 * (C) 1999 David A. Hinds <dahinds@users.sourceforge.net>
13 */
14
15#include <common.h>
16
66fd3d1c
WD
17#include <command.h>
18#include <pci.h>
19#include <pcmcia.h>
66fd3d1c
WD
20#include <asm/io.h>
21
22#include <pcmcia/ss.h>
23#include <pcmcia/i82365.h>
66fd3d1c 24#include <pcmcia/yenta.h>
e2ffd59b
WD
25#ifdef CONFIG_CPC45
26#include <pcmcia/cirrus.h>
27#else
28#include <pcmcia/ti113x.h>
29#endif
66fd3d1c
WD
30
31static struct pci_device_id supported[] = {
e2ffd59b
WD
32#ifdef CONFIG_CPC45
33 {PCI_VENDOR_ID_CIRRUS, PCI_DEVICE_ID_CIRRUS_6729},
34#else
66fd3d1c 35 {PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_1510},
e2ffd59b 36#endif
66fd3d1c
WD
37 {0, 0}
38};
39
40#define CYCLE_TIME 120
41
e2ffd59b
WD
42#ifdef CONFIG_CPC45
43extern int SPD67290Init (void);
44#endif
45
66fd3d1c
WD
46#ifdef DEBUG
47static void i82365_dump_regions (pci_dev_t dev);
48#endif
49
50typedef struct socket_info_t {
e2ffd59b
WD
51 pci_dev_t dev;
52 u_short bcr;
53 u_char pci_lat, cb_lat, sub_bus, cache;
54 u_int cb_phys;
55
56 socket_cap_t cap;
57 u_short type;
58 u_int flags;
59#ifdef CONFIG_CPC45
60 cirrus_state_t c_state;
61#else
62 ti113x_state_t state;
63#endif
66fd3d1c
WD
64} socket_info_t;
65
e2ffd59b
WD
66#ifdef CONFIG_CPC45
67/* These definitions must match the pcic table! */
68typedef enum pcic_id {
69 IS_PD6710, IS_PD672X, IS_VT83C469
70} pcic_id;
71
72typedef struct pcic_t {
73 char *name;
74} pcic_t;
75
76static pcic_t pcic[] = {
77 {" Cirrus PD6710: "},
78 {" Cirrus PD672x: "},
79 {" VIA VT83C469: "},
80};
81#endif
82
66fd3d1c
WD
83static socket_info_t socket;
84static socket_state_t state;
85static struct pccard_mem_map mem;
86static struct pccard_io_map io;
87
88/*====================================================================*/
89
90/* Some PCI shortcuts */
91
92static int pci_readb (socket_info_t * s, int r, u_char * v)
93{
94 return pci_read_config_byte (s->dev, r, v);
95}
96static int pci_writeb (socket_info_t * s, int r, u_char v)
97{
98 return pci_write_config_byte (s->dev, r, v);
99}
100static int pci_readw (socket_info_t * s, int r, u_short * v)
101{
102 return pci_read_config_word (s->dev, r, v);
103}
104static int pci_writew (socket_info_t * s, int r, u_short v)
105{
106 return pci_write_config_word (s->dev, r, v);
107}
e2ffd59b 108#ifndef CONFIG_CPC45
66fd3d1c
WD
109static int pci_readl (socket_info_t * s, int r, u_int * v)
110{
111 return pci_read_config_dword (s->dev, r, v);
112}
113static int pci_writel (socket_info_t * s, int r, u_int v)
114{
115 return pci_write_config_dword (s->dev, r, v);
116}
e2ffd59b
WD
117#endif /* !CONFIG_CPC45 */
118
119/*====================================================================*/
120
121#ifdef CONFIG_CPC45
122
123#define cb_readb(s) readb((s)->cb_phys + 1)
124#define cb_writeb(s, v) writeb(v, (s)->cb_phys)
125#define cb_writeb2(s, v) writeb(v, (s)->cb_phys + 1)
126#define cb_readl(s, r) readl((s)->cb_phys + (r))
127#define cb_writel(s, r, v) writel(v, (s)->cb_phys + (r))
128
129
130static u_char i365_get (socket_info_t * s, u_short reg)
131{
132 u_char val;
e2ffd59b
WD
133#ifdef CONFIG_PCMCIA_SLOT_A
134 int slot = 0;
135#else
136 int slot = 1;
137#endif
138
139 val = I365_REG (slot, reg);
140
141 cb_writeb (s, val);
142 val = cb_readb (s);
143
144 debug ("i365_get slot:%x reg: %x val: %x\n", slot, reg, val);
145 return val;
146}
147
148static void i365_set (socket_info_t * s, u_short reg, u_char data)
149{
150#ifdef CONFIG_PCMCIA_SLOT_A
151 int slot = 0;
152#else
153 int slot = 1;
154#endif
c3d2b4b4 155 u_char val;
e2ffd59b 156
c3d2b4b4 157 val = I365_REG (slot, reg);
e2ffd59b
WD
158
159 cb_writeb (s, val);
160 cb_writeb2 (s, data);
161
162 debug ("i365_set slot:%x reg: %x data:%x\n", slot, reg, data);
163}
164
165#else /* ! CONFIG_CPC45 */
66fd3d1c
WD
166
167#define cb_readb(s, r) readb((s)->cb_phys + (r))
168#define cb_readl(s, r) readl((s)->cb_phys + (r))
169#define cb_writeb(s, r, v) writeb(v, (s)->cb_phys + (r))
170#define cb_writel(s, r, v) writel(v, (s)->cb_phys + (r))
171
66fd3d1c
WD
172static u_char i365_get (socket_info_t * s, u_short reg)
173{
174 return cb_readb (s, 0x0800 + reg);
175}
176
177static void i365_set (socket_info_t * s, u_short reg, u_char data)
178{
179 cb_writeb (s, 0x0800 + reg, data);
180}
e2ffd59b 181#endif /* CONFIG_CPC45 */
66fd3d1c
WD
182
183static void i365_bset (socket_info_t * s, u_short reg, u_char mask)
184{
185 i365_set (s, reg, i365_get (s, reg) | mask);
186}
187
188static void i365_bclr (socket_info_t * s, u_short reg, u_char mask)
189{
190 i365_set (s, reg, i365_get (s, reg) & ~mask);
191}
192
193#if 0 /* not used */
194static void i365_bflip (socket_info_t * s, u_short reg, u_char mask, int b)
195{
196 u_char d = i365_get (s, reg);
197
198 i365_set (s, reg, (b) ? (d | mask) : (d & ~mask));
199}
200
201static u_short i365_get_pair (socket_info_t * s, u_short reg)
202{
203 return (i365_get (s, reg) + (i365_get (s, reg + 1) << 8));
204}
205#endif /* not used */
206
207static void i365_set_pair (socket_info_t * s, u_short reg, u_short data)
208{
209 i365_set (s, reg, data & 0xff);
210 i365_set (s, reg + 1, data >> 8);
211}
212
e2ffd59b
WD
213#ifdef CONFIG_CPC45
214/*======================================================================
215
216 Code to save and restore global state information for Cirrus
217 PD67xx controllers, and to set and report global configuration
218 options.
219
220======================================================================*/
221
222#define flip(v,b,f) (v = ((f)<0) ? v : ((f) ? ((v)|(b)) : ((v)&(~b))))
223
224static void cirrus_get_state (socket_info_t * s)
225{
226 int i;
227 cirrus_state_t *p = &s->c_state;
228
229 p->misc1 = i365_get (s, PD67_MISC_CTL_1);
230 p->misc1 &= (PD67_MC1_MEDIA_ENA | PD67_MC1_INPACK_ENA);
231 p->misc2 = i365_get (s, PD67_MISC_CTL_2);
232 for (i = 0; i < 6; i++)
233 p->timer[i] = i365_get (s, PD67_TIME_SETUP (0) + i);
234
235}
236
237static void cirrus_set_state (socket_info_t * s)
238{
239 int i;
240 u_char misc;
241 cirrus_state_t *p = &s->c_state;
242
243 misc = i365_get (s, PD67_MISC_CTL_2);
244 i365_set (s, PD67_MISC_CTL_2, p->misc2);
245 if (misc & PD67_MC2_SUSPEND)
246 udelay (50000);
247 misc = i365_get (s, PD67_MISC_CTL_1);
248 misc &= ~(PD67_MC1_MEDIA_ENA | PD67_MC1_INPACK_ENA);
249 i365_set (s, PD67_MISC_CTL_1, misc | p->misc1);
250 for (i = 0; i < 6; i++)
251 i365_set (s, PD67_TIME_SETUP (0) + i, p->timer[i]);
252}
253
254static u_int cirrus_set_opts (socket_info_t * s)
255{
256 cirrus_state_t *p = &s->c_state;
257 u_int mask = 0xffff;
66d1a2e3 258 char buf[200] = {0};
e2ffd59b
WD
259
260 if (has_ring == -1)
261 has_ring = 1;
262 flip (p->misc2, PD67_MC2_IRQ15_RI, has_ring);
263 flip (p->misc2, PD67_MC2_DYNAMIC_MODE, dynamic_mode);
264#if DEBUG
265 if (p->misc2 & PD67_MC2_IRQ15_RI)
266 strcat (buf, " [ring]");
267 if (p->misc2 & PD67_MC2_DYNAMIC_MODE)
268 strcat (buf, " [dyn mode]");
269 if (p->misc1 & PD67_MC1_INPACK_ENA)
270 strcat (buf, " [inpack]");
271#endif
272
273 if (p->misc2 & PD67_MC2_IRQ15_RI)
274 mask &= ~0x8000;
275 if (has_led > 0) {
276#if DEBUG
277 strcat (buf, " [led]");
278#endif
279 mask &= ~0x1000;
280 }
281 if (has_dma > 0) {
282#if DEBUG
283 strcat (buf, " [dma]");
284#endif
285 mask &= ~0x0600;
286 flip (p->misc2, PD67_MC2_FREQ_BYPASS, freq_bypass);
287#if DEBUG
288 if (p->misc2 & PD67_MC2_FREQ_BYPASS)
289 strcat (buf, " [freq bypass]");
290#endif
291 }
292
293 if (setup_time >= 0)
294 p->timer[0] = p->timer[3] = setup_time;
295 if (cmd_time > 0) {
296 p->timer[1] = cmd_time;
297 p->timer[4] = cmd_time * 2 + 4;
298 }
299 if (p->timer[1] == 0) {
300 p->timer[1] = 6;
301 p->timer[4] = 16;
302 if (p->timer[0] == 0)
303 p->timer[0] = p->timer[3] = 1;
304 }
305 if (recov_time >= 0)
306 p->timer[2] = p->timer[5] = recov_time;
307
308 debug ("i82365 Opt: %s [%d/%d/%d] [%d/%d/%d]\n",
309 buf,
310 p->timer[0], p->timer[1], p->timer[2],
311 p->timer[3], p->timer[4], p->timer[5]);
312
313 return mask;
314}
315
316#else /* !CONFIG_CPC45 */
317
66fd3d1c
WD
318/*======================================================================
319
320 Code to save and restore global state information for TI 1130 and
321 TI 1131 controllers, and to set and report global configuration
322 options.
8bde7f77 323
66fd3d1c
WD
324======================================================================*/
325
326static void ti113x_get_state (socket_info_t * s)
327{
328 ti113x_state_t *p = &s->state;
329
330 pci_readl (s, TI113X_SYSTEM_CONTROL, &p->sysctl);
331 pci_readb (s, TI113X_CARD_CONTROL, &p->cardctl);
332 pci_readb (s, TI113X_DEVICE_CONTROL, &p->devctl);
333 pci_readb (s, TI1250_DIAGNOSTIC, &p->diag);
334 pci_readl (s, TI12XX_IRQMUX, &p->irqmux);
335}
336
337static void ti113x_set_state (socket_info_t * s)
338{
339 ti113x_state_t *p = &s->state;
340
341 pci_writel (s, TI113X_SYSTEM_CONTROL, p->sysctl);
342 pci_writeb (s, TI113X_CARD_CONTROL, p->cardctl);
343 pci_writeb (s, TI113X_DEVICE_CONTROL, p->devctl);
344 pci_writeb (s, TI1250_MULTIMEDIA_CTL, 0);
345 pci_writeb (s, TI1250_DIAGNOSTIC, p->diag);
346 pci_writel (s, TI12XX_IRQMUX, p->irqmux);
347 i365_set_pair (s, TI113X_IO_OFFSET (0), 0);
348 i365_set_pair (s, TI113X_IO_OFFSET (1), 0);
349}
350
351static u_int ti113x_set_opts (socket_info_t * s)
352{
353 ti113x_state_t *p = &s->state;
354 u_int mask = 0xffff;
355
356 p->cardctl &= ~TI113X_CCR_ZVENABLE;
357 p->cardctl |= TI113X_CCR_SPKROUTEN;
358
359 return mask;
360}
e2ffd59b 361#endif /* CONFIG_CPC45 */
66fd3d1c
WD
362
363/*======================================================================
364
365 Routines to handle common CardBus options
8bde7f77 366
66fd3d1c
WD
367======================================================================*/
368
369/* Default settings for PCI command configuration register */
370#define CMD_DFLT (PCI_COMMAND_IO|PCI_COMMAND_MEMORY| \
371 PCI_COMMAND_MASTER|PCI_COMMAND_WAIT)
372
373static void cb_get_state (socket_info_t * s)
374{
375 pci_readb (s, PCI_CACHE_LINE_SIZE, &s->cache);
376 pci_readb (s, PCI_LATENCY_TIMER, &s->pci_lat);
377 pci_readb (s, CB_LATENCY_TIMER, &s->cb_lat);
378 pci_readb (s, CB_CARDBUS_BUS, &s->cap.cardbus);
379 pci_readb (s, CB_SUBORD_BUS, &s->sub_bus);
380 pci_readw (s, CB_BRIDGE_CONTROL, &s->bcr);
381}
382
383static void cb_set_state (socket_info_t * s)
384{
e2ffd59b 385#ifndef CONFIG_CPC45
66fd3d1c
WD
386 pci_writel (s, CB_LEGACY_MODE_BASE, 0);
387 pci_writel (s, PCI_BASE_ADDRESS_0, s->cb_phys);
e2ffd59b 388#endif
66fd3d1c
WD
389 pci_writew (s, PCI_COMMAND, CMD_DFLT);
390 pci_writeb (s, PCI_CACHE_LINE_SIZE, s->cache);
391 pci_writeb (s, PCI_LATENCY_TIMER, s->pci_lat);
392 pci_writeb (s, CB_LATENCY_TIMER, s->cb_lat);
393 pci_writeb (s, CB_CARDBUS_BUS, s->cap.cardbus);
394 pci_writeb (s, CB_SUBORD_BUS, s->sub_bus);
395 pci_writew (s, CB_BRIDGE_CONTROL, s->bcr);
396}
397
398static void cb_set_opts (socket_info_t * s)
399{
e2ffd59b 400#ifndef CONFIG_CPC45
66fd3d1c
WD
401 if (s->cache == 0)
402 s->cache = 8;
403 if (s->pci_lat == 0)
404 s->pci_lat = 0xa8;
405 if (s->cb_lat == 0)
406 s->cb_lat = 0xb0;
e2ffd59b 407#endif
66fd3d1c
WD
408}
409
410/*======================================================================
411
412 Power control for Cardbus controllers: used both for 16-bit and
413 Cardbus cards.
8bde7f77 414
66fd3d1c
WD
415======================================================================*/
416
417static int cb_set_power (socket_info_t * s, socket_state_t * state)
418{
419 u_int reg = 0;
420
e2ffd59b
WD
421#ifdef CONFIG_CPC45
422
e2ffd59b
WD
423 reg = I365_PWR_NORESET;
424 if (state->flags & SS_PWR_AUTO)
425 reg |= I365_PWR_AUTO;
426 if (state->flags & SS_OUTPUT_ENA)
427 reg |= I365_PWR_OUT;
428 if (state->Vpp != 0) {
429 if (state->Vpp == 120) {
430 reg |= I365_VPP1_12V;
431 puts (" 12V card found: ");
432 } else if (state->Vpp == state->Vcc) {
433 reg |= I365_VPP1_5V;
e2ffd59b
WD
434 } else {
435 puts (" power not found: ");
436 return -1;
437 }
438 }
439 if (state->Vcc != 0) {
440 reg |= I365_VCC_5V;
441 if (state->Vcc == 33) {
442 puts (" 3.3V card found: ");
443 i365_bset (s, PD67_MISC_CTL_1, PD67_MC1_VCC_3V);
444 } else if (state->Vcc == 50) {
445 puts (" 5V card found: ");
446 i365_bclr (s, PD67_MISC_CTL_1, PD67_MC1_VCC_3V);
447 } else {
448 puts (" power not found: ");
449 return -1;
450 }
451 }
e799d375
WD
452
453 if (reg != i365_get (s, I365_POWER)) {
454 reg = (I365_PWR_OUT | I365_PWR_NORESET | I365_VCC_5V | I365_VPP1_5V);
e2ffd59b 455 i365_set (s, I365_POWER, reg);
e799d375 456 }
e2ffd59b
WD
457
458#else /* ! CONFIG_CPC45 */
459
66fd3d1c
WD
460 /* restart card voltage detection if it seems appropriate */
461 if ((state->Vcc == 0) && (state->Vpp == 0) &&
e2ffd59b 462 !(cb_readl (s, CB_SOCKET_STATE) & CB_SS_VSENSE))
66fd3d1c
WD
463 cb_writel (s, CB_SOCKET_FORCE, CB_SF_CVSTEST);
464 switch (state->Vcc) {
465 case 0:
466 reg = 0;
467 break;
468 case 33:
469 reg = CB_SC_VCC_3V;
470 break;
471 case 50:
472 reg = CB_SC_VCC_5V;
473 break;
474 default:
475 return -1;
476 }
477 switch (state->Vpp) {
478 case 0:
479 break;
480 case 33:
481 reg |= CB_SC_VPP_3V;
482 break;
483 case 50:
484 reg |= CB_SC_VPP_5V;
485 break;
486 case 120:
487 reg |= CB_SC_VPP_12V;
488 break;
489 default:
490 return -1;
491 }
492 if (reg != cb_readl (s, CB_SOCKET_CONTROL))
493 cb_writel (s, CB_SOCKET_CONTROL, reg);
e2ffd59b 494#endif /* CONFIG_CPC45 */
66fd3d1c
WD
495 return 0;
496}
497
498/*======================================================================
499
500 Generic routines to get and set controller options
8bde7f77 501
66fd3d1c
WD
502======================================================================*/
503
504static void get_bridge_state (socket_info_t * s)
505{
e2ffd59b
WD
506#ifdef CONFIG_CPC45
507 cirrus_get_state (s);
508#else
66fd3d1c 509 ti113x_get_state (s);
e2ffd59b 510#endif
66fd3d1c
WD
511 cb_get_state (s);
512}
513
514static void set_bridge_state (socket_info_t * s)
515{
516 cb_set_state (s);
517 i365_set (s, I365_GBLCTL, 0x00);
518 i365_set (s, I365_GENCTL, 0x00);
e2ffd59b
WD
519#ifdef CONFIG_CPC45
520 cirrus_set_state (s);
521#else
66fd3d1c 522 ti113x_set_state (s);
e2ffd59b 523#endif
66fd3d1c
WD
524}
525
526static void set_bridge_opts (socket_info_t * s)
527{
e2ffd59b
WD
528#ifdef CONFIG_CPC45
529 cirrus_set_opts (s);
530#else
66fd3d1c 531 ti113x_set_opts (s);
e2ffd59b 532#endif
66fd3d1c
WD
533 cb_set_opts (s);
534}
535
536/*====================================================================*/
e799d375
WD
537#define PD67_EXT_INDEX 0x2e /* Extension index */
538#define PD67_EXT_DATA 0x2f /* Extension data */
539#define PD67_EXD_VS1(s) (0x01 << ((s)<<1))
540
541#define pd67_ext_get(s, r) \
542 (i365_set(s, PD67_EXT_INDEX, r), i365_get(s, PD67_EXT_DATA))
66fd3d1c
WD
543
544static int i365_get_status (socket_info_t * s, u_int * value)
545{
546 u_int status;
e2ffd59b
WD
547#ifdef CONFIG_CPC45
548 u_char val;
549 u_char power, vcc, vpp;
e799d375 550 u_int powerstate;
e2ffd59b
WD
551#endif
552
553 status = i365_get (s, I365_IDENT);
66fd3d1c
WD
554 status = i365_get (s, I365_STATUS);
555 *value = ((status & I365_CS_DETECT) == I365_CS_DETECT) ? SS_DETECT : 0;
556 if (i365_get (s, I365_INTCTL) & I365_PC_IOCARD) {
557 *value |= (status & I365_CS_STSCHG) ? 0 : SS_STSCHG;
558 } else {
559 *value |= (status & I365_CS_BVD1) ? 0 : SS_BATDEAD;
560 *value |= (status & I365_CS_BVD2) ? 0 : SS_BATWARN;
561 }
562 *value |= (status & I365_CS_WRPROT) ? SS_WRPROT : 0;
563 *value |= (status & I365_CS_READY) ? SS_READY : 0;
564 *value |= (status & I365_CS_POWERON) ? SS_POWERON : 0;
565
e2ffd59b
WD
566#ifdef CONFIG_CPC45
567 /* Check for Cirrus CL-PD67xx chips */
568 i365_set (s, PD67_CHIP_INFO, 0);
569 val = i365_get (s, PD67_CHIP_INFO);
570 s->type = -1;
571 if ((val & PD67_INFO_CHIP_ID) == PD67_INFO_CHIP_ID) {
572 val = i365_get (s, PD67_CHIP_INFO);
573 if ((val & PD67_INFO_CHIP_ID) == 0) {
c3d2b4b4 574 s->type = (val & PD67_INFO_SLOTS) ? IS_PD672X : IS_PD6710;
e2ffd59b
WD
575 i365_set (s, PD67_EXT_INDEX, 0xe5);
576 if (i365_get (s, PD67_EXT_INDEX) != 0xe5)
577 s->type = IS_VT83C469;
578 }
579 } else {
580 printf ("no Cirrus Chip found\n");
581 *value = 0;
582 return -1;
583 }
584
e2ffd59b
WD
585 power = i365_get (s, I365_POWER);
586 state.flags |= (power & I365_PWR_AUTO) ? SS_PWR_AUTO : 0;
587 state.flags |= (power & I365_PWR_OUT) ? SS_OUTPUT_ENA : 0;
588 vcc = power & I365_VCC_MASK;
589 vpp = power & I365_VPP1_MASK;
590 state.Vcc = state.Vpp = 0;
e799d375
WD
591 if((vcc== 0) || (vpp == 0)) {
592 /*
593 * On the Cirrus we get the info which card voltage
594 * we have in EXTERN DATA and write it to MISC_CTL1
595 */
596 powerstate = pd67_ext_get(s, PD67_EXTERN_DATA);
597 if (powerstate & PD67_EXD_VS1(0)) {
598 /* 5V Card */
599 i365_bclr (s, PD67_MISC_CTL_1, PD67_MC1_VCC_3V);
600 } else {
601 /* 3.3V Card */
602 i365_bset (s, PD67_MISC_CTL_1, PD67_MC1_VCC_3V);
603 }
604 i365_set (s, I365_POWER, (I365_PWR_OUT | I365_PWR_NORESET | I365_VCC_5V | I365_VPP1_5V));
605 power = i365_get (s, I365_POWER);
e2ffd59b 606 }
e799d375
WD
607 if (power & I365_VCC_5V) {
608 state.Vcc = (i365_get(s, PD67_MISC_CTL_1) & PD67_MC1_VCC_3V) ? 33 : 50;
609 }
610
e2ffd59b
WD
611 if (power == I365_VPP1_12V)
612 state.Vpp = 120;
613
614 /* IO card, RESET flags, IO interrupt */
615 power = i365_get (s, I365_INTCTL);
616 state.flags |= (power & I365_PC_RESET) ? 0 : SS_RESET;
617 if (power & I365_PC_IOCARD)
618 state.flags |= SS_IOCARD;
619 state.io_irq = power & I365_IRQ_MASK;
620
621 /* Card status change mask */
622 power = i365_get (s, I365_CSCINT);
623 state.csc_mask = (power & I365_CSC_DETECT) ? SS_DETECT : 0;
624 if (state.flags & SS_IOCARD)
625 state.csc_mask |= (power & I365_CSC_STSCHG) ? SS_STSCHG : 0;
626 else {
627 state.csc_mask |= (power & I365_CSC_BVD1) ? SS_BATDEAD : 0;
628 state.csc_mask |= (power & I365_CSC_BVD2) ? SS_BATWARN : 0;
629 state.csc_mask |= (power & I365_CSC_READY) ? SS_READY : 0;
630 }
631 debug ("i82365: GetStatus(0) = flags %#3.3x, Vcc %d, Vpp %d, "
632 "io_irq %d, csc_mask %#2.2x\n", state.flags,
633 state.Vcc, state.Vpp, state.io_irq, state.csc_mask);
634
635#else /* !CONFIG_CPC45 */
636
66fd3d1c
WD
637 status = cb_readl (s, CB_SOCKET_STATE);
638 *value |= (status & CB_SS_32BIT) ? SS_CARDBUS : 0;
639 *value |= (status & CB_SS_3VCARD) ? SS_3VCARD : 0;
640 *value |= (status & CB_SS_XVCARD) ? SS_XVCARD : 0;
641 *value |= (status & CB_SS_VSENSE) ? 0 : SS_PENDING;
642 /* For now, ignore cards with unsupported voltage keys */
643 if (*value & SS_XVCARD)
644 *value &= ~(SS_DETECT | SS_3VCARD | SS_XVCARD);
e2ffd59b 645#endif /* CONFIG_CPC45 */
66fd3d1c
WD
646 return 0;
647} /* i365_get_status */
648
649static int i365_set_socket (socket_info_t * s, socket_state_t * state)
650{
651 u_char reg;
652
653 set_bridge_state (s);
654
655 /* IO card, RESET flag */
656 reg = 0;
657 reg |= (state->flags & SS_RESET) ? 0 : I365_PC_RESET;
658 reg |= (state->flags & SS_IOCARD) ? I365_PC_IOCARD : 0;
659 i365_set (s, I365_INTCTL, reg);
660
e2ffd59b
WD
661#ifdef CONFIG_CPC45
662 cb_set_power (s, state);
663
664#if 0
665 /* Card status change interrupt mask */
666 reg = s->cs_irq << 4;
667 if (state->csc_mask & SS_DETECT)
668 reg |= I365_CSC_DETECT;
669 if (state->flags & SS_IOCARD) {
670 if (state->csc_mask & SS_STSCHG)
671 reg |= I365_CSC_STSCHG;
672 } else {
673 if (state->csc_mask & SS_BATDEAD)
674 reg |= I365_CSC_BVD1;
675 if (state->csc_mask & SS_BATWARN)
676 reg |= I365_CSC_BVD2;
677 if (state->csc_mask & SS_READY)
678 reg |= I365_CSC_READY;
679 }
680 i365_set (s, I365_CSCINT, reg);
681 i365_get (s, I365_CSC);
682#endif /* 0 */
683
684#else /* !CONFIG_CPC45 */
685
66fd3d1c
WD
686 reg = I365_PWR_NORESET;
687 if (state->flags & SS_PWR_AUTO)
688 reg |= I365_PWR_AUTO;
689 if (state->flags & SS_OUTPUT_ENA)
690 reg |= I365_PWR_OUT;
691
692 cb_set_power (s, state);
693 reg |= i365_get (s, I365_POWER) & (I365_VCC_MASK | I365_VPP1_MASK);
694
695 if (reg != i365_get (s, I365_POWER))
696 i365_set (s, I365_POWER, reg);
e2ffd59b 697#endif /* CONFIG_CPC45 */
66fd3d1c
WD
698
699 return 0;
700} /* i365_set_socket */
701
702/*====================================================================*/
703
704static int i365_set_mem_map (socket_info_t * s, struct pccard_mem_map *mem)
705{
706 u_short base, i;
707 u_char map;
708
e2ffd59b
WD
709 debug ("i82365: SetMemMap(%d, %#2.2x, %d ns, %#5.5lx-%#5.5lx, %#5.5x)\n",
710 mem->map, mem->flags, mem->speed,
711 mem->sys_start, mem->sys_stop, mem->card_start);
712
66fd3d1c
WD
713 map = mem->map;
714 if ((map > 4) ||
715 (mem->card_start > 0x3ffffff) ||
716 (mem->sys_start > mem->sys_stop) ||
717 (mem->speed > 1000)) {
718 return -1;
719 }
720
721 /* Turn off the window before changing anything */
722 if (i365_get (s, I365_ADDRWIN) & I365_ENA_MEM (map))
723 i365_bclr (s, I365_ADDRWIN, I365_ENA_MEM (map));
724
725 /* Take care of high byte, for PCI controllers */
726 i365_set (s, CB_MEM_PAGE (map), mem->sys_start >> 24);
727
728 base = I365_MEM (map);
729 i = (mem->sys_start >> 12) & 0x0fff;
730 if (mem->flags & MAP_16BIT)
731 i |= I365_MEM_16BIT;
732 if (mem->flags & MAP_0WS)
733 i |= I365_MEM_0WS;
734 i365_set_pair (s, base + I365_W_START, i);
735
736 i = (mem->sys_stop >> 12) & 0x0fff;
737 switch (mem->speed / CYCLE_TIME) {
738 case 0:
739 break;
740 case 1:
741 i |= I365_MEM_WS0;
742 break;
743 case 2:
744 i |= I365_MEM_WS1;
745 break;
746 default:
747 i |= I365_MEM_WS1 | I365_MEM_WS0;
748 break;
749 }
750 i365_set_pair (s, base + I365_W_STOP, i);
751
e2ffd59b
WD
752#ifdef CONFIG_CPC45
753 i = 0;
754#else
66fd3d1c 755 i = ((mem->card_start - mem->sys_start) >> 12) & 0x3fff;
e2ffd59b 756#endif
66fd3d1c
WD
757 if (mem->flags & MAP_WRPROT)
758 i |= I365_MEM_WRPROT;
759 if (mem->flags & MAP_ATTRIB)
760 i |= I365_MEM_REG;
761 i365_set_pair (s, base + I365_W_OFF, i);
762
e2ffd59b
WD
763#ifdef CONFIG_CPC45
764 /* set System Memory map Upper Adress */
765 i365_set(s, PD67_EXT_INDEX, PD67_MEM_PAGE(map));
766 i365_set(s, PD67_EXT_DATA, ((mem->sys_start >> 24) & 0xff));
767#endif
768
66fd3d1c
WD
769 /* Turn on the window if necessary */
770 if (mem->flags & MAP_ACTIVE)
771 i365_bset (s, I365_ADDRWIN, I365_ENA_MEM (map));
772 return 0;
773} /* i365_set_mem_map */
774
775static int i365_set_io_map (socket_info_t * s, struct pccard_io_map *io)
776{
777 u_char map, ioctl;
778
779 map = io->map;
eedcd078
WD
780 /* comment out: comparison is always false due to limited range of data type */
781 if ((map > 1) || /* (io->start > 0xffff) || (io->stop > 0xffff) || */
e2ffd59b 782 (io->stop < io->start))
66fd3d1c
WD
783 return -1;
784 /* Turn off the window before changing anything */
785 if (i365_get (s, I365_ADDRWIN) & I365_ENA_IO (map))
786 i365_bclr (s, I365_ADDRWIN, I365_ENA_IO (map));
787 i365_set_pair (s, I365_IO (map) + I365_W_START, io->start);
788 i365_set_pair (s, I365_IO (map) + I365_W_STOP, io->stop);
789 ioctl = i365_get (s, I365_IOCTL) & ~I365_IOCTL_MASK (map);
790 if (io->speed)
791 ioctl |= I365_IOCTL_WAIT (map);
792 if (io->flags & MAP_0WS)
793 ioctl |= I365_IOCTL_0WS (map);
794 if (io->flags & MAP_16BIT)
795 ioctl |= I365_IOCTL_16BIT (map);
796 if (io->flags & MAP_AUTOSZ)
797 ioctl |= I365_IOCTL_IOCS16 (map);
798 i365_set (s, I365_IOCTL, ioctl);
799 /* Turn on the window if necessary */
800 if (io->flags & MAP_ACTIVE)
801 i365_bset (s, I365_ADDRWIN, I365_ENA_IO (map));
802 return 0;
803} /* i365_set_io_map */
804
805/*====================================================================*/
806
807int i82365_init (void)
808{
809 u_int val;
810 int i;
811
e2ffd59b
WD
812#ifdef CONFIG_CPC45
813 if (SPD67290Init () != 0)
814 return 1;
815#endif
66fd3d1c
WD
816 if ((socket.dev = pci_find_devices (supported, 0)) < 0) {
817 /* Controller not found */
818 return 1;
819 }
e2ffd59b 820 debug ("i82365 Device Found!\n");
66fd3d1c
WD
821
822 pci_read_config_dword (socket.dev, PCI_BASE_ADDRESS_0, &socket.cb_phys);
823 socket.cb_phys &= ~0xf;
824
e2ffd59b
WD
825#ifdef CONFIG_CPC45
826 /* + 0xfe000000 see MPC 8245 Users Manual Adress Map B */
827 socket.cb_phys += 0xfe000000;
828#endif
829
66fd3d1c
WD
830 get_bridge_state (&socket);
831 set_bridge_opts (&socket);
832
e2ffd59b 833 i = i365_get_status (&socket, &val);
66fd3d1c 834
e2ffd59b
WD
835#ifdef CONFIG_CPC45
836 if (i > -1) {
837 puts (pcic[socket.type].name);
838 } else {
839 printf ("i82365: Controller not found.\n");
840 return 1;
841 }
436be29c
WD
842 if((val & SS_DETECT) != SS_DETECT){
843 puts ("No card\n");
844 return 1;
845 }
e2ffd59b 846#else /* !CONFIG_CPC45 */
66fd3d1c
WD
847 if (val & SS_DETECT) {
848 if (val & SS_3VCARD) {
849 state.Vcc = state.Vpp = 33;
850 puts (" 3.3V card found: ");
851 } else if (!(val & SS_XVCARD)) {
852 state.Vcc = state.Vpp = 50;
853 puts (" 5.0V card found: ");
854 } else {
e2ffd59b 855 puts ("i82365: unsupported voltage key\n");
66fd3d1c
WD
856 state.Vcc = state.Vpp = 0;
857 }
858 } else {
859 /* No card inserted */
e2ffd59b 860 puts ("No card\n");
66fd3d1c
WD
861 return 1;
862 }
e2ffd59b 863#endif /* CONFIG_CPC45 */
66fd3d1c 864
e2ffd59b
WD
865#ifdef CONFIG_CPC45
866 state.flags |= SS_OUTPUT_ENA;
867#else
66fd3d1c
WD
868 state.flags = SS_IOCARD | SS_OUTPUT_ENA;
869 state.csc_mask = 0;
870 state.io_irq = 0;
e2ffd59b 871#endif
66fd3d1c
WD
872
873 i365_set_socket (&socket, &state);
874
875 for (i = 500; i; i--) {
876 if ((i365_get (&socket, I365_STATUS) & I365_CS_READY))
877 break;
878 udelay (1000);
879 }
880
881 if (i == 0) {
882 /* PC Card not ready for data transfer */
e2ffd59b 883 puts ("i82365 PC Card not ready for data transfer\n");
66fd3d1c
WD
884 return 1;
885 }
e2ffd59b 886 debug (" PC Card ready for data transfer: ");
66fd3d1c
WD
887
888 mem.map = 0;
889 mem.flags = MAP_ATTRIB | MAP_ACTIVE;
890 mem.speed = 300;
6d0f6bcf
JCPV
891 mem.sys_start = CONFIG_SYS_PCMCIA_MEM_ADDR;
892 mem.sys_stop = CONFIG_SYS_PCMCIA_MEM_ADDR + CONFIG_SYS_PCMCIA_MEM_SIZE - 1;
66fd3d1c 893 mem.card_start = 0;
e2ffd59b 894 i365_set_mem_map (&socket, &mem);
66fd3d1c 895
e2ffd59b
WD
896#ifdef CONFIG_CPC45
897 mem.map = 1;
898 mem.flags = MAP_ACTIVE;
899 mem.speed = 300;
6d0f6bcf
JCPV
900 mem.sys_start = CONFIG_SYS_PCMCIA_MEM_ADDR + CONFIG_SYS_PCMCIA_MEM_SIZE;
901 mem.sys_stop = CONFIG_SYS_PCMCIA_MEM_ADDR + (2 * CONFIG_SYS_PCMCIA_MEM_SIZE) - 1;
e2ffd59b 902 mem.card_start = 0;
66fd3d1c
WD
903 i365_set_mem_map (&socket, &mem);
904
e2ffd59b
WD
905#else /* !CONFIG_CPC45 */
906
66fd3d1c
WD
907 io.map = 0;
908 io.flags = MAP_AUTOSZ | MAP_ACTIVE;
909 io.speed = 0;
910 io.start = 0x0100;
911 io.stop = 0x010F;
66fd3d1c
WD
912 i365_set_io_map (&socket, &io);
913
e2ffd59b
WD
914#endif /* CONFIG_CPC45 */
915
66fd3d1c
WD
916#ifdef DEBUG
917 i82365_dump_regions (socket.dev);
918#endif
919
920 return 0;
921}
922
923void i82365_exit (void)
924{
925 io.map = 0;
926 io.flags = 0;
927 io.speed = 0;
928 io.start = 0;
929 io.stop = 0x1;
930
931 i365_set_io_map (&socket, &io);
932
933 mem.map = 0;
934 mem.flags = 0;
935 mem.speed = 0;
936 mem.sys_start = 0;
937 mem.sys_stop = 0x1000;
938 mem.card_start = 0;
939
940 i365_set_mem_map (&socket, &mem);
941
e2ffd59b
WD
942#ifdef CONFIG_CPC45
943 mem.map = 1;
944 mem.flags = 0;
945 mem.speed = 0;
946 mem.sys_start = 0;
947 mem.sys_stop = 0x1000;
948 mem.card_start = 0;
66fd3d1c 949
e2ffd59b
WD
950 i365_set_mem_map (&socket, &mem);
951#else /* !CONFIG_CPC45 */
952 socket.state.sysctl &= 0xFFFF00FF;
953#endif
66fd3d1c
WD
954 state.Vcc = state.Vpp = 0;
955
956 i365_set_socket (&socket, &state);
957}
958
959/*======================================================================
960
961 Debug stuff
8bde7f77 962
66fd3d1c
WD
963======================================================================*/
964
965#ifdef DEBUG
966static void i82365_dump_regions (pci_dev_t dev)
967{
968 u_int tmp[2];
e2ffd59b 969 u_int *mem = (void *) socket.cb_phys;
6d0f6bcf
JCPV
970 u_char *cis = (void *) CONFIG_SYS_PCMCIA_MEM_ADDR;
971 u_char *ide = (void *) (CONFIG_SYS_ATA_BASE_ADDR + CONFIG_SYS_ATA_REG_OFFSET);
66fd3d1c
WD
972
973 pci_read_config_dword (dev, 0x00, tmp + 0);
974 pci_read_config_dword (dev, 0x80, tmp + 1);
975
c3d2b4b4
WD
976 printf ("PCI CONF: %08X ... %08X\n",
977 tmp[0], tmp[1]);
978 printf ("PCI MEM: ... %08X ... %08X\n",
979 mem[0x8 / 4], mem[0x800 / 4]);
66fd3d1c
WD
980 printf ("CIS: ...%c%c%c%c%c%c%c%c...\n",
981 cis[0x38], cis[0x3a], cis[0x3c], cis[0x3e],
982 cis[0x40], cis[0x42], cis[0x44], cis[0x48]);
983 printf ("CIS CONF: %02X %02X %02X ...\n",
984 cis[0x200], cis[0x202], cis[0x204]);
985 printf ("IDE: %02X %02X %02X %02X %02X %02X %02X %02X\n",
986 ide[0], ide[1], ide[2], ide[3],
987 ide[4], ide[5], ide[6], ide[7]);
988}
989#endif /* DEBUG */