Merge branches 'at91', 'ep93xx', 'iop', 'kprobes', 'ks8695', 'misc', 'msm', 's3c2410...
[sfrench/cifs-2.6.git] / 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 static int __init gayle_init(void)
114 {
115     int a4000, i;
116     u8 idx[4] = { 0xff, 0xff, 0xff, 0xff };
117
118     if (!MACH_IS_AMIGA)
119         return -ENODEV;
120
121     if ((a4000 = AMIGAHW_PRESENT(A4000_IDE)) || AMIGAHW_PRESENT(A1200_IDE))
122         goto found;
123
124 #ifdef CONFIG_ZORRO
125     if (zorro_find_device(ZORRO_PROD_MTEC_VIPER_MK_V_E_MATRIX_530_SCSI_IDE,
126                           NULL))
127         goto found;
128 #endif
129     return -ENODEV;
130
131 found:
132         printk(KERN_INFO "ide: Gayle IDE controller (A%d style%s)\n",
133                          a4000 ? 4000 : 1200,
134 #ifdef CONFIG_BLK_DEV_IDEDOUBLER
135                          ide_doubler ? ", IDE doubler" :
136 #endif
137                          "");
138
139     for (i = 0; i < GAYLE_NUM_PROBE_HWIFS; i++) {
140         unsigned long base, ctrlport, irqport;
141         ide_ack_intr_t *ack_intr;
142         hw_regs_t hw;
143         ide_hwif_t *hwif;
144         unsigned long phys_base, res_start, res_n;
145
146         if (a4000) {
147             phys_base = GAYLE_BASE_4000;
148             irqport = (unsigned long)ZTWO_VADDR(GAYLE_IRQ_4000);
149             ack_intr = gayle_ack_intr_a4000;
150         } else {
151             phys_base = GAYLE_BASE_1200;
152             irqport = (unsigned long)ZTWO_VADDR(GAYLE_IRQ_1200);
153             ack_intr = gayle_ack_intr_a1200;
154         }
155 /*
156  * FIXME: we now have selectable modes between mmio v/s iomio
157  */
158
159         phys_base += i*GAYLE_NEXT_PORT;
160
161         res_start = ((unsigned long)phys_base) & ~(GAYLE_NEXT_PORT-1);
162         res_n = GAYLE_IDEREG_SIZE;
163
164         if (!request_mem_region(res_start, res_n, "IDE"))
165             continue;
166
167         base = (unsigned long)ZTWO_VADDR(phys_base);
168         ctrlport = GAYLE_HAS_CONTROL_REG ? (base + GAYLE_CONTROL) : 0;
169
170         ide_setup_ports(&hw, base, gayle_offsets,
171                         ctrlport, irqport, ack_intr,
172 //                      &gayle_iops,
173                         IRQ_AMIGA_PORTS);
174
175         hwif = ide_find_port(base);
176         if (hwif) {
177             u8 index = hwif->index;
178
179             ide_init_port_data(hwif, index);
180             ide_init_port_hw(hwif, &hw);
181
182             hwif->mmio = 1;
183
184             idx[i] = index;
185         } else
186             release_mem_region(res_start, res_n);
187     }
188
189     ide_device_add(idx);
190
191     return 0;
192 }
193
194 module_init(gayle_init);