OpenCores
URL https://opencores.org/ocsvn/or1k/or1k/trunk

Subversion Repositories or1k

[/] [or1k/] [trunk/] [linux/] [linux-2.4/] [drivers/] [pcmcia/] [sibyte_generic.c] - Blame information for rev 1774

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 1275 phoenix
/*
2
 * Copyright (C) 2003 Broadcom Corporation
3
 *    originally contributed to SiByte, Inc as
4
 *    "sb1250pc.c 0.10 (Stanley Chen & James Liao)"
5
 *
6
 * This program is free software; you can redistribute it and/or
7
 * modify it under the terms of the GNU General Public License
8
 * as published by the Free Software Foundation; either version 2
9
 * of the License, or (at your option) any later version.
10
 *
11
 * This program is distributed in the hope that it will be useful,
12
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14
 * GNU General Public License for more details.
15
 *
16
 * You should have received a copy of the GNU General Public License
17
 * along with this program; if not, write to the Free Software
18
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
19
 */
20
 
21
/*
22
 * Notes / Apologies:
23
 *   - only ATA cards tested so far
24
 *   - requires hack in cs.c to avoid poking the CISCOR register
25
 *   - ack_intr routine might be improved to avoid error msgs.
26
 *   - remove and re-insert doesn't work (crash or fail to probe drive)
27
 */
28
 
29
#include <linux/config.h>
30
#include <linux/init.h>
31
#include <linux/kernel.h>
32
#include <linux/module.h>
33
#include <linux/ioport.h>
34
#include <linux/sched.h>
35
#include <linux/proc_fs.h>
36
#include <linux/timer.h>
37
#include <linux/ide.h>
38
 
39
#include <pcmcia/version.h>
40
#include <pcmcia/cs_types.h>
41
#include <pcmcia/ss.h>
42
#include <pcmcia/bulkmem.h>
43
#include <pcmcia/cistpl.h>
44
#include <pcmcia/cs.h>
45
#include "cs_internal.h"
46
 
47
#include <asm/io.h>
48
 
49
#include <asm/sibyte/board.h>
50
#include <asm/sibyte/sb1250_regs.h>
51
#include <asm/sibyte/sb1250_scd.h>
52
#include <asm/sibyte/sb1250_int.h>
53
#include <asm/sibyte/sb1250_genbus.h>
54
#include <asm/sibyte/64bit.h>
55
 
56
#define PFX "sibyte-pcmcia: "
57
 
58
MODULE_AUTHOR("Kip Walker, Stanley Chen & James Liao");
59
MODULE_DESCRIPTION("SiByte PCMCIA socket driver");
60
 
61
#undef PCMCIA_DEBUG
62
#ifdef PCMCIA_DEBUG
63
#define DPRINTK(args...) do { printk(KERN_DEBUG args); } while (0)
64
#else
65
#define DPRINTK(n, args...) do { } while (0)
66
#endif
67
 
68
static unsigned long sb_pcmcia_base = PCMCIA_PHYS;
69
static unsigned long sb_pcmcia_size;
70
#define SIBYTE_CS_REG(pcaddr)  (IO_SPACE_BASE + sb_pcmcia_base - mips_io_port_base + pcaddr)
71
#define SB_PC_PORT 0xff00
72
extern void sibyte_set_ideops(ide_hwif_t *hwif);
73
 
74
/* The card status change interrupt */
75
static int cs_irq = K_INT_PCMCIA;
76
 
77
/* Memory map windows */
78
static struct pccard_mem_map sibyte_memmap[MAX_WIN];
79
static struct pccard_io_map  sibyte_iomap[MAX_IO_WIN];
80
 
81
/*====================================================================*/
82
/* Socket structures                                                  */
83
/*====================================================================*/
84
 
85
 
86
static void sb1250pc_interrupt(int irq, void *dev, struct pt_regs *regs);
87
static struct pccard_operations sb1250pc_operations;
88
 
89
typedef struct socket_handler_t {
90
        void    (*handler)(void *info, u_int events);
91
        void    *info;
92
} socket_handler_t;
93
 
94
static socket_handler_t socket_handler;
95
 
96
/*
97
 * cap features:
98
 *   full 32-bit addressing for 16-bit PCcard memory windows
99
 *   16-bit card memory and IO accesses need bus_ops
100
 *   only 16-bit PCcards
101
 *   align memory windows
102
 *   statically mapped memory windows
103
 */
