source: SVN/rincon/u-boot/board/cpc45/pd67290.c @ 55

Last change on this file since 55 was 55, checked in by Tim Harvey, 22 months ago

rincon: added latest u-boot source

restored form server backup

Signed-off-by: Tim Harvey <tharvey@…>

File size: 20.1 KB
Line 
1/*
2 * (C) Copyright 2003-2005
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>
39#include <asm/io.h>
40
41#include <pcmcia/ss.h>
42#include <pcmcia/i82365.h>
43#include <pcmcia/yenta.h>
44#include <pcmcia/cirrus.h>
45
46static struct pci_device_id supported[] = {
47        {PCI_VENDOR_ID_CIRRUS, PCI_DEVICE_ID_CIRRUS_6729},
48        {0, 0}
49};
50
51#define CYCLE_TIME      120
52
53#ifdef DEBUG
54static void i82365_dump_regions (pci_dev_t dev);
55#endif
56
57typedef struct socket_info_t {
58        pci_dev_t       dev;
59        u_short         bcr;
60        u_char          pci_lat, cb_lat, sub_bus, cache;
61        u_int           cb_phys;
62
63        socket_cap_t    cap;
64        u_short         type;
65        u_int           flags;
66        cirrus_state_t  c_state;
67} socket_info_t;
68
69/* These definitions must match the pcic table! */
70typedef enum pcic_id {
71        IS_PD6710, IS_PD672X, IS_VT83C469
72} pcic_id;
73
74typedef struct pcic_t {
75        char *name;
76} pcic_t;
77
78static pcic_t pcic[] = {
79        {" Cirrus PD6710: "},
80        {" Cirrus PD672x: "},
81        {" VIA VT83C469: "},
82};
83
84static socket_info_t socket;
85static socket_state_t state;
86static struct pccard_mem_map mem;
87static struct pccard_io_map io;
88
89/*====================================================================*/
90
91/* Some PCI shortcuts */
92
93static int pci_readb (socket_info_t * s, int r, u_char * v)
94{
95        return pci_read_config_byte (s->dev, r, v);
96}
97static int pci_writeb (socket_info_t * s, int r, u_char v)
98{
99        return pci_write_config_byte (s->dev, r, v);
100}
101static int pci_readw (socket_info_t * s, int r, u_short * v)
102{
103        return pci_read_config_word (s->dev, r, v);
104}
105static int pci_writew (socket_info_t * s, int r, u_short v)
106{
107        return pci_write_config_word (s->dev, r, v);
108}
109
110/*====================================================================*/
111
112#define cb_readb(s)             readb((s)->cb_phys + 1)
113#define cb_writeb(s, v)         writeb(v, (s)->cb_phys)
114#define cb_writeb2(s, v)        writeb(v, (s)->cb_phys + 1)
115#define cb_readl(s, r)          readl((s)->cb_phys + (r))
116#define cb_writel(s, r, v)      writel(v, (s)->cb_phys + (r))
117
118
119static u_char i365_get (socket_info_t * s, u_short reg)
120{
121        u_char val;
122#ifdef CONFIG_PCMCIA_SLOT_A
123        int slot = 0;
124#else
125        int slot = 1;
126#endif
127
128        val = I365_REG (slot, reg);
129
130        cb_writeb (s, val);
131        val = cb_readb (s);
132
133        debug ("i365_get slot:%x reg: %x val: %x\n", slot, reg, val);
134        return val;
135}
136
137static void i365_set (socket_info_t * s, u_short reg, u_char data)
138{
139#ifdef CONFIG_PCMCIA_SLOT_A
140        int slot = 0;
141#else
142        int slot = 1;
143#endif
144        u_char val;
145
146        val = I365_REG (slot, reg);
147
148        cb_writeb (s, val);
149        cb_writeb2 (s, data);
150
151        debug ("i365_set slot:%x reg: %x data:%x\n", slot, reg, data);
152}
153
154static void i365_bset (socket_info_t * s, u_short reg, u_char mask)
155{
156        i365_set (s, reg, i365_get (s, reg) | mask);
157}
158
159static void i365_bclr (socket_info_t * s, u_short reg, u_char mask)
160{
161        i365_set (s, reg, i365_get (s, reg) & ~mask);
162}
163
164#if 0   /* not used */
165static void i365_bflip (socket_info_t * s, u_short reg, u_char mask, int b)
166{
167        u_char d = i365_get (s, reg);
168
169        i365_set (s, reg, (b) ? (d | mask) : (d & ~mask));
170}
171
172static u_short i365_get_pair (socket_info_t * s, u_short reg)
173{
174        return (i365_get (s, reg) + (i365_get (s, reg + 1) << 8));
175}
176#endif  /* not used */
177
178static void i365_set_pair (socket_info_t * s, u_short reg, u_short data)
179{
180        i365_set (s, reg, data & 0xff);
181        i365_set (s, reg + 1, data >> 8);
182}
183
184/*======================================================================
185
186    Code to save and restore global state information for Cirrus
187    PD67xx controllers, and to set and report global configuration
188    options.
189
190======================================================================*/
191
192#define flip(v,b,f) (v = ((f)<0) ? v : ((f) ? ((v)|(b)) : ((v)&(~b))))
193
194static void cirrus_get_state (socket_info_t * s)
195{
196        int i;
197        cirrus_state_t *p = &s->c_state;
198
199        p->misc1 = i365_get (s, PD67_MISC_CTL_1);
200        p->misc1 &= (PD67_MC1_MEDIA_ENA | PD67_MC1_INPACK_ENA);
201        p->misc2 = i365_get (s, PD67_MISC_CTL_2);
202        for (i = 0; i < 6; i++)
203                p->timer[i] = i365_get (s, PD67_TIME_SETUP (0) + i);
204
205}
206
207static void cirrus_set_state (socket_info_t * s)
208{
209        int i;
210        u_char misc;
211        cirrus_state_t *p = &s->c_state;
212
213        misc = i365_get (s, PD67_MISC_CTL_2);
214        i365_set (s, PD67_MISC_CTL_2, p->misc2);
215        if (misc & PD67_MC2_SUSPEND)
216                udelay (50000);
217        misc = i365_get (s, PD67_MISC_CTL_1);
218        misc &= ~(PD67_MC1_MEDIA_ENA | PD67_MC1_INPACK_ENA);
219        i365_set (s, PD67_MISC_CTL_1, misc | p->misc1);
220        for (i = 0; i < 6; i++)
221                i365_set (s, PD67_TIME_SETUP (0) + i, p->timer[i]);
222}
223
224static u_int cirrus_set_opts (socket_info_t * s)
225{
226        cirrus_state_t *p = &s->c_state;
227        u_int mask = 0xffff;
228#if DEBUG
229        char buf[200];
230
231        memset (buf, 0, 200);
232#endif
233
234        if (has_ring == -1)
235                has_ring = 1;
236        flip (p->misc2, PD67_MC2_IRQ15_RI, has_ring);
237        flip (p->misc2, PD67_MC2_DYNAMIC_MODE, dynamic_mode);
238#if DEBUG
239        if (p->misc2 & PD67_MC2_IRQ15_RI)
240                strcat (buf, " [ring]");
241        if (p->misc2 & PD67_MC2_DYNAMIC_MODE)
242                strcat (buf, " [dyn mode]");
243        if (p->misc1 & PD67_MC1_INPACK_ENA)
244                strcat (buf, " [inpack]");
245#endif
246
247        if (p->misc2 & PD67_MC2_IRQ15_RI)
248                mask &= ~0x8000;
249        if (has_led > 0) {
250#if DEBUG
251                strcat (buf, " [led]");
252#endif
253                mask &= ~0x1000;
254        }
255        if (has_dma > 0) {
256#if DEBUG
257                strcat (buf, " [dma]");
258#endif
259                mask &= ~0x0600;
260                flip (p->misc2, PD67_MC2_FREQ_BYPASS, freq_bypass);
261#if DEBUG
262                if (p->misc2 & PD67_MC2_FREQ_BYPASS)
263                        strcat (buf, " [freq bypass]");
264#endif
265        }
266
267        if (setup_time >= 0)
268                p->timer[0] = p->timer[3] = setup_time;
269        if (cmd_time > 0) {
270                p->timer[1] = cmd_time;
271                p->timer[4] = cmd_time * 2 + 4;
272        }
273        if (p->timer[1] == 0) {
274                p->timer[1] = 6;
275                p->timer[4] = 16;
276                if (p->timer[0] == 0)
277                        p->timer[0] = p->timer[3] = 1;
278        }
279        if (recov_time >= 0)
280                p->timer[2] = p->timer[5] = recov_time;
281
282        debug ("i82365 Opt: %s [%d/%d/%d] [%d/%d/%d]\n",
283                buf,
284                p->timer[0], p->timer[1], p->timer[2],
285                p->timer[3], p->timer[4], p->timer[5]);
286
287        return mask;
288}
289
290/*======================================================================
291
292    Routines to handle common CardBus options
293
294======================================================================*/
295
296/* Default settings for PCI command configuration register */
297#define CMD_DFLT (PCI_COMMAND_IO|PCI_COMMAND_MEMORY| \
298                  PCI_COMMAND_MASTER|PCI_COMMAND_WAIT)
299
300static void cb_get_state (socket_info_t * s)
301{
302        pci_readb (s, PCI_CACHE_LINE_SIZE, &s->cache);
303        pci_readb (s, PCI_LATENCY_TIMER, &s->pci_lat);
304        pci_readb (s, CB_LATENCY_TIMER, &s->cb_lat);
305        pci_readb (s, CB_CARDBUS_BUS, &s->cap.cardbus);
306        pci_readb (s, CB_SUBORD_BUS, &s->sub_bus);
307        pci_readw (s, CB_BRIDGE_CONTROL, &s->bcr);
308}
309
310static void cb_set_state (socket_info_t * s)
311{
312        pci_writew (s, PCI_COMMAND, CMD_DFLT);
313        pci_writeb (s, PCI_CACHE_LINE_SIZE, s->cache);
314        pci_writeb (s, PCI_LATENCY_TIMER, s->pci_lat);
315        pci_writeb (s, CB_LATENCY_TIMER, s->cb_lat);
316        pci_writeb (s, CB_CARDBUS_BUS, s->cap.cardbus);
317        pci_writeb (s, CB_SUBORD_BUS, s->sub_bus);
318        pci_writew (s, CB_BRIDGE_CONTROL, s->bcr);
319}
320
321static void cb_set_opts (socket_info_t * s)
322{
323}
324
325/*======================================================================
326
327    Power control for Cardbus controllers: used both for 16-bit and
328    Cardbus cards.
329
330======================================================================*/
331
332static int cb_set_power (socket_info_t * s, socket_state_t * state)
333{
334        u_int reg = 0;
335
336        reg = I365_PWR_NORESET;
337        if (state->flags & SS_PWR_AUTO)
338                reg |= I365_PWR_AUTO;
339        if (state->flags & SS_OUTPUT_ENA)
340                reg |= I365_PWR_OUT;
341        if (state->Vpp != 0) {
342                if (state->Vpp == 120) {
343                        reg |= I365_VPP1_12V;
344                        puts (" 12V card found: ");
345                } else if (state->Vpp == state->Vcc) {
346                        reg |= I365_VPP1_5V;
347                } else {
348                        puts (" power not found: ");
349                        return -1;
350                }
351        }
352        if (state->Vcc != 0) {
353                reg |= I365_VCC_5V;
354                if (state->Vcc == 33) {
355                        puts (" 3.3V card found: ");
356                        i365_bset (s, PD67_MISC_CTL_1, PD67_MC1_VCC_3V);
357                } else if (state->Vcc == 50) {
358                        puts (" 5V card found: ");
359                        i365_bclr (s, PD67_MISC_CTL_1, PD67_MC1_VCC_3V);
360                } else {
361                        puts (" power not found: ");
362                        return -1;
363                }
364        }
365
366        if (reg != i365_get (s, I365_POWER)) {
367                reg = (I365_PWR_OUT | I365_PWR_NORESET | I365_VCC_5V | I365_VPP1_5V);
368                i365_set (s, I365_POWER, reg);
369        }
370
371        return 0;
372}
373
374/*======================================================================
375
376    Generic routines to get and set controller options
377
378======================================================================*/
379
380static void get_bridge_state (socket_info_t * s)
381{
382        cirrus_get_state (s);
383        cb_get_state (s);
384}
385
386static void set_bridge_state (socket_info_t * s)
387{
388        cb_set_state (s);
389        i365_set (s, I365_GBLCTL, 0x00);
390        i365_set (s, I365_GENCTL, 0x00);
391        cirrus_set_state (s);
392}
393
394static void set_bridge_opts (socket_info_t * s)
395{
396        cirrus_set_opts (s);
397        cb_set_opts (s);
398}
399
400/*====================================================================*/
401#define PD67_EXT_INDEX          0x2e    /* Extension index */
402#define PD67_EXT_DATA           0x2f    /* Extension data */
403#define PD67_EXD_VS1(s)         (0x01 << ((s)<<1))
404
405#define pd67_ext_get(s, r) \
406    (i365_set(s, PD67_EXT_INDEX, r), i365_get(s, PD67_EXT_DATA))
407
408static int i365_get_status (socket_info_t * s, u_int * value)
409{
410        u_int status;
411        u_char val;
412        u_char power, vcc, vpp;
413        u_int powerstate;
414
415        status = i365_get (s, I365_IDENT);
416        status = i365_get (s, I365_STATUS);
417        *value = ((status & I365_CS_DETECT) == I365_CS_DETECT) ? SS_DETECT : 0;
418        if (i365_get (s, I365_INTCTL) & I365_PC_IOCARD) {
419                *value |= (status & I365_CS_STSCHG) ? 0 : SS_STSCHG;
420        } else {
421                *value |= (status & I365_CS_BVD1) ? 0 : SS_BATDEAD;
422                *value |= (status & I365_CS_BVD2) ? 0 : SS_BATWARN;
423        }
424        *value |= (status & I365_CS_WRPROT) ? SS_WRPROT : 0;
425        *value |= (status & I365_CS_READY) ? SS_READY : 0;
426        *value |= (status & I365_CS_POWERON) ? SS_POWERON : 0;
427
428        /* Check for Cirrus CL-PD67xx chips */
429        i365_set (s, PD67_CHIP_INFO, 0);
430        val = i365_get (s, PD67_CHIP_INFO);
431        s->type = -1;
432        if ((val & PD67_INFO_CHIP_ID) == PD67_INFO_CHIP_ID) {
433                val = i365_get (s, PD67_CHIP_INFO);
434                if ((val & PD67_INFO_CHIP_ID) == 0) {
435                        s->type = (val & PD67_INFO_SLOTS) ? IS_PD672X : IS_PD6710;
436                        i365_set (s, PD67_EXT_INDEX, 0xe5);
437                        if (i365_get (s, PD67_EXT_INDEX) != 0xe5)
438                                s->type = IS_VT83C469;
439                }
440        } else {
441                printf ("no Cirrus Chip found\n");
442                *value = 0;
443                return -1;
444        }
445
446        power = i365_get (s, I365_POWER);
447        state.flags |= (power & I365_PWR_AUTO) ? SS_PWR_AUTO : 0;
448        state.flags |= (power & I365_PWR_OUT) ? SS_OUTPUT_ENA : 0;
449        vcc = power & I365_VCC_MASK;
450        vpp = power & I365_VPP1_MASK;
451        state.Vcc = state.Vpp = 0;
452        if((vcc== 0) || (vpp == 0)) {
453                /*
454                 * On the Cirrus we get the info which card voltage
455                 * we have in EXTERN DATA and write it to MISC_CTL1
456                 */
457                powerstate = pd67_ext_get(s, PD67_EXTERN_DATA);
458                if (powerstate & PD67_EXD_VS1(0)) {
459                        /* 5V Card */
460                        i365_bclr (s, PD67_MISC_CTL_1, PD67_MC1_VCC_3V);
461                } else {
462                        /* 3.3V Card */
463                        i365_bset (s, PD67_MISC_CTL_1, PD67_MC1_VCC_3V);
464                }
465                i365_set (s, I365_POWER, (I365_PWR_OUT | I365_PWR_NORESET | I365_VCC_5V | I365_VPP1_5V));
466                power = i365_get (s, I365_POWER);
467        }
468        if (power & I365_VCC_5V) {
469                state.Vcc = (i365_get(s, PD67_MISC_CTL_1) & PD67_MC1_VCC_3V) ? 33 : 50;
470        }
471
472        if (power == I365_VPP1_12V)
473                state.Vpp = 120;
474
475        /* IO card, RESET flags, IO interrupt */
476        power = i365_get (s, I365_INTCTL);
477        state.flags |= (power & I365_PC_RESET) ? 0 : SS_RESET;
478        if (power & I365_PC_IOCARD)
479                state.flags |= SS_IOCARD;
480        state.io_irq = power & I365_IRQ_MASK;
481
482        /* Card status change mask */
483        power = i365_get (s, I365_CSCINT);
484        state.csc_mask = (power & I365_CSC_DETECT) ? SS_DETECT : 0;
485        if (state.flags & SS_IOCARD)
486                state.csc_mask |= (power & I365_CSC_STSCHG) ? SS_STSCHG : 0;
487        else {
488                state.csc_mask |= (power & I365_CSC_BVD1) ? SS_BATDEAD : 0;
489                state.csc_mask |= (power & I365_CSC_BVD2) ? SS_BATWARN : 0;
490                state.csc_mask |= (power & I365_CSC_READY) ? SS_READY : 0;
491        }
492        debug ("i82365: GetStatus(0) = flags %#3.3x, Vcc %d, Vpp %d, "
493                "io_irq %d, csc_mask %#2.2x\n", state.flags,
494                state.Vcc, state.Vpp, state.io_irq, state.csc_mask);
495
496        return 0;
497}       /* i365_get_status */
498
499static int i365_set_socket (socket_info_t * s, socket_state_t * state)
500{
501        u_char reg;
502
503        set_bridge_state (s);
504
505        /* IO card, RESET flag */
506        reg = 0;
507        reg |= (state->flags & SS_RESET) ? 0 : I365_PC_RESET;
508        reg |= (state->flags & SS_IOCARD) ? I365_PC_IOCARD : 0;
509        i365_set (s, I365_INTCTL, reg);
510
511        cb_set_power (s, state);
512
513#if 0
514        /* Card status change interrupt mask */
515        reg = s->cs_irq << 4;
516        if (state->csc_mask & SS_DETECT)
517                reg |= I365_CSC_DETECT;
518        if (state->flags & SS_IOCARD) {
519                if (state->csc_mask & SS_STSCHG)
520                        reg |= I365_CSC_STSCHG;
521        } else {
522                if (state->csc_mask & SS_BATDEAD)
523                        reg |= I365_CSC_BVD1;
524                if (state->csc_mask & SS_BATWARN)
525                        reg |= I365_CSC_BVD2;
526                if (state->csc_mask & SS_READY)
527                        reg |= I365_CSC_READY;
528        }
529        i365_set (s, I365_CSCINT, reg);
530        i365_get (s, I365_CSC);
531#endif  /* 0 */
532
533        return 0;
534}       /* i365_set_socket */
535
536/*====================================================================*/
537
538static int i365_set_mem_map (socket_info_t * s, struct pccard_mem_map *mem)
539{
540        u_short base, i;
541        u_char map;
542
543        debug ("i82365: SetMemMap(%d, %#2.2x, %d ns, %#5.5lx-%#5.5lx, %#5.5x)\n",
544                mem->map, mem->flags, mem->speed,
545                mem->sys_start, mem->sys_stop, mem->card_start);
546
547        map = mem->map;
548        if ((map > 4) ||
549            (mem->card_start > 0x3ffffff) ||
550            (mem->sys_start > mem->sys_stop) ||
551            (mem->speed > 1000)) {
552                return -1;
553        }
554
555        /* Turn off the window before changing anything */
556        if (i365_get (s, I365_ADDRWIN) & I365_ENA_MEM (map))
557                i365_bclr (s, I365_ADDRWIN, I365_ENA_MEM (map));
558
559        /* Take care of high byte, for PCI controllers */
560        i365_set (s, CB_MEM_PAGE (map), mem->sys_start >> 24);
561
562        base = I365_MEM (map);
563        i = (mem->sys_start >> 12) & 0x0fff;
564        if (mem->flags & MAP_16BIT)
565                i |= I365_MEM_16BIT;
566        if (mem->flags & MAP_0WS)
567                i |= I365_MEM_0WS;
568        i365_set_pair (s, base + I365_W_START, i);
569
570        i = (mem->sys_stop >> 12) & 0x0fff;
571        switch (mem->speed / CYCLE_TIME) {
572        case 0:
573                break;
574        case 1:
575                i |= I365_MEM_WS0;
576                break;
577        case 2:
578                i |= I365_MEM_WS1;
579                break;
580        default:
581                i |= I365_MEM_WS1 | I365_MEM_WS0;
582                break;
583        }
584        i365_set_pair (s, base + I365_W_STOP, i);
585
586        i = 0;
587        if (mem->flags & MAP_WRPROT)
588                i |= I365_MEM_WRPROT;
589        if (mem->flags & MAP_ATTRIB)
590                i |= I365_MEM_REG;
591        i365_set_pair (s, base + I365_W_OFF, i);
592
593        /* set System Memory map Upper Adress */
594        i365_set(s, PD67_EXT_INDEX, PD67_MEM_PAGE(map));
595        i365_set(s, PD67_EXT_DATA, ((mem->sys_start >> 24) & 0xff));
596
597        /* Turn on the window if necessary */
598        if (mem->flags & MAP_ACTIVE)
599                i365_bset (s, I365_ADDRWIN, I365_ENA_MEM (map));
600        return 0;
601}       /* i365_set_mem_map */
602
603static int i365_set_io_map (socket_info_t * s, struct pccard_io_map *io)
604{
605        u_char map, ioctl;
606
607        map = io->map;
608        /* comment out: comparison is always false due to limited range of data type */
609        if ((map > 1) || /* (io->start > 0xffff) || (io->stop > 0xffff) || */
610            (io->stop < io->start))
611                return -1;
612        /* Turn off the window before changing anything */
613        if (i365_get (s, I365_ADDRWIN) & I365_ENA_IO (map))
614                i365_bclr (s, I365_ADDRWIN, I365_ENA_IO (map));
615        i365_set_pair (s, I365_IO (map) + I365_W_START, io->start);
616        i365_set_pair (s, I365_IO (map) + I365_W_STOP, io->stop);
617        ioctl = i365_get (s, I365_IOCTL) & ~I365_IOCTL_MASK (map);
618        if (io->speed)
619                ioctl |= I365_IOCTL_WAIT (map);
620        if (io->flags & MAP_0WS)
621                ioctl |= I365_IOCTL_0WS (map);
622        if (io->flags & MAP_16BIT)
623                ioctl |= I365_IOCTL_16BIT (map);
624        if (io->flags & MAP_AUTOSZ)
625                ioctl |= I365_IOCTL_IOCS16 (map);
626        i365_set (s, I365_IOCTL, ioctl);
627        /* Turn on the window if necessary */
628        if (io->flags & MAP_ACTIVE)
629                i365_bset (s, I365_ADDRWIN, I365_ENA_IO (map));
630        return 0;
631}       /* i365_set_io_map */
632
633/*====================================================================*/
634
635/*
636 * PCI_ADDR = (HOST_ADDR - 0xfe000000)
637 * see MPC 8245 Users Manual Adress Map B
638 */
639#define HOST_TO_PCI(addr)       ((addr) - 0xfe000000)
640#define PCI_TO_HOST(addr)       ((addr) + 0xfe000000)
641
642int i82365_init (void)
643{
644        u_int val;
645        int i;
646
647        if ((socket.dev = pci_find_devices (supported, 0)) < 0) {
648                /* Controller not found */
649                printf ("No PD67290 device found !!\n");
650                return 1;
651        }
652        debug ("i82365 Device Found!\n");
653
654        socket.cb_phys = PCMCIA_IO_BASE;
655
656        /* set base address */
657        pci_write_config_dword (socket.dev, PCI_BASE_ADDRESS_0,
658                HOST_TO_PCI(socket.cb_phys));
659
660        /* enable mapped memory and IO addresses */
661        pci_write_config_dword (socket.dev,
662                                PCI_COMMAND,
663                                PCI_COMMAND_MEMORY |
664                                PCI_COMMAND_IO | PCI_COMMAND_WAIT);
665
666        get_bridge_state (&socket);
667        set_bridge_opts (&socket);
668
669        i = i365_get_status (&socket, &val);
670
671        if (i > -1) {
672                puts (pcic[socket.type].name);
673        } else {
674                printf ("i82365: Controller not found.\n");
675                return 1;
676        }
677        if((val & SS_DETECT) != SS_DETECT){
678                puts ("No card\n");
679                return 1;
680        }
681
682        state.flags |= SS_OUTPUT_ENA;
683
684        i365_set_socket (&socket, &state);
685
686        for (i = 500; i; i--) {
687                if ((i365_get (&socket, I365_STATUS) & I365_CS_READY))
688                        break;
689                udelay (1000);
690        }
691
692        if (i == 0) {
693                /* PC Card not ready for data transfer */
694                puts ("i82365 PC Card not ready for data transfer\n");
695                return 1;
696        }
697        debug (" PC Card ready for data transfer: ");
698
699        mem.map = 0;
700        mem.flags = MAP_ATTRIB | MAP_ACTIVE;
701        mem.speed = 300;
702        mem.sys_start = CFG_PCMCIA_MEM_ADDR;
703        mem.sys_stop = CFG_PCMCIA_MEM_ADDR + CFG_PCMCIA_MEM_SIZE - 1;
704        mem.card_start = 0;
705        i365_set_mem_map (&socket, &mem);
706
707        mem.map = 1;
708        mem.flags = MAP_ACTIVE;
709        mem.speed = 300;
710        mem.sys_start = CFG_PCMCIA_MEM_ADDR + CFG_PCMCIA_MEM_SIZE;
711        mem.sys_stop = CFG_PCMCIA_MEM_ADDR + (2 * CFG_PCMCIA_MEM_SIZE) - 1;
712        mem.card_start = 0;
713        i365_set_mem_map (&socket, &mem);
714
715#ifdef DEBUG
716        i82365_dump_regions (socket.dev);
717#endif
718
719        return 0;
720}
721
722void i82365_exit (void)
723{
724        io.map = 0;
725        io.flags = 0;
726        io.speed = 0;
727        io.start = 0;
728        io.stop = 0x1;
729
730        i365_set_io_map (&socket, &io);
731
732        mem.map = 0;
733        mem.flags = 0;
734        mem.speed = 0;
735        mem.sys_start = 0;
736        mem.sys_stop = 0x1000;
737        mem.card_start = 0;
738
739        i365_set_mem_map (&socket, &mem);
740
741        mem.map = 1;
742        mem.flags = 0;
743        mem.speed = 0;
744        mem.sys_start = 0;
745        mem.sys_stop = 0x1000;
746        mem.card_start = 0;
747
748        i365_set_mem_map (&socket, &mem);
749
750        state.Vcc = state.Vpp = 0;
751
752        i365_set_socket (&socket, &state);
753}
754
755int pcmcia_on (void)
756{
757        u_int rc;
758
759        debug ("Enable PCMCIA " PCMCIA_SLOT_MSG "\n");
760
761        rc = i82365_init();
762        if (rc)
763                goto exit;
764
765        rc = check_ide_device(0);
766        if (rc == 0)
767                goto exit;
768
769        i82365_exit();
770
771exit:
772        return rc;
773}
774
775#if defined(CONFIG_CMD_PCMCIA)
776int pcmcia_off (void)
777{
778        printf ("Disable PCMCIA " PCMCIA_SLOT_MSG "\n");
779
780        i82365_exit();
781
782        return 0;
783}
784#endif
785
786/*======================================================================
787
788    Debug stuff
789
790======================================================================*/
791
792#ifdef DEBUG
793static void i82365_dump_regions (pci_dev_t dev)
794{
795        u_int tmp[2];
796        u_int *mem = (void *) socket.cb_phys;
797        u_char *cis = (void *) CFG_PCMCIA_MEM_ADDR;
798        u_char *ide = (void *) (CFG_ATA_BASE_ADDR + CFG_ATA_REG_OFFSET);
799
800        pci_read_config_dword (dev, 0x00, tmp + 0);
801        pci_read_config_dword (dev, 0x80, tmp + 1);
802
803        printf ("PCI CONF: %08X ... %08X\n",
804                tmp[0], tmp[1]);
805        printf ("PCI MEM:  ... %08X ... %08X\n",
806                mem[0x8 / 4], mem[0x800 / 4]);
807        printf ("CIS:      ...%c%c%c%c%c%c%c%c...\n",
808                cis[0x38], cis[0x3a], cis[0x3c], cis[0x3e],
809                cis[0x40], cis[0x42], cis[0x44], cis[0x48]);
810        printf ("CIS CONF: %02X %02X %02X ...\n",
811                cis[0x200], cis[0x202], cis[0x204]);
812        printf ("IDE:      %02X %02X %02X %02X %02X %02X %02X %02X\n",
813                ide[0], ide[1], ide[2], ide[3],
814                ide[4], ide[5], ide[6], ide[7]);
815}
816#endif  /* DEBUG */
817
818#endif /* CONFIG_I82365 */
Note: See TracBrowser for help on using the repository browser.