Merge ARM fixes
[linux-2.6] / drivers / ide / legacy / gayle.c
1 /*
2  *  linux/drivers/ide/legacy/gayle.c -- Amiga Gayle IDE Driver
3  *
4  *     Created 9 Jul 1997 by Geert Uytterhoeven
5  *
6  *  This file is subject to the terms and conditions of the GNU General Public
7  *  License.  See the file COPYING in the main directory of this archive for
8  *  more details.
9  */
10
11 #include <linux/types.h>
12 #include <linux/mm.h>
13 #include <linux/interrupt.h>
14 #include <linux/blkdev.h>
15 #include <linux/hdreg.h>
16 #include <linux/ide.h>
17 #include <linux/init.h>
18 #include <linux/zorro.h>
19
20 #include <asm/setup.h>
21 #include <asm/amigahw.h>
22 #include <asm/amigaints.h>
23 #include <asm/amigayle.h>
24
25
26     /*
27      *  Bases of the IDE interfaces
28      */
29
30 #define GAYLE_BASE_4000 0xdd2020        /* A4000/A4000T */
31 #define GAYLE_BASE_1200 0xda0000        /* A1200/A600 and E-Matrix 530 */
32
33     /*
34      *  Offsets from one of the above bases
35      */
36
37 #define GAYLE_DATA      0x00
38 #define GAYLE_ERROR     0x06            /* see err-bits */
39 #define GAYLE_NSECTOR   0x0a            /* nr of sectors to read/write */
40 #define GAYLE_SECTOR    0x0e            /* starting sector */
41 #define GAYLE_LCYL      0x12            /* starting cylinder */
42 #define GAYLE_HCYL      0x16            /* high byte of starting cyl */
43 #define GAYLE_SELECT    0x1a            /* 101dhhhh , d=drive, hhhh=head */
44 #define GAYLE_STATUS    0x1e            /* see status-bits */
45 #define GAYLE_CONTROL   0x101a
46
47 static int gayle_offsets[IDE_NR_PORTS] __initdata = {
48     GAYLE_DATA, GAYLE_ERROR, GAYLE_NSECTOR, GAYLE_SECTOR, GAYLE_LCYL,
49     GAYLE_HCYL, GAYLE_SELECT, GAYLE_STATUS, -1, -1
50 };
51
52
53     /*
54      *  These are at different offsets from the base
55      */
56
57 #define GAYLE_IRQ_4000  0xdd3020        /* MSB = 1, Harddisk is source of */
58 #define GAYLE_IRQ_1200  0xda9000        /* interrupt */
59
60
61     /*
62      *  Offset of the secondary port for IDE doublers
63      *  Note that GAYLE_CONTROL is NOT available then!
64      */
65
66 #define GAYLE_NEXT_PORT 0x1000
67
68 #ifndef CONFIG_BLK_DEV_IDEDOUBLER
69 #define GAYLE_NUM_HWIFS         1
70 #define GAYLE_NUM_PROBE_HWIFS   GAYLE_NUM_HWIFS
71 #define GAYLE_HAS_CONTROL_REG   1
72 #define GAYLE_IDEREG_SIZE       0x2000
73 #else /* CONFIG_BLK_DEV_IDEDOUBLER */
74 #define GAYLE_NUM_HWIFS         2
75 #define GAYLE_NUM_PROBE_HWIFS   (ide_doubler ? GAYLE_NUM_HWIFS : \
76                                                GAYLE_NUM_HWIFS-1)
77 #define GAYLE_HAS_CONTROL_REG   (!ide_doubler)
78 #define GAYLE_IDEREG_SIZE       (ide_doubler ? 0x1000 : 0x2000)
79 int ide_doubler = 0;    /* support IDE doublers? */
80 #endif /* CONFIG_BLK_DEV_IDEDOUBLER */
81
82
83     /*
84      *  Check and acknowledge the interrupt status
85      */
86
87 static int gayle_ack_intr_a4000(ide_hwif_t *hwif)
88 {
89     unsigned char ch;
90
91     ch = z_readb(hwif->io_ports[IDE_IRQ_OFFSET]);
92     if (!(ch & GAYLE_IRQ_IDE))
93         return 0;
94     return 1;
95 }
96
97 static int gayle_ack_intr_a1200(ide_hwif_t *hwif)
98 {
99     unsigned char ch;
100
101     ch = z_readb(hwif->io_ports[IDE_IRQ_OFFSET]);
102     if (!(ch & GAYLE_IRQ_IDE))
103         return 0;
104     (void)z_readb(hwif->io_ports[IDE_STATUS_OFFSET]);
105     z_writeb(0x7c, hwif->io_ports[IDE_IRQ_OFFSET]);
106     return 1;
107 }
108
109     /*
110      *  Probe for a Gayle IDE interface (and optionally for an IDE doubler)
111      */
112
113 void __init gayle_init(void)
114 {
115     int a4000, i;
116
117     if (!MACH_IS_AMIGA)
118         return;
119
120     if ((a4000 = AMIGAHW_PRESENT(A4000_IDE)) || AMIGAHW_PRESENT(A1200_IDE))
121         goto found;
122
123 #ifdef CONFIG_ZORRO
124     if (zorro_find_device(ZORRO_PROD_MTEC_VIPER_MK_V_E_MATRIX_530_SCSI_IDE,
125                           NULL))
126         goto found;
127 #endif
128     return;
129
130 found:
131     for (i = 0; i < GAYLE_NUM_PROBE_HWIFS; i++) {
132         unsigned long base, ctrlport, irqport;
133         ide_ack_intr_t *ack_intr;
134         hw_regs_t hw;
135         ide_hwif_t *hwif;
136         int index;
137         unsigned long phys_base, res_start, res_n;
138
139         if (a4000) {
140             phys_base = GAYLE_BASE_4000;
141             irqport = (unsigned long)ZTWO_VADDR(GAYLE_IRQ_4000);
142             ack_intr = gayle_ack_intr_a4000;
143         } else {
144             phys_base = GAYLE_BASE_1200;
145             irqport = (unsigned long)ZTWO_VADDR(GAYLE_IRQ_1200);
146             ack_intr = gayle_ack_intr_a1200;
147         }
148 /*
149  * FIXME: we now have selectable modes between mmio v/s iomio
150  */
151
152         phys_base += i*GAYLE_NEXT_PORT;
153
154         res_start = ((unsigned long)phys_base) & ~(GAYLE_NEXT_PORT-1);
155         res_n = GAYLE_IDEREG_SIZE;
156
157         if (!request_mem_region(res_start, res_n, "IDE"))
158             continue;
159
160         base = (unsigned long)ZTWO_VADDR(phys_base);
161         ctrlport = GAYLE_HAS_CONTROL_REG ? (base + GAYLE_CONTROL) : 0;
162
163         ide_setup_ports(&hw, base, gayle_offsets,
164                         ctrlport, irqport, ack_intr,
165 //                      &gayle_iops,
166                         IRQ_AMIGA_PORTS);
167
168         index = ide_register_hw(&hw, &hwif);
169         if (index != -1) {
170             hwif->mmio = 1;
171             switch (i) {
172                 case 0:
173                     printk("ide%d: Gayle IDE interface (A%d style)\n", index,
174                            a4000 ? 4000 : 1200);
175                     break;
176 #ifdef CONFIG_BLK_DEV_IDEDOUBLER
177                 case 1:
178                     printk("ide%d: IDE doubler\n", index);
179                     break;
180 #endif /* CONFIG_BLK_DEV_IDEDOUBLER */
181             }
182         } else
183             release_mem_region(res_start, res_n);
184     }
185 }