| 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? */ | 
| Bartlomiej Zolnierkiewicz | 9dcba7f | 2008-04-27 15:38:30 +0200 | [diff] [blame] | 66 | module_param_named(doubler, ide_doubler, bool, 0); | 
 | 67 | MODULE_PARM_DESC(doubler, "enable support for IDE doublers"); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 68 | #endif /* CONFIG_BLK_DEV_IDEDOUBLER */ | 
 | 69 |  | 
 | 70 |  | 
 | 71 |     /* | 
 | 72 |      *  Check and acknowledge the interrupt status | 
 | 73 |      */ | 
 | 74 |  | 
 | 75 | static int gayle_ack_intr_a4000(ide_hwif_t *hwif) | 
 | 76 | { | 
 | 77 |     unsigned char ch; | 
 | 78 |  | 
| Bartlomiej Zolnierkiewicz | 4c3032d | 2008-04-27 15:38:32 +0200 | [diff] [blame] | 79 |     ch = z_readb(hwif->io_ports.irq_addr); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 80 |     if (!(ch & GAYLE_IRQ_IDE)) | 
 | 81 | 	return 0; | 
 | 82 |     return 1; | 
 | 83 | } | 
 | 84 |  | 
 | 85 | static int gayle_ack_intr_a1200(ide_hwif_t *hwif) | 
 | 86 | { | 
 | 87 |     unsigned char ch; | 
 | 88 |  | 
| Bartlomiej Zolnierkiewicz | 4c3032d | 2008-04-27 15:38:32 +0200 | [diff] [blame] | 89 |     ch = z_readb(hwif->io_ports.irq_addr); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 90 |     if (!(ch & GAYLE_IRQ_IDE)) | 
 | 91 | 	return 0; | 
| Bartlomiej Zolnierkiewicz | 4c3032d | 2008-04-27 15:38:32 +0200 | [diff] [blame] | 92 |     (void)z_readb(hwif->io_ports.status_addr); | 
 | 93 |     z_writeb(0x7c, hwif->io_ports.irq_addr); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 94 |     return 1; | 
 | 95 | } | 
 | 96 |  | 
| Bartlomiej Zolnierkiewicz | 29dd597 | 2008-02-06 02:57:50 +0100 | [diff] [blame] | 97 | static void __init gayle_setup_ports(hw_regs_t *hw, unsigned long base, | 
 | 98 | 				     unsigned long ctl, unsigned long irq_port, | 
| Adrian Bunk | 56efa7b | 2008-02-11 00:32:14 +0100 | [diff] [blame] | 99 | 				     ide_ack_intr_t *ack_intr) | 
| Bartlomiej Zolnierkiewicz | 29dd597 | 2008-02-06 02:57:50 +0100 | [diff] [blame] | 100 | { | 
 | 101 | 	int i; | 
 | 102 |  | 
 | 103 | 	memset(hw, 0, sizeof(*hw)); | 
 | 104 |  | 
| Bartlomiej Zolnierkiewicz | 4c3032d | 2008-04-27 15:38:32 +0200 | [diff] [blame] | 105 | 	hw->io_ports.data_addr = base; | 
| Bartlomiej Zolnierkiewicz | 29dd597 | 2008-02-06 02:57:50 +0100 | [diff] [blame] | 106 |  | 
 | 107 | 	for (i = 1; i < 8; i++) | 
| Bartlomiej Zolnierkiewicz | 4c3032d | 2008-04-27 15:38:32 +0200 | [diff] [blame] | 108 | 		hw->io_ports_array[i] = base + 2 + i * 4; | 
| Bartlomiej Zolnierkiewicz | 29dd597 | 2008-02-06 02:57:50 +0100 | [diff] [blame] | 109 |  | 
| Bartlomiej Zolnierkiewicz | 4c3032d | 2008-04-27 15:38:32 +0200 | [diff] [blame] | 110 | 	hw->io_ports.ctl_addr = ctl; | 
 | 111 | 	hw->io_ports.irq_addr = irq_port; | 
| Bartlomiej Zolnierkiewicz | 29dd597 | 2008-02-06 02:57:50 +0100 | [diff] [blame] | 112 |  | 
 | 113 | 	hw->irq = IRQ_AMIGA_PORTS; | 
 | 114 | 	hw->ack_intr = ack_intr; | 
 | 115 | } | 
 | 116 |  | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 117 |     /* | 
 | 118 |      *  Probe for a Gayle IDE interface (and optionally for an IDE doubler) | 
 | 119 |      */ | 
 | 120 |  | 
