| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 1 | /* | 
| Bartlomiej Zolnierkiewicz | 58f189f | 2008-02-01 23:09:33 +0100 | [diff] [blame] | 2 | *  Amiga Gayle IDE Driver | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 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 |  | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 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 |  | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 37 | #define GAYLE_CONTROL	0x101a | 
|  | 38 |  | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 39 | /* | 
|  | 40 | *  These are at different offsets from the base | 
|  | 41 | */ | 
|  | 42 |  | 
|  | 43 | #define GAYLE_IRQ_4000	0xdd3020	/* MSB = 1, Harddisk is source of */ | 
|  | 44 | #define GAYLE_IRQ_1200	0xda9000	/* interrupt */ | 
|  | 45 |  | 
|  | 46 |  | 
|  | 47 | /* | 
|  | 48 | *  Offset of the secondary port for IDE doublers | 
|  | 49 | *  Note that GAYLE_CONTROL is NOT available then! | 
|  | 50 | */ | 
|  | 51 |  | 
|  | 52 | #define GAYLE_NEXT_PORT	0x1000 | 
|  | 53 |  | 
|  | 54 | #ifndef CONFIG_BLK_DEV_IDEDOUBLER | 
|  | 55 | #define GAYLE_NUM_HWIFS		1 | 
|  | 56 | #define GAYLE_NUM_PROBE_HWIFS	GAYLE_NUM_HWIFS | 
|  | 57 | #define GAYLE_HAS_CONTROL_REG	1 | 
|  | 58 | #define GAYLE_IDEREG_SIZE	0x2000 | 
|  | 59 | #else /* CONFIG_BLK_DEV_IDEDOUBLER */ | 
|  | 60 | #define GAYLE_NUM_HWIFS		2 | 
|  | 61 | #define GAYLE_NUM_PROBE_HWIFS	(ide_doubler ? GAYLE_NUM_HWIFS : \ | 
|  | 62 | GAYLE_NUM_HWIFS-1) | 
|  | 63 | #define GAYLE_HAS_CONTROL_REG	(!ide_doubler) | 
|  | 64 | #define GAYLE_IDEREG_SIZE	(ide_doubler ? 0x1000 : 0x2000) | 
|  | 65 | int ide_doubler = 0;	/* support IDE doublers? */ | 
|  | 66 | #endif /* CONFIG_BLK_DEV_IDEDOUBLER */ | 
|  | 67 |  | 
|  | 68 |  | 
|  | 69 | /* | 
|  | 70 | *  Check and acknowledge the interrupt status | 
|  | 71 | */ | 
|  | 72 |  | 
|  | 73 | static int gayle_ack_intr_a4000(ide_hwif_t *hwif) | 
|  | 74 | { | 
|  | 75 | unsigned char ch; | 
|  | 76 |  | 
|  | 77 | ch = z_readb(hwif->io_ports[IDE_IRQ_OFFSET]); | 
|  | 78 | if (!(ch & GAYLE_IRQ_IDE)) | 
|  | 79 | return 0; | 
|  | 80 | return 1; | 
|  | 81 | } | 
|  | 82 |  | 
|  | 83 | static int gayle_ack_intr_a1200(ide_hwif_t *hwif) | 
|  | 84 | { | 
|  | 85 | unsigned char ch; | 
|  | 86 |  | 
|  | 87 | ch = z_readb(hwif->io_ports[IDE_IRQ_OFFSET]); | 
|  | 88 | if (!(ch & GAYLE_IRQ_IDE)) | 
|  | 89 | return 0; | 
|  | 90 | (void)z_readb(hwif->io_ports[IDE_STATUS_OFFSET]); | 
|  | 91 | z_writeb(0x7c, hwif->io_ports[IDE_IRQ_OFFSET]); | 
|  | 92 | return 1; | 
|  | 93 | } | 
|  | 94 |  | 
| Bartlomiej Zolnierkiewicz | 29dd597 | 2008-02-06 02:57:50 +0100 | [diff] [blame] | 95 | static void __init gayle_setup_ports(hw_regs_t *hw, unsigned long base, | 
|  | 96 | unsigned long ctl, unsigned long irq_port, | 
| Adrian Bunk | 56efa7b | 2008-02-11 00:32:14 +0100 | [diff] [blame] | 97 | ide_ack_intr_t *ack_intr) | 
| Bartlomiej Zolnierkiewicz | 29dd597 | 2008-02-06 02:57:50 +0100 | [diff] [blame] | 98 | { | 
|  | 99 | int i; | 
|  | 100 |  | 
|  | 101 | memset(hw, 0, sizeof(*hw)); | 
|  | 102 |  | 
|  | 103 | hw->io_ports[IDE_DATA_OFFSET] = base; | 
|  | 104 |  | 
|  | 105 | for (i = 1; i < 8; i++) | 
|  | 106 | hw->io_ports[i] = base + 2 + i * 4; | 
|  | 107 |  | 
|  | 108 | hw->io_ports[IDE_CONTROL_OFFSET] = ctl; | 
|  | 109 | hw->io_ports[IDE_IRQ_OFFSET] = irq_port; | 
|  | 110 |  | 
|  | 111 | hw->irq = IRQ_AMIGA_PORTS; | 
|  | 112 | hw->ack_intr = ack_intr; | 
|  | 113 | } | 
|  | 114 |  | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 115 | /* | 
|  | 116 | *  Probe for a Gayle IDE interface (and optionally for an IDE doubler) | 
|  | 117 | */ | 
|  | 118 |  | 
| Bartlomiej Zolnierkiewicz | ade2daf | 2008-01-26 20:13:07 +0100 | [diff] [blame] | 119 | static int __init gayle_init(void) | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 120 | { | 
|  | 121 | int a4000, i; | 
| Bartlomiej Zolnierkiewicz | 8ac4ce7 | 2008-01-26 20:13:06 +0100 | [diff] [blame] | 122 | u8 idx[4] = { 0xff, 0xff, 0xff, 0xff }; | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 123 |  | 
|  | 124 | if (!MACH_IS_AMIGA) | 
| Bartlomiej Zolnierkiewicz | ade2daf | 2008-01-26 20:13:07 +0100 | [diff] [blame] | 125 | return -ENODEV; | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 126 |  | 
|  | 127 | if ((a4000 = AMIGAHW_PRESENT(A4000_IDE)) || AMIGAHW_PRESENT(A1200_IDE)) | 
|  | 128 | goto found; | 
|  | 129 |  | 
|  | 130 | #ifdef CONFIG_ZORRO | 
|  | 131 | if (zorro_find_device(ZORRO_PROD_MTEC_VIPER_MK_V_E_MATRIX_530_SCSI_IDE, | 
|  | 132 | NULL)) | 
|  | 133 | goto found; | 
|  | 134 | #endif | 
| Bartlomiej Zolnierkiewicz | ade2daf | 2008-01-26 20:13:07 +0100 | [diff] [blame] | 135 | return -ENODEV; | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 136 |  | 
|  | 137 | found: | 
| Bartlomiej Zolnierkiewicz | c99c92c | 2008-01-26 20:13:09 +0100 | [diff] [blame] | 138 | printk(KERN_INFO "ide: Gayle IDE controller (A%d style%s)\n", | 
|  | 139 | a4000 ? 4000 : 1200, | 
|  | 140 | #ifdef CONFIG_BLK_DEV_IDEDOUBLER | 
|  | 141 | ide_doubler ? ", IDE doubler" : | 
|  | 142 | #endif | 
|  | 143 | ""); | 
|  | 144 |  | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 145 | for (i = 0; i < GAYLE_NUM_PROBE_HWIFS; i++) { | 
|  | 146 | unsigned long base, ctrlport, irqport; | 
|  | 147 | ide_ack_intr_t *ack_intr; | 
|  | 148 | hw_regs_t hw; | 
|  | 149 | ide_hwif_t *hwif; | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 150 | unsigned long phys_base, res_start, res_n; | 
|  | 151 |  | 
|  | 152 | if (a4000) { | 
|  | 153 | phys_base = GAYLE_BASE_4000; | 
|  | 154 | irqport = (unsigned long)ZTWO_VADDR(GAYLE_IRQ_4000); | 
|  | 155 | ack_intr = gayle_ack_intr_a4000; | 
|  | 156 | } else { | 
|  | 157 | phys_base = GAYLE_BASE_1200; | 
|  | 158 | irqport = (unsigned long)ZTWO_VADDR(GAYLE_IRQ_1200); | 
|  | 159 | ack_intr = gayle_ack_intr_a1200; | 
|  | 160 | } | 
|  | 161 | /* | 
|  | 162 | * FIXME: we now have selectable modes between mmio v/s iomio | 
|  | 163 | */ | 
|  | 164 |  | 
|  | 165 | phys_base += i*GAYLE_NEXT_PORT; | 
|  | 166 |  | 
|  | 167 | res_start = ((unsigned long)phys_base) & ~(GAYLE_NEXT_PORT-1); | 
|  | 168 | res_n = GAYLE_IDEREG_SIZE; | 
|  | 169 |  | 
|  | 170 | if (!request_mem_region(res_start, res_n, "IDE")) | 
|  | 171 | continue; | 
|  | 172 |  | 
|  | 173 | base = (unsigned long)ZTWO_VADDR(phys_base); | 
|  | 174 | ctrlport = GAYLE_HAS_CONTROL_REG ? (base + GAYLE_CONTROL) : 0; | 
|  | 175 |  | 
| Bartlomiej Zolnierkiewicz | 29dd597 | 2008-02-06 02:57:50 +0100 | [diff] [blame] | 176 | gayle_setup_ports(&hw, base, ctrlport, irqport, ack_intr); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 177 |  | 
| Bartlomiej Zolnierkiewicz | cbb010c | 2008-01-26 20:13:06 +0100 | [diff] [blame] | 178 | hwif = ide_find_port(base); | 
|  | 179 | if (hwif) { | 
|  | 180 | u8 index = hwif->index; | 
|  | 181 |  | 
|  | 182 | ide_init_port_data(hwif, index); | 
|  | 183 | ide_init_port_hw(hwif, &hw); | 
|  | 184 |  | 
| Bartlomiej Zolnierkiewicz | 2ad1e55 | 2007-02-17 02:40:25 +0100 | [diff] [blame] | 185 | hwif->mmio = 1; | 
| Bartlomiej Zolnierkiewicz | 8ac4ce7 | 2008-01-26 20:13:06 +0100 | [diff] [blame] | 186 |  | 
|  | 187 | idx[i] = index; | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 188 | } else | 
|  | 189 | release_mem_region(res_start, res_n); | 
|  | 190 | } | 
| Bartlomiej Zolnierkiewicz | 8ac4ce7 | 2008-01-26 20:13:06 +0100 | [diff] [blame] | 191 |  | 
| Bartlomiej Zolnierkiewicz | c413b9b | 2008-02-02 19:56:31 +0100 | [diff] [blame] | 192 | ide_device_add(idx, NULL); | 
| Bartlomiej Zolnierkiewicz | ade2daf | 2008-01-26 20:13:07 +0100 | [diff] [blame] | 193 |  | 
|  | 194 | return 0; | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 195 | } | 
| Bartlomiej Zolnierkiewicz | ade2daf | 2008-01-26 20:13:07 +0100 | [diff] [blame] | 196 |  | 
|  | 197 | module_init(gayle_init); |