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