]> git.ipfire.org Git - people/ms/u-boot.git/blame - drivers/i82365.c
Files include/linux/byteorder/{big,little}_endian.h define
[people/ms/u-boot.git] / drivers / i82365.c
CommitLineData
66fd3d1c 1/*
e799d375 2 * (C) Copyright 2003-2005
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
e2ffd59b
WD
446 reg = I365_PWR_NORESET;
447 if (state->flags & SS_PWR_AUTO)
448 reg |= I365_PWR_AUTO;
449 if (state->flags & SS_OUTPUT_ENA)
450 reg |= I365_PWR_OUT;
451 if (state->Vpp != 0) {
452 if (state->Vpp == 120) {
453 reg |= I365_VPP1_12V;
454 puts (" 12V card found: ");
455 } else if (state->Vpp == state->Vcc) {
456 reg |= I365_VPP1_5V;
e2ffd59b
WD
457 } else {
458 puts (" power not found: ");
459 return -1;
460 }
461 }
462 if (state->Vcc != 0) {
463 reg |= I365_VCC_5V;
464 if (state->Vcc == 33) {
465 puts (" 3.3V card found: ");
466 i365_bset (s, PD67_MISC_CTL_1, PD67_MC1_VCC_3V);
467 } else if (state->Vcc == 50) {
468 puts (" 5V card found: ");
469 i365_bclr (s, PD67_MISC_CTL_1, PD67_MC1_VCC_3V);
470 } else {
471 puts (" power not found: ");
472 return -1;
473 }
474 }
e799d375
WD
475
476 if (reg != i365_get (s, I365_POWER)) {
477 reg = (I365_PWR_OUT | I365_PWR_NORESET | I365_VCC_5V | I365_VPP1_5V);
e2ffd59b 478 i365_set (s, I365_POWER, reg);
e799d375 479 }
e2ffd59b
WD
480
481#else /* ! CONFIG_CPC45 */
482
66fd3d1c
WD
483 /* restart card voltage detection if it seems appropriate */
484 if ((state->Vcc == 0) && (state->Vpp == 0) &&
e2ffd59b 485 !(cb_readl (s, CB_SOCKET_STATE) & CB_SS_VSENSE))
66fd3d1c
WD
486 cb_writel (s, CB_SOCKET_FORCE, CB_SF_CVSTEST);
487 switch (state->Vcc) {
488 case 0:
489 reg = 0;
490 break;
491 case 33:
492 reg = CB_SC_VCC_3V;
493 break;
494 case 50:
495 reg = CB_SC_VCC_5V;
496 break;
497 default:
498 return -1;
499 }
500 switch (state->Vpp) {
501 case 0:
502 break;
503 case 33:
504 reg |= CB_SC_VPP_3V;
505 break;
506 case 50:
507 reg |= CB_SC_VPP_5V;
508 break;
509 case 120:
510 reg |= CB_SC_VPP_12V;
511 break;
512 default:
513 return -1;
514 }
515 if (reg != cb_readl (s, CB_SOCKET_CONTROL))
516 cb_writel (s, CB_SOCKET_CONTROL, reg);
e2ffd59b 517#endif /* CONFIG_CPC45 */
66fd3d1c
WD
518 return 0;
519}
520
521/*======================================================================
522
523 Generic routines to get and set controller options
8bde7f77 524
66fd3d1c
WD
525======================================================================*/
526
527static void get_bridge_state (socket_info_t * s)
528{
e2ffd59b
WD
529#ifdef CONFIG_CPC45
530 cirrus_get_state (s);
531#else
66fd3d1c 532 ti113x_get_state (s);
e2ffd59b 533#endif
66fd3d1c
WD
534 cb_get_state (s);
535}
536
537static void set_bridge_state (socket_info_t * s)
538{
539 cb_set_state (s);
540 i365_set (s, I365_GBLCTL, 0x00);
541 i365_set (s, I365_GENCTL, 0x00);
e2ffd59b
WD
542#ifdef CONFIG_CPC45
543 cirrus_set_state (s);
544#else
66fd3d1c 545 ti113x_set_state (s);
e2ffd59b 546#endif
66fd3d1c
WD
547}
548
549static void set_bridge_opts (socket_info_t * s)
550{
e2ffd59b
WD
551#ifdef CONFIG_CPC45
552 cirrus_set_opts (s);
553#else
66fd3d1c 554 ti113x_set_opts (s);
e2ffd59b 555#endif
66fd3d1c
WD
556 cb_set_opts (s);
557}
558
559/*====================================================================*/
e799d375
WD
560#define PD67_EXT_INDEX 0x2e /* Extension index */
561#define PD67_EXT_DATA 0x2f /* Extension data */
562#define PD67_EXD_VS1(s) (0x01 << ((s)<<1))
563
564#define pd67_ext_get(s, r) \
565 (i365_set(s, PD67_EXT_INDEX, r), i365_get(s, PD67_EXT_DATA))
66fd3d1c
WD
566
567static int i365_get_status (socket_info_t * s, u_int * value)
568{
569 u_int status;
e2ffd59b
WD
570#ifdef CONFIG_CPC45
571 u_char val;
572 u_char power, vcc, vpp;
e799d375 573 u_int powerstate;
e2ffd59b
WD
574#endif
575
576 status = i365_get (s, I365_IDENT);
66fd3d1c
WD
577 status = i365_get (s, I365_STATUS);
578 *value = ((status & I365_CS_DETECT) == I365_CS_DETECT) ? SS_DETECT : 0;
579 if (i365_get (s, I365_INTCTL) & I365_PC_IOCARD) {
580 *value |= (status & I365_CS_STSCHG) ? 0 : SS_STSCHG;
581 } else {
582 *value |= (status & I365_CS_BVD1) ? 0 : SS_BATDEAD;
583 *value |= (status & I365_CS_BVD2) ? 0 : SS_BATWARN;
584 }
585 *value |= (status & I365_CS_WRPROT) ? SS_WRPROT : 0;
586 *value |= (status & I365_CS_READY) ? SS_READY : 0;
587 *value |= (status & I365_CS_POWERON) ? SS_POWERON : 0;
588
e2ffd59b
WD
589#ifdef CONFIG_CPC45
590 /* Check for Cirrus CL-PD67xx chips */
591 i365_set (s, PD67_CHIP_INFO, 0);
592 val = i365_get (s, PD67_CHIP_INFO);
593 s->type = -1;
594 if ((val & PD67_INFO_CHIP_ID) == PD67_INFO_CHIP_ID) {
595 val = i365_get (s, PD67_CHIP_INFO);
596 if ((val & PD67_INFO_CHIP_ID) == 0) {
c3d2b4b4 597 s->type = (val & PD67_INFO_SLOTS) ? IS_PD672X : IS_PD6710;
e2ffd59b
WD
598 i365_set (s, PD67_EXT_INDEX, 0xe5);
599 if (i365_get (s, PD67_EXT_INDEX) != 0xe5)
600 s->type = IS_VT83C469;
601 }
602 } else {
603 printf ("no Cirrus Chip found\n");
604 *value = 0;
605 return -1;
606 }
607
e2ffd59b
WD
608 power = i365_get (s, I365_POWER);
609 state.flags |= (power & I365_PWR_AUTO) ? SS_PWR_AUTO : 0;
610 state.flags |= (power & I365_PWR_OUT) ? SS_OUTPUT_ENA : 0;
611 vcc = power & I365_VCC_MASK;
612 vpp = power & I365_VPP1_MASK;
613 state.Vcc = state.Vpp = 0;
e799d375
WD
614 if((vcc== 0) || (vpp == 0)) {
615 /*
616 * On the Cirrus we get the info which card voltage
617 * we have in EXTERN DATA and write it to MISC_CTL1
618 */
619 powerstate = pd67_ext_get(s, PD67_EXTERN_DATA);
620 if (powerstate & PD67_EXD_VS1(0)) {
621 /* 5V Card */
622 i365_bclr (s, PD67_MISC_CTL_1, PD67_MC1_VCC_3V);
623 } else {
624 /* 3.3V Card */
625 i365_bset (s, PD67_MISC_CTL_1, PD67_MC1_VCC_3V);
626 }
627 i365_set (s, I365_POWER, (I365_PWR_OUT | I365_PWR_NORESET | I365_VCC_5V | I365_VPP1_5V));
628 power = i365_get (s, I365_POWER);
e2ffd59b 629 }
e799d375
WD
630 if (power & I365_VCC_5V) {
631 state.Vcc = (i365_get(s, PD67_MISC_CTL_1) & PD67_MC1_VCC_3V) ? 33 : 50;
632 }
633
e2ffd59b
WD
634 if (power == I365_VPP1_12V)
635 state.Vpp = 120;
636
637 /* IO card, RESET flags, IO interrupt */
638 power = i365_get (s, I365_INTCTL);
639 state.flags |= (power & I365_PC_RESET) ? 0 : SS_RESET;
640 if (power & I365_PC_IOCARD)
641 state.flags |= SS_IOCARD;
642 state.io_irq = power & I365_IRQ_MASK;
643
644 /* Card status change mask */
645 power = i365_get (s, I365_CSCINT);
646 state.csc_mask = (power & I365_CSC_DETECT) ? SS_DETECT : 0;
647 if (state.flags & SS_IOCARD)
648 state.csc_mask |= (power & I365_CSC_STSCHG) ? SS_STSCHG : 0;
649 else {
650 state.csc_mask |= (power & I365_CSC_BVD1) ? SS_BATDEAD : 0;
651 state.csc_mask |= (power & I365_CSC_BVD2) ? SS_BATWARN : 0;
652 state.csc_mask |= (power & I365_CSC_READY) ? SS_READY : 0;
653 }
654 debug ("i82365: GetStatus(0) = flags %#3.3x, Vcc %d, Vpp %d, "
655 "io_irq %d, csc_mask %#2.2x\n", state.flags,
656 state.Vcc, state.Vpp, state.io_irq, state.csc_mask);
657
658#else /* !CONFIG_CPC45 */
659
66fd3d1c
WD
660 status = cb_readl (s, CB_SOCKET_STATE);
661 *value |= (status & CB_SS_32BIT) ? SS_CARDBUS : 0;
662 *value |= (status & CB_SS_3VCARD) ? SS_3VCARD : 0;
663 *value |= (status & CB_SS_XVCARD) ? SS_XVCARD : 0;
664 *value |= (status & CB_SS_VSENSE) ? 0 : SS_PENDING;
665 /* For now, ignore cards with unsupported voltage keys */
666 if (*value & SS_XVCARD)
667 *value &= ~(SS_DETECT | SS_3VCARD | SS_XVCARD);
e2ffd59b 668#endif /* CONFIG_CPC45 */
66fd3d1c
WD
669 return 0;
670} /* i365_get_status */
671
672static int i365_set_socket (socket_info_t * s, socket_state_t * state)
673{
674 u_char reg;
675
676 set_bridge_state (s);
677
678 /* IO card, RESET flag */
679 reg = 0;
680 reg |= (state->flags & SS_RESET) ? 0 : I365_PC_RESET;
681 reg |= (state->flags & SS_IOCARD) ? I365_PC_IOCARD : 0;
682 i365_set (s, I365_INTCTL, reg);
683
e2ffd59b
WD
684#ifdef CONFIG_CPC45
685 cb_set_power (s, state);
686
687#if 0
688 /* Card status change interrupt mask */
689 reg = s->cs_irq << 4;
690 if (state->csc_mask & SS_DETECT)
691 reg |= I365_CSC_DETECT;
692 if (state->flags & SS_IOCARD) {
693 if (state->csc_mask & SS_STSCHG)
694 reg |= I365_CSC_STSCHG;
695 } else {
696 if (state->csc_mask & SS_BATDEAD)
697 reg |= I365_CSC_BVD1;
698 if (state->csc_mask & SS_BATWARN)
699 reg |= I365_CSC_BVD2;
700 if (state->csc_mask & SS_READY)
701 reg |= I365_CSC_READY;
702 }
703 i365_set (s, I365_CSCINT, reg);
704 i365_get (s, I365_CSC);
705#endif /* 0 */
706
707#else /* !CONFIG_CPC45 */
708
66fd3d1c
WD
709 reg = I365_PWR_NORESET;
710 if (state->flags & SS_PWR_AUTO)
711 reg |= I365_PWR_AUTO;
712 if (state->flags & SS_OUTPUT_ENA)
713 reg |= I365_PWR_OUT;
714
715 cb_set_power (s, state);
716 reg |= i365_get (s, I365_POWER) & (I365_VCC_MASK | I365_VPP1_MASK);
717
718 if (reg != i365_get (s, I365_POWER))
719 i365_set (s, I365_POWER, reg);
e2ffd59b 720#endif /* CONFIG_CPC45 */
66fd3d1c
WD
721
722 return 0;
723} /* i365_set_socket */
724
725/*====================================================================*/
726
727static int i365_set_mem_map (socket_info_t * s, struct pccard_mem_map *mem)
728{
729 u_short base, i;
730 u_char map;
731
e2ffd59b
WD
732 debug ("i82365: SetMemMap(%d, %#2.2x, %d ns, %#5.5lx-%#5.5lx, %#5.5x)\n",
733 mem->map, mem->flags, mem->speed,
734 mem->sys_start, mem->sys_stop, mem->card_start);
735
66fd3d1c
WD
736 map = mem->map;
737 if ((map > 4) ||
738 (mem->card_start > 0x3ffffff) ||
739 (mem->sys_start > mem->sys_stop) ||
740 (mem->speed > 1000)) {
741 return -1;
742 }
743
744 /* Turn off the window before changing anything */
745 if (i365_get (s, I365_ADDRWIN) & I365_ENA_MEM (map))
746 i365_bclr (s, I365_ADDRWIN, I365_ENA_MEM (map));
747
748 /* Take care of high byte, for PCI controllers */
749 i365_set (s, CB_MEM_PAGE (map), mem->sys_start >> 24);
750
751 base = I365_MEM (map);
752 i = (mem->sys_start >> 12) & 0x0fff;
753 if (mem->flags & MAP_16BIT)
754 i |= I365_MEM_16BIT;
755 if (mem->flags & MAP_0WS)
756 i |= I365_MEM_0WS;
757 i365_set_pair (s, base + I365_W_START, i);
758
759 i = (mem->sys_stop >> 12) & 0x0fff;
760 switch (mem->speed / CYCLE_TIME) {
761 case 0:
762 break;
763 case 1:
764 i |= I365_MEM_WS0;
765 break;
766 case 2:
767 i |= I365_MEM_WS1;
768 break;
769 default:
770 i |= I365_MEM_WS1 | I365_MEM_WS0;
771 break;
772 }
773 i365_set_pair (s, base + I365_W_STOP, i);
774
e2ffd59b
WD
775#ifdef CONFIG_CPC45
776 i = 0;
777#else
66fd3d1c 778 i = ((mem->card_start - mem->sys_start) >> 12) & 0x3fff;
e2ffd59b 779#endif
66fd3d1c
WD
780 if (mem->flags & MAP_WRPROT)
781 i |= I365_MEM_WRPROT;
782 if (mem->flags & MAP_ATTRIB)
783 i |= I365_MEM_REG;
784 i365_set_pair (s, base + I365_W_OFF, i);
785
e2ffd59b
WD
786#ifdef CONFIG_CPC45
787 /* set System Memory map Upper Adress */
788 i365_set(s, PD67_EXT_INDEX, PD67_MEM_PAGE(map));
789 i365_set(s, PD67_EXT_DATA, ((mem->sys_start >> 24) & 0xff));
790#endif
791
66fd3d1c
WD
792 /* Turn on the window if necessary */
793 if (mem->flags & MAP_ACTIVE)
794 i365_bset (s, I365_ADDRWIN, I365_ENA_MEM (map));
795 return 0;
796} /* i365_set_mem_map */
797
798static int i365_set_io_map (socket_info_t * s, struct pccard_io_map *io)
799{
800 u_char map, ioctl;
801
802 map = io->map;
eedcd078
WD
803 /* comment out: comparison is always false due to limited range of data type */
804 if ((map > 1) || /* (io->start > 0xffff) || (io->stop > 0xffff) || */
e2ffd59b 805 (io->stop < io->start))
66fd3d1c
WD
806 return -1;
807 /* Turn off the window before changing anything */
808 if (i365_get (s, I365_ADDRWIN) & I365_ENA_IO (map))
809 i365_bclr (s, I365_ADDRWIN, I365_ENA_IO (map));
810 i365_set_pair (s, I365_IO (map) + I365_W_START, io->start);
811 i365_set_pair (s, I365_IO (map) + I365_W_STOP, io->stop);
812 ioctl = i365_get (s, I365_IOCTL) & ~I365_IOCTL_MASK (map);
813 if (io->speed)
814 ioctl |= I365_IOCTL_WAIT (map);
815 if (io->flags & MAP_0WS)
816 ioctl |= I365_IOCTL_0WS (map);
817 if (io->flags & MAP_16BIT)
818 ioctl |= I365_IOCTL_16BIT (map);
819 if (io->flags & MAP_AUTOSZ)
820 ioctl |= I365_IOCTL_IOCS16 (map);
821 i365_set (s, I365_IOCTL, ioctl);
822 /* Turn on the window if necessary */
823 if (io->flags & MAP_ACTIVE)
824 i365_bset (s, I365_ADDRWIN, I365_ENA_IO (map));
825 return 0;
826} /* i365_set_io_map */
827
828/*====================================================================*/
829
830int i82365_init (void)
831{
832 u_int val;
833 int i;
834
e2ffd59b
WD
835#ifdef CONFIG_CPC45
836 if (SPD67290Init () != 0)
837 return 1;
838#endif
66fd3d1c
WD
839 if ((socket.dev = pci_find_devices (supported, 0)) < 0) {
840 /* Controller not found */
841 return 1;
842 }
e2ffd59b 843 debug ("i82365 Device Found!\n");
66fd3d1c
WD
844
845 pci_read_config_dword (socket.dev, PCI_BASE_ADDRESS_0, &socket.cb_phys);
846 socket.cb_phys &= ~0xf;
847
e2ffd59b
WD
848#ifdef CONFIG_CPC45
849 /* + 0xfe000000 see MPC 8245 Users Manual Adress Map B */
850 socket.cb_phys += 0xfe000000;
851#endif
852
66fd3d1c
WD
853 get_bridge_state (&socket);
854 set_bridge_opts (&socket);
855
e2ffd59b 856 i = i365_get_status (&socket, &val);
66fd3d1c 857
e2ffd59b
WD
858#ifdef CONFIG_CPC45
859 if (i > -1) {
860 puts (pcic[socket.type].name);
861 } else {
862 printf ("i82365: Controller not found.\n");
863 return 1;
864 }
436be29c
WD
865 if((val & SS_DETECT) != SS_DETECT){
866 puts ("No card\n");
867 return 1;
868 }
e2ffd59b 869#else /* !CONFIG_CPC45 */
66fd3d1c
WD
870 if (val & SS_DETECT) {
871 if (val & SS_3VCARD) {
872 state.Vcc = state.Vpp = 33;
873 puts (" 3.3V card found: ");
874 } else if (!(val & SS_XVCARD)) {
875 state.Vcc = state.Vpp = 50;
876 puts (" 5.0V card found: ");
877 } else {
e2ffd59b 878 puts ("i82365: unsupported voltage key\n");
66fd3d1c
WD
879 state.Vcc = state.Vpp = 0;
880 }
881 } else {
882 /* No card inserted */
e2ffd59b 883 puts ("No card\n");
66fd3d1c
WD
884 return 1;
885 }
e2ffd59b 886#endif /* CONFIG_CPC45 */
66fd3d1c 887
e2ffd59b
WD
888#ifdef CONFIG_CPC45
889 state.flags |= SS_OUTPUT_ENA;
890#else
66fd3d1c
WD
891 state.flags = SS_IOCARD | SS_OUTPUT_ENA;
892 state.csc_mask = 0;
893 state.io_irq = 0;
e2ffd59b 894#endif
66fd3d1c
WD
895
896 i365_set_socket (&socket, &state);
897
898 for (i = 500; i; i--) {
899 if ((i365_get (&socket, I365_STATUS) & I365_CS_READY))
900 break;
901 udelay (1000);
902 }
903
904 if (i == 0) {
905 /* PC Card not ready for data transfer */
e2ffd59b 906 puts ("i82365 PC Card not ready for data transfer\n");
66fd3d1c
WD
907 return 1;
908 }
e2ffd59b 909 debug (" PC Card ready for data transfer: ");
66fd3d1c
WD
910
911 mem.map = 0;
912 mem.flags = MAP_ATTRIB | MAP_ACTIVE;
913 mem.speed = 300;
914 mem.sys_start = CFG_PCMCIA_MEM_ADDR;
915 mem.sys_stop = CFG_PCMCIA_MEM_ADDR + CFG_PCMCIA_MEM_SIZE - 1;
916 mem.card_start = 0;
e2ffd59b 917 i365_set_mem_map (&socket, &mem);
66fd3d1c 918
e2ffd59b
WD
919#ifdef CONFIG_CPC45
920 mem.map = 1;
921 mem.flags = MAP_ACTIVE;
922 mem.speed = 300;
923 mem.sys_start = CFG_PCMCIA_MEM_ADDR + CFG_PCMCIA_MEM_SIZE;
924 mem.sys_stop = CFG_PCMCIA_MEM_ADDR + (2 * CFG_PCMCIA_MEM_SIZE) - 1;
925 mem.card_start = 0;
66fd3d1c
WD
926 i365_set_mem_map (&socket, &mem);
927
e2ffd59b
WD
928#else /* !CONFIG_CPC45 */
929
66fd3d1c
WD
930 io.map = 0;
931 io.flags = MAP_AUTOSZ | MAP_ACTIVE;
932 io.speed = 0;
933 io.start = 0x0100;
934 io.stop = 0x010F;
66fd3d1c
WD
935 i365_set_io_map (&socket, &io);
936
e2ffd59b
WD
937#endif /* CONFIG_CPC45 */
938
66fd3d1c
WD
939#ifdef DEBUG
940 i82365_dump_regions (socket.dev);
941#endif
942
943 return 0;
944}
945
946void i82365_exit (void)
947{
948 io.map = 0;
949 io.flags = 0;
950 io.speed = 0;
951 io.start = 0;
952 io.stop = 0x1;
953
954 i365_set_io_map (&socket, &io);
955
956 mem.map = 0;
957 mem.flags = 0;
958 mem.speed = 0;
959 mem.sys_start = 0;
960 mem.sys_stop = 0x1000;
961 mem.card_start = 0;
962
963 i365_set_mem_map (&socket, &mem);
964
e2ffd59b
WD
965#ifdef CONFIG_CPC45
966 mem.map = 1;
967 mem.flags = 0;
968 mem.speed = 0;
969 mem.sys_start = 0;
970 mem.sys_stop = 0x1000;
971 mem.card_start = 0;
66fd3d1c 972
e2ffd59b
WD
973 i365_set_mem_map (&socket, &mem);
974#else /* !CONFIG_CPC45 */
975 socket.state.sysctl &= 0xFFFF00FF;
976#endif
66fd3d1c
WD
977 state.Vcc = state.Vpp = 0;
978
979 i365_set_socket (&socket, &state);
980}
981
982/*======================================================================
983
984 Debug stuff
8bde7f77 985
66fd3d1c
WD
986======================================================================*/
987
988#ifdef DEBUG
989static void i82365_dump_regions (pci_dev_t dev)
990{
991 u_int tmp[2];
e2ffd59b 992 u_int *mem = (void *) socket.cb_phys;
66fd3d1c
WD
993 u_char *cis = (void *) CFG_PCMCIA_MEM_ADDR;
994 u_char *ide = (void *) (CFG_ATA_BASE_ADDR + CFG_ATA_REG_OFFSET);
995
996 pci_read_config_dword (dev, 0x00, tmp + 0);
997 pci_read_config_dword (dev, 0x80, tmp + 1);
998
c3d2b4b4
WD
999 printf ("PCI CONF: %08X ... %08X\n",
1000 tmp[0], tmp[1]);
1001 printf ("PCI MEM: ... %08X ... %08X\n",
1002 mem[0x8 / 4], mem[0x800 / 4]);
66fd3d1c
WD
1003 printf ("CIS: ...%c%c%c%c%c%c%c%c...\n",
1004 cis[0x38], cis[0x3a], cis[0x3c], cis[0x3e],
1005 cis[0x40], cis[0x42], cis[0x44], cis[0x48]);
1006 printf ("CIS CONF: %02X %02X %02X ...\n",
1007 cis[0x200], cis[0x202], cis[0x204]);
1008 printf ("IDE: %02X %02X %02X %02X %02X %02X %02X %02X\n",
1009 ide[0], ide[1], ide[2], ide[3],
1010 ide[4], ide[5], ide[6], ide[7]);
1011}
1012#endif /* DEBUG */
1013
1014#endif /* CONFIG_I82365 */