104
static socket_cap_t sb1250pc_cap = {
105
        features: (SS_CAP_PAGE_REGS |
106
//                 SS_CAP_VIRTUAL_BUS |
107
                   SS_CAP_PCCARD |
108
                   SS_CAP_MEM_ALIGN | SS_CAP_STATIC_MAP),
109
        irq_mask:  0,            /* tell ide layer to take PCI irq */
110
        map_size:  0x4000000,   /* 64MB minimum window size (What *should* this be?)*/
111
        io_offset: SB_PC_PORT,  /* This is ide5 -- just a special token for ide-sibyte */
112
        pci_irq:   K_INT_PC_READY, /* XXXKW This serves as IREQ# for CompactFlash */
113
        cb_dev:    NULL,
114
        bus:       NULL
115
};
116
 
117
/*====================================================================*/
118
/* Useful macros                                                      */
119
/*====================================================================*/
120
 
121
#define READ_PHYSADDR(addr) (*(volatile u32 *)(KSEG1ADDR(addr)))
122
#define WRITE_PHYSADDR(addr, data) (*(volatile u32 *)(KSEG1ADDR(addr))) = (data)
123
 
124
#define READ_CSR32(reg)         csr_in32(IO_SPACE_BASE + (reg))
125
#define WRITE_CSR32(data, reg)  csr_out32(data, IO_SPACE_BASE + (reg))
126
 
127
#define sb1250pc_write_config(data)     WRITE_CSR32(data, A_IO_PCMCIA_CFG)
128
#define sb1250pc_read_config()          READ_CSR32(A_IO_PCMCIA_CFG)
129
#define sb1250pc_read_status()          READ_CSR32(A_IO_PCMCIA_STATUS)
130
 
131
#define CARDPRESENT(s) (((s) & (M_PCMCIA_STATUS_CD1 | M_PCMCIA_STATUS_CD2)) == 0)
132
 
133
int sb_pcmcia_ack_intr(struct hwif_s *hwif)
134
{
135
        /*
136
         * XXXKW verify interrupt and return appropriate value?
137
         * Simple check of the bit in A_GPIO_READ didn't DTRT
138
         */
139
 
140
        /* Clear out the GPIO edge detector */
141
        WRITE_CSR32(1 << K_GPIO_PC_READY, A_GPIO_CLR_EDGE);
142
        return 1;
143
}
144
 
145
/*====================================================================*/
146
/* Interrupt handling                                                 */
147
/*====================================================================*/
148
 
149
static unsigned int pending_events;
150
static spinlock_t pending_event_lock = SPIN_LOCK_UNLOCKED;
151
 
152
static void sb1250pc_bh(void *dummy)
153
{
154
        unsigned int events;
155
 
156
        spin_lock_irq(&pending_event_lock);
157
        events = pending_events;
158
        pending_events = 0;
159
        spin_unlock_irq(&pending_event_lock);
160
 
161
        if (socket_handler.handler)
162
                socket_handler.handler(socket_handler.info, events);
163
}
164
 
165
static struct tq_struct sb1250pc_task =
166
{
167
        routine:        sb1250pc_bh
168
};
169
 
170
static void sb1250pc_interrupt(int irq, void *dev, struct pt_regs *regs)
171
{
172
        unsigned int events = 0;
173
        uint32_t status;
174
 
175
        status = sb1250pc_read_status();
176
 
177
        if (status & M_PCMCIA_STATUS_CDCHG) {
178
                events = SS_DETECT;
179
                if (CARDPRESENT(status)) {
180
                        events |= SS_INSERTION;
181
                } else {
182
                        events |= SS_EJECTION;
183
                }
184
        }
185
#if 0
186
        /* XXXKW ignore everything but CD? */
187
        if (status & M_PCMCIA_STATUS_RDYCHG) {
188
                if (status & M_PCMCIA_STATUS_RDY) {
189
                        /* XXXKW if ide, ack the interrupt? */
190
                        events |= SS_READY;
191
                }
192
        }
193
#endif
194
 
195
        if (events) {
196
                DPRINTK(PFX " passing %x to bh\n", events);
197
 
198
                /* Pass the events off to the bottom-half */
199
                spin_lock(&pending_event_lock);
200
                pending_events |= events;
201
                spin_unlock(&pending_event_lock);
202
                schedule_task(&sb1250pc_task);
203
        }
204
}
205
 