| Bartlomiej Zolnierkiewicz | ade2daf | 2008-01-26 20:13:07 +0100 | [diff] [blame] | 121 | static int __init gayle_init(void) | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 122 | { | 
 | 123 |     int a4000, i; | 
| Bartlomiej Zolnierkiewicz | 8ac4ce7 | 2008-01-26 20:13:06 +0100 | [diff] [blame] | 124 |     u8 idx[4] = { 0xff, 0xff, 0xff, 0xff }; | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 125 |  | 
 | 126 |     if (!MACH_IS_AMIGA) | 
| Bartlomiej Zolnierkiewicz | ade2daf | 2008-01-26 20:13:07 +0100 | [diff] [blame] | 127 | 	return -ENODEV; | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 128 |  | 
 | 129 |     if ((a4000 = AMIGAHW_PRESENT(A4000_IDE)) || AMIGAHW_PRESENT(A1200_IDE)) | 
 | 130 | 	goto found; | 
 | 131 |  | 
 | 132 | #ifdef CONFIG_ZORRO | 
 | 133 |     if (zorro_find_device(ZORRO_PROD_MTEC_VIPER_MK_V_E_MATRIX_530_SCSI_IDE, | 
 | 134 | 			  NULL)) | 
 | 135 | 	goto found; | 
 | 136 | #endif | 
| Bartlomiej Zolnierkiewicz | ade2daf | 2008-01-26 20:13:07 +0100 | [diff] [blame] | 137 |     return -ENODEV; | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 138 |  | 
 | 139 | found: | 
| Bartlomiej Zolnierkiewicz | c99c92c | 2008-01-26 20:13:09 +0100 | [diff] [blame] | 140 | 	printk(KERN_INFO "ide: Gayle IDE controller (A%d style%s)\n", | 
 | 141 | 			 a4000 ? 4000 : 1200, | 
 | 142 | #ifdef CONFIG_BLK_DEV_IDEDOUBLER | 
 | 143 | 			 ide_doubler ? ", IDE doubler" : | 
 | 144 | #endif | 
 | 145 | 			 ""); | 
 | 146 |  | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 147 |     for (i = 0; i < GAYLE_NUM_PROBE_HWIFS; i++) { | 
 | 148 | 	unsigned long base, ctrlport, irqport; | 
 | 149 | 	ide_ack_intr_t *ack_intr; | 
 | 150 | 	hw_regs_t hw; | 
 | 151 | 	ide_hwif_t *hwif; | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 152 | 	unsigned long phys_base, res_start, res_n; | 
 | 153 |  | 
 | 154 | 	if (a4000) { | 
 | 155 | 	    phys_base = GAYLE_BASE_4000; | 
 | 156 | 	    irqport = (unsigned long)ZTWO_VADDR(GAYLE_IRQ_4000); | 
 | 157 | 	    ack_intr = gayle_ack_intr_a4000; | 
 | 158 | 	} else { | 
 | 159 | 	    phys_base = GAYLE_BASE_1200; | 
 | 160 | 	    irqport = (unsigned long)ZTWO_VADDR(GAYLE_IRQ_1200); | 
 | 161 | 	    ack_intr = gayle_ack_intr_a1200; | 
 | 162 | 	} | 
 | 163 | /* | 
 | 164 |  * FIXME: we now have selectable modes between mmio v/s iomio | 
 | 165 |  */ | 
 | 166 |  | 
 | 167 | 	phys_base += i*GAYLE_NEXT_PORT; | 
 | 168 |  | 
 | 169 | 	res_start = ((unsigned long)phys_base) & ~(GAYLE_NEXT_PORT-1); | 
 | 170 | 	res_n = GAYLE_IDEREG_SIZE; | 
 | 171 |  | 
 | 172 | 	if (!request_mem_region(res_start, res_n, "IDE")) | 
 | 173 | 	    continue; | 
 | 174 |  | 
 | 175 | 	base = (unsigned long)ZTWO_VADDR(phys_base); | 
 | 176 | 	ctrlport = GAYLE_HAS_CONTROL_REG ? (base + GAYLE_CONTROL) : 0; | 
 | 177 |  | 
| Bartlomiej Zolnierkiewicz | 29dd597 | 2008-02-06 02:57:50 +0100 | [diff] [blame] | 178 | 	gayle_setup_ports(&hw, base, ctrlport, irqport, ack_intr); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 179 |  | 
| Bartlomiej Zolnierkiewicz | 59bff5b | 2008-04-26 17:36:32 +0200 | [diff] [blame] | 180 | 	hwif = ide_find_port(); | 
| Bartlomiej Zolnierkiewicz | cbb010c | 2008-01-26 20:13:06 +0100 | [diff] [blame] | 181 | 	if (hwif) { | 
 | 182 | 	    u8 index = hwif->index; | 
 | 183 |  | 
 | 184 | 	    ide_init_port_data(hwif, index); | 
 | 185 | 	    ide_init_port_hw(hwif, &hw); | 
 | 186 |  | 
| Bartlomiej Zolnierkiewicz | 8ac4ce7 | 2008-01-26 20:13:06 +0100 | [diff] [blame] | 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); | 
| Adrian Bunk | 6e1d17d | 2008-04-02 21:22:04 +0200 | [diff] [blame] | 198 |  | 
 | 199 | MODULE_LICENSE("GPL"); |