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