206
/*====================================================================*/
207
/* PC Card Operations                                                 */
208
/*====================================================================*/
209
 
210
static int sb1250pc_register_callback(unsigned int lsock,
211
                                      void (*handler)(void *, unsigned int),
212
                                      void * info)
213
{
214
        DPRINTK(PFX "sb1250pc_register_callback(%d)\n", lsock);
215
 
216
        socket_handler.handler = handler;
217
        socket_handler.info = info;
218
        if (handler == NULL) {
219
                MOD_DEC_USE_COUNT;
220
        } else {
221
                MOD_INC_USE_COUNT;
222
        }
223
        return 0;
224
}
225
 
226
/*====================================================================*/
227
 
228
static int sb1250pc_get_status(unsigned int lsock, u_int *value)
229
{
230
        u_int val;
231
        uint32_t status;
232
#if PCMCIA_DEBUG
233
        u32 config;
234
#endif
235
 
236
        status = sb1250pc_read_status();
237
#if PCMCIA_DEBUG
238
        config = sb1250pc_read_config();
239
#endif
240
 
241
        val = CARDPRESENT(status) ? SS_DETECT : 0;
242
        val |= (status & M_PCMCIA_CFG_RESET) ? SS_RESET : 0;
243
        val |= (status & (M_PCMCIA_STATUS_3VEN | M_PCMCIA_STATUS_5VEN)) ?
244
                SS_POWERON : 0;
245
        val |= (status & M_PCMCIA_STATUS_RDY) ? SS_READY : 0;
246
        val |= (status & M_PCMCIA_STATUS_WP) ? SS_WRPROT : 0;
247
        val |= ((status & M_PCMCIA_STATUS_VS2) &&
248
                (~status & M_PCMCIA_STATUS_VS1)) ? SS_3VCARD : 0;
249
        val |= (status & (M_PCMCIA_STATUS_CDCHG | M_PCMCIA_STATUS_WPCHG
250
                          | M_PCMCIA_STATUS_RDYCHG)) ? SS_STSCHG : 0;
251
        /* XXXKW SS_INSERTION on cdchange? */
252
 
253
        DPRINTK(PFX "GetStatus(%d) = %x", lsock, val);
254
#if PCMCIA_DEBUG
255
        DPRINTK(" [config(0x%4.4x) status(0x%4.4x)]", config, status);
256
#endif
257
        DPRINTK("\n");
258
 
259
        *value = val;
260
        return 0;
261
}
262
 
263
/*====================================================================*/
264
 
265
static int sb1250pc_inquire_socket(unsigned int lsock, socket_cap_t *cap)
266
{
267
        *cap = sb1250pc_cap;
268
 
269
        DPRINTK(PFX "InquireSocket(%d) = features 0x%4.4x, irq_mask "
270
               "0x%4.4x, map_size 0x%4.4x\n", lsock, cap->features,
271
               cap->irq_mask, cap->map_size);
272
 
273
        return 0;
274
}
275
 
276
/*====================================================================*/
277
 
278
// This garbage function never seems to get called...
279
static int sb1250pc_get_socket(unsigned int lsock, socket_state_t *state)
280
{
281
        DPRINTK(PFX "Does GetSocket(%d) ever get called???", lsock);
282
        return -1;
283
} /* sb1250pc_get_socket */
284
 
285
/*====================================================================*/
286
 
287
static uint32_t sibyte_set_power(uint32_t config, int vcc)
288
{
289
        config &= ~(M_PCMCIA_CFG_3VEN | M_PCMCIA_CFG_5VEN);
290
        if (vcc == 33) {
291
                config |= M_PCMCIA_CFG_3VEN;
292
        } else if (vcc == 50) {
293
                config |= M_PCMCIA_CFG_5VEN;
294
        }
295
 
296
        sb1250pc_write_config(config);
297
        return config;
298
}
299
 
