]> git.ipfire.org Git - people/ms/u-boot.git/blame - drivers/i82365.c
* Add support for NSCU board
[people/ms/u-boot.git] / drivers / i82365.c
CommitLineData
66fd3d1c
WD
1/*
2 * (C) Copyright 2003
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>
43#include <pcmcia/ti113x.h>
44#include <pcmcia/yenta.h>
45
46/* #define DEBUG */
47
48static struct pci_device_id supported[] = {
49 {PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_1510},
50 {0, 0}
51};
52
53#define CYCLE_TIME 120
54
55#ifdef DEBUG
56static void i82365_dump_regions (pci_dev_t dev);
57#endif
58
59typedef struct socket_info_t {
60 pci_dev_t dev;
61 u_short bcr;
62 u_char pci_lat, cb_lat, sub_bus, cache;
63 u_int cb_phys;
64
65 socket_cap_t cap;
66 ti113x_state_t state;
67} socket_info_t;
68
69static socket_info_t socket;
70static socket_state_t state;
71static struct pccard_mem_map mem;
72static struct pccard_io_map io;
73
74/*====================================================================*/
75
76/* Some PCI shortcuts */
77
78static int pci_readb (socket_info_t * s, int r, u_char * v)
79{
80 return pci_read_config_byte (s->dev, r, v);
81}
82static int pci_writeb (socket_info_t * s, int r, u_char v)
83{
84 return pci_write_config_byte (s->dev, r, v);
85}
86static int pci_readw (socket_info_t * s, int r, u_short * v)
87{
88 return pci_read_config_word (s->dev, r, v);
89}
90static int pci_writew (socket_info_t * s, int r, u_short v)
91{
92 return pci_write_config_word (s->dev, r, v);
93}
94static int pci_readl (socket_info_t * s, int r, u_int * v)
95{
96 return pci_read_config_dword (s->dev, r, v);
97}
98static int pci_writel (socket_info_t * s, int r, u_int v)
99{
100 return pci_write_config_dword (s->dev, r, v);
101}
102
103#define cb_readb(s, r) readb((s)->cb_phys + (r))
104#define cb_readl(s, r) readl((s)->cb_phys + (r))
105#define cb_writeb(s, r, v) writeb(v, (s)->cb_phys + (r))
106#define cb_writel(s, r, v) writel(v, (s)->cb_phys + (r))
107
108/*====================================================================*/
109
110static u_char i365_get (socket_info_t * s, u_short reg)
111{
112 return cb_readb (s, 0x0800 + reg);
113}
114
115static void i365_set (socket_info_t * s, u_short reg, u_char data)
116{
117 cb_writeb (s, 0x0800 + reg, data);
118}
119
120static void i365_bset (socket_info_t * s, u_short reg, u_char mask)
121{
122 i365_set (s, reg, i365_get (s, reg) | mask);
123}
124
125static void i365_bclr (socket_info_t * s, u_short reg, u_char mask)
126{
127 i365_set (s, reg, i365_get (s, reg) & ~mask);
128}
129
130#if 0 /* not used */
131static void i365_bflip (socket_info_t * s, u_short reg, u_char mask, int b)
132{
133 u_char d = i365_get (s, reg);
134
135 i365_set (s, reg, (b) ? (d | mask) : (d & ~mask));
136}
137
138static u_short i365_get_pair (socket_info_t * s, u_short reg)
139{
140 return (i365_get (s, reg) + (i365_get (s, reg + 1) << 8));
141}
142#endif /* not used */
143
144static void i365_set_pair (socket_info_t * s, u_short reg, u_short data)
145{
146 i365_set (s, reg, data & 0xff);
147 i365_set (s, reg + 1, data >> 8);
148}
149
150/*======================================================================
151
152 Code to save and restore global state information for TI 1130 and
153 TI 1131 controllers, and to set and report global configuration
154 options.
8bde7f77 155
66fd3d1c
WD
156======================================================================*/
157
158static void ti113x_get_state (socket_info_t * s)
159{
160 ti113x_state_t *p = &s->state;
161
162 pci_readl (s, TI113X_SYSTEM_CONTROL, &p->sysctl);
163 pci_readb (s, TI113X_CARD_CONTROL, &p->cardctl);
164 pci_readb (s, TI113X_DEVICE_CONTROL, &p->devctl);
165 pci_readb (s, TI1250_DIAGNOSTIC, &p->diag);
166 pci_readl (s, TI12XX_IRQMUX, &p->irqmux);
167}
168
169static void ti113x_set_state (socket_info_t * s)
170{
171 ti113x_state_t *p = &s->state;
172
173 pci_writel (s, TI113X_SYSTEM_CONTROL, p->sysctl);
174 pci_writeb (s, TI113X_CARD_CONTROL, p->cardctl);
175 pci_writeb (s, TI113X_DEVICE_CONTROL, p->devctl);
176 pci_writeb (s, TI1250_MULTIMEDIA_CTL, 0);
177 pci_writeb (s, TI1250_DIAGNOSTIC, p->diag);
178 pci_writel (s, TI12XX_IRQMUX, p->irqmux);
179 i365_set_pair (s, TI113X_IO_OFFSET (0), 0);
180 i365_set_pair (s, TI113X_IO_OFFSET (1), 0);
181}
182
183static u_int ti113x_set_opts (socket_info_t * s)
184{
185 ti113x_state_t *p = &s->state;
186 u_int mask = 0xffff;
187
188 p->cardctl &= ~TI113X_CCR_ZVENABLE;
189 p->cardctl |= TI113X_CCR_SPKROUTEN;
190
191 return mask;
192}
193
194/*======================================================================
195
196 Routines to handle common CardBus options
8bde7f77 197
66fd3d1c
WD
198======================================================================*/
199
200/* Default settings for PCI command configuration register */
201#define CMD_DFLT (PCI_COMMAND_IO|PCI_COMMAND_MEMORY| \
202 PCI_COMMAND_MASTER|PCI_COMMAND_WAIT)
203
204static void cb_get_state (socket_info_t * s)
205{
206 pci_readb (s, PCI_CACHE_LINE_SIZE, &s->cache);
207 pci_readb (s, PCI_LATENCY_TIMER, &s->pci_lat);
208 pci_readb (s, CB_LATENCY_TIMER, &s->cb_lat);
209 pci_readb (s, CB_CARDBUS_BUS, &s->cap.cardbus);
210 pci_readb (s, CB_SUBORD_BUS, &s->sub_bus);
211 pci_readw (s, CB_BRIDGE_CONTROL, &s->bcr);
212}
213
214static void cb_set_state (socket_info_t * s)
215{
216 pci_writel (s, CB_LEGACY_MODE_BASE, 0);
217 pci_writel (s, PCI_BASE_ADDRESS_0, s->cb_phys);
218 pci_writew (s, PCI_COMMAND, CMD_DFLT);
219 pci_writeb (s, PCI_CACHE_LINE_SIZE, s->cache);
220 pci_writeb (s, PCI_LATENCY_TIMER, s->pci_lat);
221 pci_writeb (s, CB_LATENCY_TIMER, s->cb_lat);
222 pci_writeb (s, CB_CARDBUS_BUS, s->cap.cardbus);
223 pci_writeb (s, CB_SUBORD_BUS, s->sub_bus);
224 pci_writew (s, CB_BRIDGE_CONTROL, s->bcr);
225}
226
227static void cb_set_opts (socket_info_t * s)
228{
229 if (s->cache == 0)
230 s->cache = 8;
231 if (s->pci_lat == 0)
232 s->pci_lat = 0xa8;
233 if (s->cb_lat == 0)
234 s->cb_lat = 0xb0;
235}
236
237/*======================================================================
238
239 Power control for Cardbus controllers: used both for 16-bit and
240 Cardbus cards.
8bde7f77 241
66fd3d1c
WD
242======================================================================*/
243
244static int cb_set_power (socket_info_t * s, socket_state_t * state)
245{
246 u_int reg = 0;
247
248 /* restart card voltage detection if it seems appropriate */
249 if ((state->Vcc == 0) && (state->Vpp == 0) &&
250 !(cb_readl (s, CB_SOCKET_STATE) & CB_SS_VSENSE))
251 cb_writel (s, CB_SOCKET_FORCE, CB_SF_CVSTEST);
252 switch (state->Vcc) {
253 case 0:
254 reg = 0;
255 break;
256 case 33:
257 reg = CB_SC_VCC_3V;
258 break;
259 case 50:
260 reg = CB_SC_VCC_5V;
261 break;
262 default:
263 return -1;
264 }
265 switch (state->Vpp) {
266 case 0:
267 break;
268 case 33:
269 reg |= CB_SC_VPP_3V;
270 break;
271 case 50:
272 reg |= CB_SC_VPP_5V;
273 break;
274 case 120:
275 reg |= CB_SC_VPP_12V;
276 break;
277 default:
278 return -1;
279 }
280 if (reg != cb_readl (s, CB_SOCKET_CONTROL))
281 cb_writel (s, CB_SOCKET_CONTROL, reg);
282 return 0;
283}
284
285/*======================================================================
286
287 Generic routines to get and set controller options
8bde7f77 288
66fd3d1c
WD
289======================================================================*/
290
291static void get_bridge_state (socket_info_t * s)
292{
293 ti113x_get_state (s);
294 cb_get_state (s);
295}
296
297static void set_bridge_state (socket_info_t * s)
298{
299 cb_set_state (s);
300 i365_set (s, I365_GBLCTL, 0x00);
301 i365_set (s, I365_GENCTL, 0x00);
302 ti113x_set_state (s);
303}
304
305static void set_bridge_opts (socket_info_t * s)
306{
307 ti113x_set_opts (s);
308 cb_set_opts (s);
309}
310
311/*====================================================================*/
312
313static int i365_get_status (socket_info_t * s, u_int * value)
314{
315 u_int status;
316
317 status = i365_get (s, I365_STATUS);
318 *value = ((status & I365_CS_DETECT) == I365_CS_DETECT) ? SS_DETECT : 0;
319 if (i365_get (s, I365_INTCTL) & I365_PC_IOCARD) {
320 *value |= (status & I365_CS_STSCHG) ? 0 : SS_STSCHG;
321 } else {
322 *value |= (status & I365_CS_BVD1) ? 0 : SS_BATDEAD;
323 *value |= (status & I365_CS_BVD2) ? 0 : SS_BATWARN;
324 }
325 *value |= (status & I365_CS_WRPROT) ? SS_WRPROT : 0;
326 *value |= (status & I365_CS_READY) ? SS_READY : 0;
327 *value |= (status & I365_CS_POWERON) ? SS_POWERON : 0;
328
329 status = cb_readl (s, CB_SOCKET_STATE);
330 *value |= (status & CB_SS_32BIT) ? SS_CARDBUS : 0;
331 *value |= (status & CB_SS_3VCARD) ? SS_3VCARD : 0;
332 *value |= (status & CB_SS_XVCARD) ? SS_XVCARD : 0;
333 *value |= (status & CB_SS_VSENSE) ? 0 : SS_PENDING;
334 /* For now, ignore cards with unsupported voltage keys */
335 if (*value & SS_XVCARD)
336 *value &= ~(SS_DETECT | SS_3VCARD | SS_XVCARD);
337
338 return 0;
339} /* i365_get_status */
340
341static int i365_set_socket (socket_info_t * s, socket_state_t * state)
342{
343 u_char reg;
344
345 set_bridge_state (s);
346
347 /* IO card, RESET flag */
348 reg = 0;
349 reg |= (state->flags & SS_RESET) ? 0 : I365_PC_RESET;
350 reg |= (state->flags & SS_IOCARD) ? I365_PC_IOCARD : 0;
351 i365_set (s, I365_INTCTL, reg);
352
353 reg = I365_PWR_NORESET;
354 if (state->flags & SS_PWR_AUTO)
355 reg |= I365_PWR_AUTO;
356 if (state->flags & SS_OUTPUT_ENA)
357 reg |= I365_PWR_OUT;
358
359 cb_set_power (s, state);
360 reg |= i365_get (s, I365_POWER) & (I365_VCC_MASK | I365_VPP1_MASK);
361
362 if (reg != i365_get (s, I365_POWER))
363 i365_set (s, I365_POWER, reg);
364
365 return 0;
366} /* i365_set_socket */
367
368/*====================================================================*/
369
370static int i365_set_mem_map (socket_info_t * s, struct pccard_mem_map *mem)
371{
372 u_short base, i;
373 u_char map;
374
375 map = mem->map;
376 if ((map > 4) ||
377 (mem->card_start > 0x3ffffff) ||
378 (mem->sys_start > mem->sys_stop) ||
379 (mem->speed > 1000)) {
380 return -1;
381 }
382
383 /* Turn off the window before changing anything */
384 if (i365_get (s, I365_ADDRWIN) & I365_ENA_MEM (map))
385 i365_bclr (s, I365_ADDRWIN, I365_ENA_MEM (map));
386
387 /* Take care of high byte, for PCI controllers */
388 i365_set (s, CB_MEM_PAGE (map), mem->sys_start >> 24);
389
390 base = I365_MEM (map);
391 i = (mem->sys_start >> 12) & 0x0fff;
392 if (mem->flags & MAP_16BIT)
393 i |= I365_MEM_16BIT;
394 if (mem->flags & MAP_0WS)
395 i |= I365_MEM_0WS;
396 i365_set_pair (s, base + I365_W_START, i);
397
398 i = (mem->sys_stop >> 12) & 0x0fff;
399 switch (mem->speed / CYCLE_TIME) {
400 case 0:
401 break;
402 case 1:
403 i |= I365_MEM_WS0;
404 break;
405 case 2:
406 i |= I365_MEM_WS1;
407 break;
408 default:
409 i |= I365_MEM_WS1 | I365_MEM_WS0;
410 break;
411 }
412 i365_set_pair (s, base + I365_W_STOP, i);
413
414 i = ((mem->card_start - mem->sys_start) >> 12) & 0x3fff;
415 if (mem->flags & MAP_WRPROT)
416 i |= I365_MEM_WRPROT;
417 if (mem->flags & MAP_ATTRIB)
418 i |= I365_MEM_REG;
419 i365_set_pair (s, base + I365_W_OFF, i);
420
421 /* Turn on the window if necessary */
422 if (mem->flags & MAP_ACTIVE)
423 i365_bset (s, I365_ADDRWIN, I365_ENA_MEM (map));
424 return 0;
425} /* i365_set_mem_map */
426
427static int i365_set_io_map (socket_info_t * s, struct pccard_io_map *io)
428{
429 u_char map, ioctl;
430
431 map = io->map;
432 if ((map > 1) || (io->start > 0xffff) || (io->stop > 0xffff) ||
433 (io->stop < io->start))
434 return -1;
435 /* Turn off the window before changing anything */
436 if (i365_get (s, I365_ADDRWIN) & I365_ENA_IO (map))
437 i365_bclr (s, I365_ADDRWIN, I365_ENA_IO (map));
438 i365_set_pair (s, I365_IO (map) + I365_W_START, io->start);
439 i365_set_pair (s, I365_IO (map) + I365_W_STOP, io->stop);
440 ioctl = i365_get (s, I365_IOCTL) & ~I365_IOCTL_MASK (map);
441 if (io->speed)
442 ioctl |= I365_IOCTL_WAIT (map);
443 if (io->flags & MAP_0WS)
444 ioctl |= I365_IOCTL_0WS (map);
445 if (io->flags & MAP_16BIT)
446 ioctl |= I365_IOCTL_16BIT (map);
447 if (io->flags & MAP_AUTOSZ)
448 ioctl |= I365_IOCTL_IOCS16 (map);
449 i365_set (s, I365_IOCTL, ioctl);
450 /* Turn on the window if necessary */
451 if (io->flags & MAP_ACTIVE)
452 i365_bset (s, I365_ADDRWIN, I365_ENA_IO (map));
453 return 0;
454} /* i365_set_io_map */
455
456/*====================================================================*/
457
458int i82365_init (void)
459{
460 u_int val;
461 int i;
462
463 if ((socket.dev = pci_find_devices (supported, 0)) < 0) {
464 /* Controller not found */
465 return 1;
466 }
467
468 pci_read_config_dword (socket.dev, PCI_BASE_ADDRESS_0, &socket.cb_phys);
469 socket.cb_phys &= ~0xf;
470
471 get_bridge_state (&socket);
472 set_bridge_opts (&socket);
473
474 i365_get_status (&socket, &val);
475
476 if (val & SS_DETECT) {
477 if (val & SS_3VCARD) {
478 state.Vcc = state.Vpp = 33;
479 puts (" 3.3V card found: ");
480 } else if (!(val & SS_XVCARD)) {
481 state.Vcc = state.Vpp = 50;
482 puts (" 5.0V card found: ");
483 } else {
484 printf ("i82365: unsupported voltage key\n");
485 state.Vcc = state.Vpp = 0;
486 }
487 } else {
488 /* No card inserted */
489 return 1;
490 }
491
492 state.flags = SS_IOCARD | SS_OUTPUT_ENA;
493 state.csc_mask = 0;
494 state.io_irq = 0;
495
496 i365_set_socket (&socket, &state);
497
498 for (i = 500; i; i--) {
499 if ((i365_get (&socket, I365_STATUS) & I365_CS_READY))
500 break;
501 udelay (1000);
502 }
503
504 if (i == 0) {
505 /* PC Card not ready for data transfer */
506 return 1;
507 }
508
509 mem.map = 0;
510 mem.flags = MAP_ATTRIB | MAP_ACTIVE;
511 mem.speed = 300;
512 mem.sys_start = CFG_PCMCIA_MEM_ADDR;
513 mem.sys_stop = CFG_PCMCIA_MEM_ADDR + CFG_PCMCIA_MEM_SIZE - 1;
514 mem.card_start = 0;
515
516 i365_set_mem_map (&socket, &mem);
517
518 io.map = 0;
519 io.flags = MAP_AUTOSZ | MAP_ACTIVE;
520 io.speed = 0;
521 io.start = 0x0100;
522 io.stop = 0x010F;
523
524 i365_set_io_map (&socket, &io);
525
526#ifdef DEBUG
527 i82365_dump_regions (socket.dev);
528#endif
529
530 return 0;
531}
532
533void i82365_exit (void)
534{
535 io.map = 0;
536 io.flags = 0;
537 io.speed = 0;
538 io.start = 0;
539 io.stop = 0x1;
540
541 i365_set_io_map (&socket, &io);
542
543 mem.map = 0;
544 mem.flags = 0;
545 mem.speed = 0;
546 mem.sys_start = 0;
547 mem.sys_stop = 0x1000;
548 mem.card_start = 0;
549
550 i365_set_mem_map (&socket, &mem);
551
552 socket.state.sysctl &= 0xFFFF00FF;
553
554 state.Vcc = state.Vpp = 0;
555
556 i365_set_socket (&socket, &state);
557}
558
559/*======================================================================
560
561 Debug stuff
8bde7f77 562
66fd3d1c
WD
563======================================================================*/
564
565#ifdef DEBUG
566static void i82365_dump_regions (pci_dev_t dev)
567{
568 u_int tmp[2];
569 u_int *mem = (void *) sock.cb_phys;
570 u_char *cis = (void *) CFG_PCMCIA_MEM_ADDR;
571 u_char *ide = (void *) (CFG_ATA_BASE_ADDR + CFG_ATA_REG_OFFSET);
572
573 pci_read_config_dword (dev, 0x00, tmp + 0);
574 pci_read_config_dword (dev, 0x80, tmp + 1);
575
576 printf ("PCI CONF: %08X ... %08X\n", tmp[0], tmp[1]);
577 printf ("PCI MEM: ... %08X ... %08X\n", mem[0x8 / 4], mem[0x800 / 4]);
578 printf ("CIS: ...%c%c%c%c%c%c%c%c...\n",
579 cis[0x38], cis[0x3a], cis[0x3c], cis[0x3e],
580 cis[0x40], cis[0x42], cis[0x44], cis[0x48]);
581 printf ("CIS CONF: %02X %02X %02X ...\n",
582 cis[0x200], cis[0x202], cis[0x204]);
583 printf ("IDE: %02X %02X %02X %02X %02X %02X %02X %02X\n",
584 ide[0], ide[1], ide[2], ide[3],
585 ide[4], ide[5], ide[6], ide[7]);
586}
587#endif /* DEBUG */
588
589#endif /* CONFIG_I82365 */