300
static int sb1250pc_set_socket(unsigned int lsock, socket_state_t *state)
301
{
302
        uint32_t config;
303
 
304
        DPRINTK(PFX "SetSocket(%d, flags %#3.3x, Vcc %d, Vpp %d, "
305
               "io_irq %d, csc_mask %#2.2x)\n", lsock, state->flags,
306
               state->Vcc, state->Vpp, state->io_irq, state->csc_mask);
307
 
308
        config = sb1250pc_read_config();
309
 
310
        config = sibyte_set_power(config, state->Vcc);
311
 
312
        if (state->flags & SS_DEBOUNCED)
313
                state->flags &= ~SS_DEBOUNCED; /* SS_DEBOUNCED is oneshot */
314
        /* XXXKW SS_OUTPUT_ENA? */
315
        /* XXXKW SS_PWR_AUTO? */
316
        /* XXXKW SS_IOCARD? */
317
 
318
        if (state->csc_mask & SS_DETECT)
319
                config &= ~M_PCMCIA_CFG_CDMASK;
320
        else
321
                config |= M_PCMCIA_CFG_CDMASK;
322
 
323
        config &= ~M_PCMCIA_CFG_RESET;
324
        if (state->flags & SS_RESET) {
325
                DPRINTK(PFX "  resetting PCMCIA\n");
326
                config |= M_PCMCIA_CFG_RESET;
327
        }
328
        sb1250pc_write_config(config);
329
 
330
        DPRINTK(PFX "  new config: %x\n", sb1250pc_read_config());
331
 
332
        return 0;
333
}
334
 
335
/*====================================================================*/
336
 
337
static int sb1250pc_get_io_map(unsigned int lsock, struct pccard_io_map *io)
338
{
339
        *io = sibyte_iomap[io->map];
340
 
341
        DPRINTK(PFX "GetIOMap(%d, %d) = %#2.2x, %d ns, "
342
               "%#4.4x-%#4.4x\n", lsock, io->map, io->flags,
343
               io->speed, io->start, io->stop);
344
        return 0;
345
} /* sb1250pc_get_io_map */
346
 
347
static int sb1250pc_set_io_map(unsigned int lsock, struct pccard_io_map *io)
348
{
349
        unsigned int speed;
350
        unsigned long start;
351
        u32 config;
352
 
353
        /* SB1250 uses direct mapping */
354
        DPRINTK(PFX "SetIOMap(%d, %d, %#2.2x, %d ns, "
355
               "%#4.4x-%#4.4x) called\n", lsock, io->map, io->flags,
356
               io->speed, io->start, io->stop);
357
 
358
        if (io->map >= MAX_IO_WIN) {
359
                DPRINTK(KERN_ERR PFX "map (%d) out of range\n", io->map);
360
                return -1;
361
        }
362
 
363
        if (io->flags & MAP_ACTIVE) {
364
                speed = (io->speed > 0) ? io->speed : 255;
365
        }
366
 
367
        config = sb1250pc_read_config();
368
 
369
        if (io->flags & MAP_ATTRIB) {
370
                DPRINTK(PFX "  Setting pcmcia_cfg_reg to 1  (Attribute Mode)\n");
371
                config |= M_PCMCIA_CFG_ATTRMEM;
372
        } else {
373
                DPRINTK(PFX "  Setting pcmcia_cfg_reg to 0  (Data Mode)\n");
374
                config &= ~M_PCMCIA_CFG_ATTRMEM;
375
        }
376
        sb1250pc_write_config(config);
377
 
378
        start = io->start;
379
 
380
        if (io->stop == 1) {
381
                io->stop = PAGE_SIZE - 1;
382
        }
383
 
384
        if (io->start == 0)
385
                io->start = sb_pcmcia_base;
386
 
387
        io->stop = io->start + (io->stop - start);
388
 
389
        sibyte_iomap[io->map] = *io;
390
 
391
        DPRINTK(PFX "SetIOMap(%d, %d, %#2.2x, %d ns, "
392
               "%#4.4x-%#4.4x) returns\n", lsock, io->map, io->flags,
393
               io->speed, io->start, io->stop);
394
        return 0;
395
} /* sb1250pc_set_io_map */
396
 
397
/*====================================================================*/
398
 
399
static int sb1250pc_get_mem_map(unsigned int lsock, struct pccard_mem_map *mem)
400
{
401
        if(mem->map >= MAX_WIN)
402
                return -EINVAL;
403
 
404
        *mem = sibyte_memmap[mem->map];
405
 
406
        DPRINTK(PFX "GetMemMap(%d, mem[%d, %#2.2x, %d ns, "
407
               "%#5.5lx-%#5.5lx, %#5.5x) called\n", lsock, mem->map, mem->flags,
408
               mem->speed, mem->sys_start, mem->sys_stop, mem->card_start);
409
 
410
        return 0;
411
}
412
 
413
static int sb1250pc_set_mem_map(unsigned int lsock, struct pccard_mem_map *mem)
414
{
415
        u32 old_config, new_config;
416
 
417
        if (mem->map >= MAX_WIN) {
418
                DPRINTK(KERN_ERR PFX "map (%d) out of range\n", mem->map);
419
                return -1;
420
        }
421
 
422
        if (mem->sys_start == 0)
423
                mem->sys_start = mem->card_start + sb_pcmcia_base;
424
 
425
        if (mem->sys_stop == 0)
426
                mem->sys_stop = mem->sys_start + sb_pcmcia_size - 1;
427
 
428
        old_config = sb1250pc_read_config();
429
 
430
        DPRINTK(PFX "  Setting mem_map %p\n", mem);
431
        if (mem->flags & MAP_ATTRIB) {
432
                DPRINTK(PFX "  Setting pcmcia_cfg_reg to 1 (Attribute Mode)\n");
433
                new_config = old_config | M_PCMCIA_CFG_ATTRMEM;
434
        } else {
435
                DPRINTK(PFX "  Setting pcmcia_cfg_reg to 0 (Data Mode)\n");
436
                new_config = old_config & ~M_PCMCIA_CFG_ATTRMEM;
437
        }
438
        if (new_config != old_config)
439
                sb1250pc_write_config(new_config);
440
 
441
        sibyte_memmap[mem->map] = *mem;
442
 
443
        DPRINTK(PFX "SetMemMap(%d, mem[%d, %#2.2x, %d ns], "
444
               "%#5.5lx-%#5.5lx, %#5.5x)\n", lsock, mem->map, mem->flags,
445
               mem->speed, mem->sys_start, mem->sys_stop, mem->card_start);
446
 
447
        return 0;
448
}
449
 
450
/*====================================================================*/
451
 
452
#ifdef CONFIG_PROC_FS
453
/* sb1250pc_proc_status()
454
 * Implements the /proc/bus/pccard/??/status file.
455
 *
456
 * Returns: the number of characters added to the buffer
457
 *
458
 * Be aware that reading status clears the "change" bits; this seems
459
 * unlikely to bite us by making us miss interrupts.
460
 */
461
static int sb1250pc_proc_status(char *buf, char **start, off_t pos,
462
                                int count, int *eof, void *data)
463
{
464
        char *p = buf;
465
        u32 addr, temp;
466
        u32 status, config;
467
        //unsigned int sock = (unsigned int) data;
468
 
469
        config = sb1250pc_read_config();
470
        status = sb1250pc_read_status();
471
        p += sprintf(p, "config(0x%4.4x) status(0x%4.4x)\n", config, status);
472
 
473
        for (addr = sb_pcmcia_base; addr < sb_pcmcia_base + 8; addr+=4) {
474
                temp = READ_PHYSADDR(addr);
475
                p += sprintf(p, " Looking up addr 0x%x: 0x%8.8x\n", addr, temp);
476
        }
477
 
478
        return p - buf;
479
}
480
 
481
static void sb1250pc_proc_setup(unsigned int sock, struct proc_dir_entry *base)
482
{
483
        struct proc_dir_entry *entry;
484
 
485
        if ((entry = create_proc_entry("sb1250pc", 0, base)) == NULL) {
486
                printk(KERN_ERR PFX "Unable to install \"sb1250pc\" procfs entry\n");
487
                return;
488
        } else
489
                printk(KERN_INFO PFX "Setting up \"sb1250pc\" procfs entry\n");
490
 
491
        entry->read_proc = sb1250pc_proc_status;
492
        entry->data = (void *) sock;
493
}
494
 
495
#endif
496
 
497
/*====================================================================*/
498
 
499
static int sibyte_pcmcia_initted = 0;
500
 
501
static int sb1250pc_init(unsigned int s)
502
{
503
        u32 config, status;
504
 
505
        DPRINTK(PFX "Initializing SB1250 PCMCIA:\n");
506
 
507
        /* Read status to clear interrupt sources */
508
        status = sb1250pc_read_status();
509
 
510
        /*
511
         * Before getting setting up the IRQ, set the config:
512
         *   reset off, auto-power off
513
         *   interrupt mask: WP, CD, Ready off
514
         */
515
        config = sb1250pc_read_config();
516
        config = M_PCMCIA_CFG_CDMASK | M_PCMCIA_CFG_WPMASK | M_PCMCIA_CFG_RDYMASK;
517
        sb1250pc_write_config(config);
518
 
519
        if (!sibyte_pcmcia_initted) {
520
                uint32_t gpio_ctrl;
521
                /* Set up the GPIO for PC_READY for use in ide-cs */
522
                gpio_ctrl = READ_CSR32(A_GPIO_INT_TYPE);
523
                gpio_ctrl &= ~M_GPIO_INTR_TYPEX(K_GPIO_PC_READY);
524
                gpio_ctrl |= V_GPIO_INTR_TYPEX(K_GPIO_PC_READY, K_GPIO_INTR_EDGE);
525
                WRITE_CSR32(gpio_ctrl, A_GPIO_INT_TYPE);
526
                WRITE_CSR32(1 << K_GPIO_PC_READY, A_GPIO_CLR_EDGE);
527
 
528
                /* Invert to get busy->ready transition */
529
                gpio_ctrl = READ_CSR32(A_GPIO_INPUT_INVERT);
530
                gpio_ctrl |= 1 << K_GPIO_PC_READY;
531
                WRITE_CSR32(gpio_ctrl, A_GPIO_INPUT_INVERT);
532
 
533
                /* Should not be any pending since we masked all sources */
534
                if (request_irq(cs_irq, sb1250pc_interrupt, 0, "pcmcia", NULL))
535
                        return -ENODEV;
536
                DPRINTK(PFX "  IRQ %d registered\n", cs_irq);
537
 
538
                sibyte_pcmcia_initted = 1;
539
        }
540
 
541
        status = sb1250pc_read_status();
542
        DPRINTK(PFX "  config(0x%4.4x) status(0x%4.4x)\n", config, status);
543
 
544
        sb1250pc_set_socket(s, &dead_socket);
545
 
546
        return 0;
547
}
548
 
549
static int sb1250pc_suspend(unsigned int sock)
550
{
551
        free_irq(cs_irq, NULL);
552
        DPRINTK(KERN_INFO PFX "  IRQ %d freed\n", cs_irq);
553
        return sb1250pc_set_socket(sock, &dead_socket);
554
}
555
 
556
static struct pccard_operations sb1250pc_operations = {
557
        sb1250pc_init,
558
        sb1250pc_suspend,
559
        sb1250pc_register_callback,
560
        sb1250pc_inquire_socket,
561
        sb1250pc_get_status,
562
        sb1250pc_get_socket,
563
        sb1250pc_set_socket,
564
        sb1250pc_get_io_map,
565
        sb1250pc_set_io_map,
566
        sb1250pc_get_mem_map,
567
        sb1250pc_set_mem_map,
568
#ifdef CONFIG_PROC_FS
569
        sb1250pc_proc_setup
570
#endif
571
};
572
 
573
/*
574
 * XXXKW This is a hack.  The ide-cs stuff seems to leave us in
575
 * Attribute mode.  Since I know that a SELECT_DRIVE will happen as
576
 * the first I/O access, use this opportunity to enter data mode.
577
 */
578
static void sibyte_pcmcia_selectproc(ide_drive_t *drive)
579
{
580
        sb1250pc_write_config(sb1250pc_read_config() & ~M_PCMCIA_CFG_ATTRMEM);
581
}
582
 
583
static int sibyte_pc_prep_ide(void)
584
{
585
        int i;
586
        ide_hwif_t *hwif = NULL;
587
 
588
        /* Stake early claim on an ide_hwif */
589
        for (i = 0; i < MAX_HWIFS; i++) {
590
                if (!ide_hwifs[i].io_ports[IDE_DATA_OFFSET]) {
591
                        hwif = &ide_hwifs[i];
592
                        break;
593
                }
594
        }
595
        if (hwif == NULL) {
596
                printk("No space for SiByte onboard PCMCIA driver in ide_hwifs[].  Not enabled.\n");
597
                return 1;
598
        }
599
 
600
        /*
601
         * Prime the hwif with port values, so when a card is
602
         * detected, the 'io_offset' from the capabilities will lead
603
         * it here
604
         */
605
        hwif->hw.io_ports[IDE_DATA_OFFSET]    = SIBYTE_CS_REG(0);
606
        hwif->hw.io_ports[IDE_ERROR_OFFSET]   = SIBYTE_CS_REG(1);
607
        hwif->hw.io_ports[IDE_NSECTOR_OFFSET] = SIBYTE_CS_REG(2);
608
        hwif->hw.io_ports[IDE_SECTOR_OFFSET]  = SIBYTE_CS_REG(3);
609
        hwif->hw.io_ports[IDE_LCYL_OFFSET]    = SIBYTE_CS_REG(4);
610
        hwif->hw.io_ports[IDE_HCYL_OFFSET]    = SIBYTE_CS_REG(5);
611
        hwif->hw.io_ports[IDE_SELECT_OFFSET]  = SIBYTE_CS_REG(6);
612
        hwif->hw.io_ports[IDE_STATUS_OFFSET]  = SIBYTE_CS_REG(7);
613
        hwif->hw.io_ports[IDE_CONTROL_OFFSET] = SIBYTE_CS_REG(6); /* XXXKW ? */
614
        hwif->hw.ack_intr                     = sb_pcmcia_ack_intr;
615
        hwif->selectproc                      = sibyte_pcmcia_selectproc;
616
        hwif->hold                            = 1;
617
        hwif->mmio                            = 2;
618
        sibyte_set_ideops(&ide_hwifs[i]);
619
 
620
        printk("SiByte onboard PCMCIA-IDE configured as device %i\n", i);
621
 
622
        return 0;
623
}
624
 
625
static int __init sibyte_pcmcia_init(void)
626
{
627
        servinfo_t info;
628
        u32 addr, temp;
629
        u64 cfg;
630
 
631
        CardServices(GetCardServicesInfo, &info);
632
        if (info.Revision != CS_RELEASE_CODE) {
633
                printk(KERN_ERR PFX "Card Services release does not match!\n");
634
                return -1;
635
        }
636
 
637
        cfg = in64(IO_SPACE_BASE + A_SCD_SYSTEM_CFG);
638
        if (!(cfg & M_SYS_PCMCIA_ENABLE)) {
639
                printk(KERN_INFO PFX "chip not configured for PCMCIA\n");
640
                return -1;
641
        }
642
 
643
        /* Find memory base address and size */
644
        addr = A_IO_EXT_REG(R_IO_EXT_REG(R_IO_EXT_MULT_SIZE, PCMCIA_CS));
645
        temp = G_IO_MULT_SIZE(csr_in32(IO_SPACE_BASE + addr));
646
        printk(PFX "Looking up addr 0x%x: 0x%4.4x (IO size)\n", addr, temp);
647
        sb_pcmcia_size = (temp+1) << S_IO_REGSIZE;
648
 
649
        addr = A_IO_EXT_REG(R_IO_EXT_REG(R_IO_EXT_START_ADDR, PCMCIA_CS));
650
        temp = G_IO_START_ADDR(csr_in32(KSEG1|addr));
651
        printk(PFX "Looking up addr 0x%x: 0x%4.4x (IO Base Address)\n", addr, temp);
652
        if (temp << S_IO_ADDRBASE != PCMCIA_PHYS)
653
                panic(PFX "pcmcia base doesn't match gencs value\n");
654
 
655
        /* check and request memory region */
656
        if (check_mem_region(sb_pcmcia_base, sb_pcmcia_size)) {
657
                printk(KERN_ERR PFX "Can't request memory region?\n");
658
        } else {
659
                request_mem_region(sb_pcmcia_base, sb_pcmcia_size, "sibyte-pcmcia");
660
                printk(PFX "Memory region 0x%8.8lx of size 0x%8.8lx requested.\n",
661
                       sb_pcmcia_base, sb_pcmcia_size);
662
        }
663
 
664
        /* register with socket services */
665
        if (register_ss_entry(1, &sb1250pc_operations)) {
666
                printk(KERN_ERR PFX "register_ss_entry() failed\n");
667
                release_region(sb_pcmcia_base, sb_pcmcia_size);
668
                return -ENODEV;
669
        }
670
 
671
        if (!sibyte_pc_prep_ide()) {
672
                /* XXXKW hack for ide-cs warning squash */
673
                request_region(sb1250pc_cap.io_offset, 16, "ide-cs");
674
                request_mem_region(SIBYTE_CS_REG(0), 8, "sibyte-ide-cs");
675
        }
676
 
677
        return 0;
678
}
679
 
680
static void __exit sibyte_pcmcia_exit(void)
681
{
682
        /* XXXKW untested as module */
683
        unregister_ss_entry(&sb1250pc_operations);
684
        release_region(sb_pcmcia_base, sb_pcmcia_size);
685
}
686
 
687
module_init(sibyte_pcmcia_init);
688
module_exit(sibyte_pcmcia_exit);

powered by: WebSVN 2.1.0

© copyright 1999-2025 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.