| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 1 | /* | 
|  | 2 | * linux/drivers/ide/ide-pmac.c | 
|  | 3 | * | 
|  | 4 | * Support for IDE interfaces on PowerMacs. | 
|  | 5 | * These IDE interfaces are memory-mapped and have a DBDMA channel | 
|  | 6 | * for doing DMA. | 
|  | 7 | * | 
|  | 8 | *  Copyright (C) 1998-2003 Paul Mackerras & Ben. Herrenschmidt | 
|  | 9 | * | 
|  | 10 | *  This program is free software; you can redistribute it and/or | 
|  | 11 | *  modify it under the terms of the GNU General Public License | 
|  | 12 | *  as published by the Free Software Foundation; either version | 
|  | 13 | *  2 of the License, or (at your option) any later version. | 
|  | 14 | * | 
|  | 15 | * Some code taken from drivers/ide/ide-dma.c: | 
|  | 16 | * | 
|  | 17 | *  Copyright (c) 1995-1998  Mark Lord | 
|  | 18 | * | 
|  | 19 | * TODO: - Use pre-calculated (kauai) timing tables all the time and | 
|  | 20 | * get rid of the "rounded" tables used previously, so we have the | 
|  | 21 | * same table format for all controllers and can then just have one | 
|  | 22 | * big table | 
|  | 23 | * | 
|  | 24 | */ | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 25 | #include <linux/types.h> | 
|  | 26 | #include <linux/kernel.h> | 
|  | 27 | #include <linux/sched.h> | 
|  | 28 | #include <linux/init.h> | 
|  | 29 | #include <linux/delay.h> | 
|  | 30 | #include <linux/ide.h> | 
|  | 31 | #include <linux/notifier.h> | 
|  | 32 | #include <linux/reboot.h> | 
|  | 33 | #include <linux/pci.h> | 
|  | 34 | #include <linux/adb.h> | 
|  | 35 | #include <linux/pmu.h> | 
|  | 36 | #include <linux/scatterlist.h> | 
|  | 37 |  | 
|  | 38 | #include <asm/prom.h> | 
|  | 39 | #include <asm/io.h> | 
|  | 40 | #include <asm/dbdma.h> | 
|  | 41 | #include <asm/ide.h> | 
|  | 42 | #include <asm/pci-bridge.h> | 
|  | 43 | #include <asm/machdep.h> | 
|  | 44 | #include <asm/pmac_feature.h> | 
|  | 45 | #include <asm/sections.h> | 
|  | 46 | #include <asm/irq.h> | 
|  | 47 |  | 
|  | 48 | #ifndef CONFIG_PPC64 | 
|  | 49 | #include <asm/mediabay.h> | 
|  | 50 | #endif | 
|  | 51 |  | 
|  | 52 | #include "ide-timing.h" | 
|  | 53 |  | 
|  | 54 | #undef IDE_PMAC_DEBUG | 
|  | 55 |  | 
|  | 56 | #define DMA_WAIT_TIMEOUT	50 | 
|  | 57 |  | 
|  | 58 | typedef struct pmac_ide_hwif { | 
|  | 59 | unsigned long			regbase; | 
|  | 60 | int				irq; | 
|  | 61 | int				kind; | 
|  | 62 | int				aapl_bus_id; | 
|  | 63 | unsigned			cable_80 : 1; | 
|  | 64 | unsigned			mediabay : 1; | 
|  | 65 | unsigned			broken_dma : 1; | 
|  | 66 | unsigned			broken_dma_warn : 1; | 
|  | 67 | struct device_node*		node; | 
|  | 68 | struct macio_dev		*mdev; | 
|  | 69 | u32				timings[4]; | 
|  | 70 | volatile u32 __iomem *		*kauai_fcr; | 
|  | 71 | #ifdef CONFIG_BLK_DEV_IDEDMA_PMAC | 
|  | 72 | /* Those fields are duplicating what is in hwif. We currently | 
|  | 73 | * can't use the hwif ones because of some assumptions that are | 
|  | 74 | * beeing done by the generic code about the kind of dma controller | 
|  | 75 | * and format of the dma table. This will have to be fixed though. | 
|  | 76 | */ | 
|  | 77 | volatile struct dbdma_regs __iomem *	dma_regs; | 
|  | 78 | struct dbdma_cmd*		dma_table_cpu; | 
|  | 79 | #endif | 
|  | 80 |  | 
|  | 81 | } pmac_ide_hwif_t; | 
|  | 82 |  | 
| Jon Loeliger | aacaf9b | 2005-09-17 10:36:54 -0500 | [diff] [blame] | 83 | static pmac_ide_hwif_t pmac_ide[MAX_HWIFS]; | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 84 | static int pmac_ide_count; | 
|  | 85 |  | 
|  | 86 | enum { | 
|  | 87 | controller_ohare,	/* OHare based */ | 
|  | 88 | controller_heathrow,	/* Heathrow/Paddington */ | 
|  | 89 | controller_kl_ata3,	/* KeyLargo ATA-3 */ | 
|  | 90 | controller_kl_ata4,	/* KeyLargo ATA-4 */ | 
|  | 91 | controller_un_ata6,	/* UniNorth2 ATA-6 */ | 
|  | 92 | controller_k2_ata6,	/* K2 ATA-6 */ | 
|  | 93 | controller_sh_ata6,	/* Shasta ATA-6 */ | 
|  | 94 | }; | 
|  | 95 |  | 
|  | 96 | static const char* model_name[] = { | 
|  | 97 | "OHare ATA",		/* OHare based */ | 
|  | 98 | "Heathrow ATA",		/* Heathrow/Paddington */ | 
|  | 99 | "KeyLargo ATA-3",	/* KeyLargo ATA-3 (MDMA only) */ | 
|  | 100 | "KeyLargo ATA-4",	/* KeyLargo ATA-4 (UDMA/66) */ | 
|  | 101 | "UniNorth ATA-6",	/* UniNorth2 ATA-6 (UDMA/100) */ | 
|  | 102 | "K2 ATA-6",		/* K2 ATA-6 (UDMA/100) */ | 
|  | 103 | "Shasta ATA-6",		/* Shasta ATA-6 (UDMA/133) */ | 
|  | 104 | }; | 
|  | 105 |  | 
|  | 106 | /* | 
|  | 107 | * Extra registers, both 32-bit little-endian | 
|  | 108 | */ | 
|  | 109 | #define IDE_TIMING_CONFIG	0x200 | 
|  | 110 | #define IDE_INTERRUPT		0x300 | 
|  | 111 |  | 
|  | 112 | /* Kauai (U2) ATA has different register setup */ | 
|  | 113 | #define IDE_KAUAI_PIO_CONFIG	0x200 | 
|  | 114 | #define IDE_KAUAI_ULTRA_CONFIG	0x210 | 
|  | 115 | #define IDE_KAUAI_POLL_CONFIG	0x220 | 
|  | 116 |  | 
|  | 117 | /* | 
|  | 118 | * Timing configuration register definitions | 
|  | 119 | */ | 
|  | 120 |  | 
|  | 121 | /* Number of IDE_SYSCLK_NS ticks, argument is in nanoseconds */ | 
|  | 122 | #define SYSCLK_TICKS(t)		(((t) + IDE_SYSCLK_NS - 1) / IDE_SYSCLK_NS) | 
|  | 123 | #define SYSCLK_TICKS_66(t)	(((t) + IDE_SYSCLK_66_NS - 1) / IDE_SYSCLK_66_NS) | 
|  | 124 | #define IDE_SYSCLK_NS		30	/* 33Mhz cell */ | 
|  | 125 | #define IDE_SYSCLK_66_NS	15	/* 66Mhz cell */ | 
|  | 126 |  | 
|  | 127 | /* 133Mhz cell, found in shasta. | 
|  | 128 | * See comments about 100 Mhz Uninorth 2... | 
|  | 129 | * Note that PIO_MASK and MDMA_MASK seem to overlap | 
|  | 130 | */ | 
|  | 131 | #define TR_133_PIOREG_PIO_MASK		0xff000fff | 
|  | 132 | #define TR_133_PIOREG_MDMA_MASK		0x00fff800 | 
|  | 133 | #define TR_133_UDMAREG_UDMA_MASK	0x0003ffff | 
|  | 134 | #define TR_133_UDMAREG_UDMA_EN		0x00000001 | 
|  | 135 |  | 
|  | 136 | /* 100Mhz cell, found in Uninorth 2. I don't have much infos about | 
|  | 137 | * this one yet, it appears as a pci device (106b/0033) on uninorth | 
|  | 138 | * internal PCI bus and it's clock is controlled like gem or fw. It | 
|  | 139 | * appears to be an evolution of keylargo ATA4 with a timing register | 
|  | 140 | * extended to 2 32bits registers and a similar DBDMA channel. Other | 
|  | 141 | * registers seem to exist but I can't tell much about them. | 
|  | 142 | * | 
|  | 143 | * So far, I'm using pre-calculated tables for this extracted from | 
|  | 144 | * the values used by the MacOS X driver. | 
|  | 145 | * | 
|  | 146 | * The "PIO" register controls PIO and MDMA timings, the "ULTRA" | 
|  | 147 | * register controls the UDMA timings. At least, it seems bit 0 | 
|  | 148 | * of this one enables UDMA vs. MDMA, and bits 4..7 are the | 
|  | 149 | * cycle time in units of 10ns. Bits 8..15 are used by I don't | 
|  | 150 | * know their meaning yet | 
|  | 151 | */ | 
|  | 152 | #define TR_100_PIOREG_PIO_MASK		0xff000fff | 
|  | 153 | #define TR_100_PIOREG_MDMA_MASK		0x00fff000 | 
|  | 154 | #define TR_100_UDMAREG_UDMA_MASK	0x0000ffff | 
|  | 155 | #define TR_100_UDMAREG_UDMA_EN		0x00000001 | 
|  | 156 |  | 
|  | 157 |  | 
|  | 158 | /* 66Mhz cell, found in KeyLargo. Can do ultra mode 0 to 2 on | 
|  | 159 | * 40 connector cable and to 4 on 80 connector one. | 
|  | 160 | * Clock unit is 15ns (66Mhz) | 
|  | 161 | * | 
|  | 162 | * 3 Values can be programmed: | 
|  | 163 | *  - Write data setup, which appears to match the cycle time. They | 
|  | 164 | *    also call it DIOW setup. | 
|  | 165 | *  - Ready to pause time (from spec) | 
|  | 166 | *  - Address setup. That one is weird. I don't see where exactly | 
|  | 167 | *    it fits in UDMA cycles, I got it's name from an obscure piece | 
|  | 168 | *    of commented out code in Darwin. They leave it to 0, we do as | 
|  | 169 | *    well, despite a comment that would lead to think it has a | 
|  | 170 | *    min value of 45ns. | 
|  | 171 | * Apple also add 60ns to the write data setup (or cycle time ?) on | 
|  | 172 | * reads. | 
|  | 173 | */ | 
|  | 174 | #define TR_66_UDMA_MASK			0xfff00000 | 
|  | 175 | #define TR_66_UDMA_EN			0x00100000 /* Enable Ultra mode for DMA */ | 
|  | 176 | #define TR_66_UDMA_ADDRSETUP_MASK	0xe0000000 /* Address setup */ | 
|  | 177 | #define TR_66_UDMA_ADDRSETUP_SHIFT	29 | 
|  | 178 | #define TR_66_UDMA_RDY2PAUS_MASK	0x1e000000 /* Ready 2 pause time */ | 
|  | 179 | #define TR_66_UDMA_RDY2PAUS_SHIFT	25 | 
|  | 180 | #define TR_66_UDMA_WRDATASETUP_MASK	0x01e00000 /* Write data setup time */ | 
|  | 181 | #define TR_66_UDMA_WRDATASETUP_SHIFT	21 | 
|  | 182 | #define TR_66_MDMA_MASK			0x000ffc00 | 
|  | 183 | #define TR_66_MDMA_RECOVERY_MASK	0x000f8000 | 
|  | 184 | #define TR_66_MDMA_RECOVERY_SHIFT	15 | 
|  | 185 | #define TR_66_MDMA_ACCESS_MASK		0x00007c00 | 
|  | 186 | #define TR_66_MDMA_ACCESS_SHIFT		10 | 
|  | 187 | #define TR_66_PIO_MASK			0x000003ff | 
|  | 188 | #define TR_66_PIO_RECOVERY_MASK		0x000003e0 | 
|  | 189 | #define TR_66_PIO_RECOVERY_SHIFT	5 | 
|  | 190 | #define TR_66_PIO_ACCESS_MASK		0x0000001f | 
|  | 191 | #define TR_66_PIO_ACCESS_SHIFT		0 | 
|  | 192 |  | 
|  | 193 | /* 33Mhz cell, found in OHare, Heathrow (& Paddington) and KeyLargo | 
|  | 194 | * Can do pio & mdma modes, clock unit is 30ns (33Mhz) | 
|  | 195 | * | 
|  | 196 | * The access time and recovery time can be programmed. Some older | 
|  | 197 | * Darwin code base limit OHare to 150ns cycle time. I decided to do | 
|  | 198 | * the same here fore safety against broken old hardware ;) | 
|  | 199 | * The HalfTick bit, when set, adds half a clock (15ns) to the access | 
|  | 200 | * time and removes one from recovery. It's not supported on KeyLargo | 
|  | 201 | * implementation afaik. The E bit appears to be set for PIO mode 0 and | 
|  | 202 | * is used to reach long timings used in this mode. | 
|  | 203 | */ | 
|  | 204 | #define TR_33_MDMA_MASK			0x003ff800 | 
|  | 205 | #define TR_33_MDMA_RECOVERY_MASK	0x001f0000 | 
|  | 206 | #define TR_33_MDMA_RECOVERY_SHIFT	16 | 
|  | 207 | #define TR_33_MDMA_ACCESS_MASK		0x0000f800 | 
|  | 208 | #define TR_33_MDMA_ACCESS_SHIFT		11 | 
|  | 209 | #define TR_33_MDMA_HALFTICK		0x00200000 | 
|  | 210 | #define TR_33_PIO_MASK			0x000007ff | 
|  | 211 | #define TR_33_PIO_E			0x00000400 | 
|  | 212 | #define TR_33_PIO_RECOVERY_MASK		0x000003e0 | 
|  | 213 | #define TR_33_PIO_RECOVERY_SHIFT	5 | 
|  | 214 | #define TR_33_PIO_ACCESS_MASK		0x0000001f | 
|  | 215 | #define TR_33_PIO_ACCESS_SHIFT		0 | 
|  | 216 |  | 
|  | 217 | /* | 
|  | 218 | * Interrupt register definitions | 
|  | 219 | */ | 
|  | 220 | #define IDE_INTR_DMA			0x80000000 | 
|  | 221 | #define IDE_INTR_DEVICE			0x40000000 | 
|  | 222 |  | 
|  | 223 | /* | 
|  | 224 | * FCR Register on Kauai. Not sure what bit 0x4 is  ... | 
|  | 225 | */ | 
|  | 226 | #define KAUAI_FCR_UATA_MAGIC		0x00000004 | 
|  | 227 | #define KAUAI_FCR_UATA_RESET_N		0x00000002 | 
|  | 228 | #define KAUAI_FCR_UATA_ENABLE		0x00000001 | 
|  | 229 |  | 
|  | 230 | #ifdef CONFIG_BLK_DEV_IDEDMA_PMAC | 
|  | 231 |  | 
|  | 232 | /* Rounded Multiword DMA timings | 
|  | 233 | * | 
|  | 234 | * I gave up finding a generic formula for all controller | 
|  | 235 | * types and instead, built tables based on timing values | 
|  | 236 | * used by Apple in Darwin's implementation. | 
|  | 237 | */ | 
|  | 238 | struct mdma_timings_t { | 
|  | 239 | int	accessTime; | 
|  | 240 | int	recoveryTime; | 
|  | 241 | int	cycleTime; | 
|  | 242 | }; | 
|  | 243 |  | 
| Jon Loeliger | aacaf9b | 2005-09-17 10:36:54 -0500 | [diff] [blame] | 244 | struct mdma_timings_t mdma_timings_33[] = | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 245 | { | 
|  | 246 | { 240, 240, 480 }, | 
|  | 247 | { 180, 180, 360 }, | 
|  | 248 | { 135, 135, 270 }, | 
|  | 249 | { 120, 120, 240 }, | 
|  | 250 | { 105, 105, 210 }, | 
|  | 251 | {  90,  90, 180 }, | 
|  | 252 | {  75,  75, 150 }, | 
|  | 253 | {  75,  45, 120 }, | 
|  | 254 | {   0,   0,   0 } | 
|  | 255 | }; | 
|  | 256 |  | 
| Jon Loeliger | aacaf9b | 2005-09-17 10:36:54 -0500 | [diff] [blame] | 257 | struct mdma_timings_t mdma_timings_33k[] = | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 258 | { | 
|  | 259 | { 240, 240, 480 }, | 
|  | 260 | { 180, 180, 360 }, | 
|  | 261 | { 150, 150, 300 }, | 
|  | 262 | { 120, 120, 240 }, | 
|  | 263 | {  90, 120, 210 }, | 
|  | 264 | {  90,  90, 180 }, | 
|  | 265 | {  90,  60, 150 }, | 
|  | 266 | {  90,  30, 120 }, | 
|  | 267 | {   0,   0,   0 } | 
|  | 268 | }; | 
|  | 269 |  | 
| Jon Loeliger | aacaf9b | 2005-09-17 10:36:54 -0500 | [diff] [blame] | 270 | struct mdma_timings_t mdma_timings_66[] = | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 271 | { | 
|  | 272 | { 240, 240, 480 }, | 
|  | 273 | { 180, 180, 360 }, | 
|  | 274 | { 135, 135, 270 }, | 
|  | 275 | { 120, 120, 240 }, | 
|  | 276 | { 105, 105, 210 }, | 
|  | 277 | {  90,  90, 180 }, | 
|  | 278 | {  90,  75, 165 }, | 
|  | 279 | {  75,  45, 120 }, | 
|  | 280 | {   0,   0,   0 } | 
|  | 281 | }; | 
|  | 282 |  | 
|  | 283 | /* KeyLargo ATA-4 Ultra DMA timings (rounded) */ | 
|  | 284 | struct { | 
|  | 285 | int	addrSetup; /* ??? */ | 
|  | 286 | int	rdy2pause; | 
|  | 287 | int	wrDataSetup; | 
| Jon Loeliger | aacaf9b | 2005-09-17 10:36:54 -0500 | [diff] [blame] | 288 | } kl66_udma_timings[] = | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 289 | { | 
|  | 290 | {   0, 180,  120 },	/* Mode 0 */ | 
|  | 291 | {   0, 150,  90 },	/*      1 */ | 
|  | 292 | {   0, 120,  60 },	/*      2 */ | 
|  | 293 | {   0, 90,   45 },	/*      3 */ | 
|  | 294 | {   0, 90,   30 }	/*      4 */ | 
|  | 295 | }; | 
|  | 296 |  | 
|  | 297 | /* UniNorth 2 ATA/100 timings */ | 
|  | 298 | struct kauai_timing { | 
|  | 299 | int	cycle_time; | 
|  | 300 | u32	timing_reg; | 
|  | 301 | }; | 
|  | 302 |  | 
| Jon Loeliger | aacaf9b | 2005-09-17 10:36:54 -0500 | [diff] [blame] | 303 | static struct kauai_timing	kauai_pio_timings[] = | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 304 | { | 
|  | 305 | { 930	, 0x08000fff }, | 
|  | 306 | { 600	, 0x08000a92 }, | 
|  | 307 | { 383	, 0x0800060f }, | 
|  | 308 | { 360	, 0x08000492 }, | 
|  | 309 | { 330	, 0x0800048f }, | 
|  | 310 | { 300	, 0x080003cf }, | 
|  | 311 | { 270	, 0x080003cc }, | 
|  | 312 | { 240	, 0x0800038b }, | 
|  | 313 | { 239	, 0x0800030c }, | 
|  | 314 | { 180	, 0x05000249 }, | 
|  | 315 | { 120	, 0x04000148 } | 
|  | 316 | }; | 
|  | 317 |  | 
| Jon Loeliger | aacaf9b | 2005-09-17 10:36:54 -0500 | [diff] [blame] | 318 | static struct kauai_timing	kauai_mdma_timings[] = | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 319 | { | 
|  | 320 | { 1260	, 0x00fff000 }, | 
|  | 321 | { 480	, 0x00618000 }, | 
|  | 322 | { 360	, 0x00492000 }, | 
|  | 323 | { 270	, 0x0038e000 }, | 
|  | 324 | { 240	, 0x0030c000 }, | 
|  | 325 | { 210	, 0x002cb000 }, | 
|  | 326 | { 180	, 0x00249000 }, | 
|  | 327 | { 150	, 0x00209000 }, | 
|  | 328 | { 120	, 0x00148000 }, | 
|  | 329 | { 0	, 0 }, | 
|  | 330 | }; | 
|  | 331 |  | 
| Jon Loeliger | aacaf9b | 2005-09-17 10:36:54 -0500 | [diff] [blame] | 332 | static struct kauai_timing	kauai_udma_timings[] = | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 333 | { | 
|  | 334 | { 120	, 0x000070c0 }, | 
|  | 335 | { 90	, 0x00005d80 }, | 
|  | 336 | { 60	, 0x00004a60 }, | 
|  | 337 | { 45	, 0x00003a50 }, | 
|  | 338 | { 30	, 0x00002a30 }, | 
|  | 339 | { 20	, 0x00002921 }, | 
|  | 340 | { 0	, 0 }, | 
|  | 341 | }; | 
|  | 342 |  | 
| Jon Loeliger | aacaf9b | 2005-09-17 10:36:54 -0500 | [diff] [blame] | 343 | static struct kauai_timing	shasta_pio_timings[] = | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 344 | { | 
|  | 345 | { 930	, 0x08000fff }, | 
|  | 346 | { 600	, 0x0A000c97 }, | 
|  | 347 | { 383	, 0x07000712 }, | 
|  | 348 | { 360	, 0x040003cd }, | 
|  | 349 | { 330	, 0x040003cd }, | 
|  | 350 | { 300	, 0x040003cd }, | 
|  | 351 | { 270	, 0x040003cd }, | 
|  | 352 | { 240	, 0x040003cd }, | 
|  | 353 | { 239	, 0x040003cd }, | 
|  | 354 | { 180	, 0x0400028b }, | 
|  | 355 | { 120	, 0x0400010a } | 
|  | 356 | }; | 
|  | 357 |  | 
| Jon Loeliger | aacaf9b | 2005-09-17 10:36:54 -0500 | [diff] [blame] | 358 | static struct kauai_timing	shasta_mdma_timings[] = | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 359 | { | 
|  | 360 | { 1260	, 0x00fff000 }, | 
|  | 361 | { 480	, 0x00820800 }, | 
|  | 362 | { 360	, 0x00820800 }, | 
|  | 363 | { 270	, 0x00820800 }, | 
|  | 364 | { 240	, 0x00820800 }, | 
|  | 365 | { 210	, 0x00820800 }, | 
|  | 366 | { 180	, 0x00820800 }, | 
|  | 367 | { 150	, 0x0028b000 }, | 
|  | 368 | { 120	, 0x001ca000 }, | 
|  | 369 | { 0	, 0 }, | 
|  | 370 | }; | 
|  | 371 |  | 
| Jon Loeliger | aacaf9b | 2005-09-17 10:36:54 -0500 | [diff] [blame] | 372 | static struct kauai_timing	shasta_udma133_timings[] = | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 373 | { | 
|  | 374 | { 120   , 0x00035901, }, | 
|  | 375 | { 90    , 0x000348b1, }, | 
|  | 376 | { 60    , 0x00033881, }, | 
|  | 377 | { 45    , 0x00033861, }, | 
|  | 378 | { 30    , 0x00033841, }, | 
|  | 379 | { 20    , 0x00033031, }, | 
|  | 380 | { 15    , 0x00033021, }, | 
|  | 381 | { 0	, 0 }, | 
|  | 382 | }; | 
|  | 383 |  | 
|  | 384 |  | 
|  | 385 | static inline u32 | 
|  | 386 | kauai_lookup_timing(struct kauai_timing* table, int cycle_time) | 
|  | 387 | { | 
|  | 388 | int i; | 
|  | 389 |  | 
|  | 390 | for (i=0; table[i].cycle_time; i++) | 
|  | 391 | if (cycle_time > table[i+1].cycle_time) | 
|  | 392 | return table[i].timing_reg; | 
|  | 393 | return 0; | 
|  | 394 | } | 
|  | 395 |  | 
|  | 396 | /* allow up to 256 DBDMA commands per xfer */ | 
|  | 397 | #define MAX_DCMDS		256 | 
|  | 398 |  | 
|  | 399 | /* | 
|  | 400 | * Wait 1s for disk to answer on IDE bus after a hard reset | 
|  | 401 | * of the device (via GPIO/FCR). | 
|  | 402 | * | 
|  | 403 | * Some devices seem to "pollute" the bus even after dropping | 
|  | 404 | * the BSY bit (typically some combo drives slave on the UDMA | 
|  | 405 | * bus) after a hard reset. Since we hard reset all drives on | 
|  | 406 | * KeyLargo ATA66, we have to keep that delay around. I may end | 
|  | 407 | * up not hard resetting anymore on these and keep the delay only | 
|  | 408 | * for older interfaces instead (we have to reset when coming | 
|  | 409 | * from MacOS...) --BenH. | 
|  | 410 | */ | 
|  | 411 | #define IDE_WAKEUP_DELAY	(1*HZ) | 
|  | 412 |  | 
|  | 413 | static void pmac_ide_setup_dma(pmac_ide_hwif_t *pmif, ide_hwif_t *hwif); | 
|  | 414 | static int pmac_ide_build_dmatable(ide_drive_t *drive, struct request *rq); | 
|  | 415 | static int pmac_ide_tune_chipset(ide_drive_t *drive, u8 speed); | 
|  | 416 | static void pmac_ide_tuneproc(ide_drive_t *drive, u8 pio); | 
|  | 417 | static void pmac_ide_selectproc(ide_drive_t *drive); | 
|  | 418 | static void pmac_ide_kauai_selectproc(ide_drive_t *drive); | 
|  | 419 |  | 
|  | 420 | #endif /* CONFIG_BLK_DEV_IDEDMA_PMAC */ | 
|  | 421 |  | 
|  | 422 | /* | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 423 | * N.B. this can't be an initfunc, because the media-bay task can | 
|  | 424 | * call ide_[un]register at any time. | 
|  | 425 | */ | 
| Jon Loeliger | aacaf9b | 2005-09-17 10:36:54 -0500 | [diff] [blame] | 426 | void | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 427 | pmac_ide_init_hwif_ports(hw_regs_t *hw, | 
|  | 428 | unsigned long data_port, unsigned long ctrl_port, | 
|  | 429 | int *irq) | 
|  | 430 | { | 
|  | 431 | int i, ix; | 
|  | 432 |  | 
|  | 433 | if (data_port == 0) | 
|  | 434 | return; | 
|  | 435 |  | 
|  | 436 | for (ix = 0; ix < MAX_HWIFS; ++ix) | 
|  | 437 | if (data_port == pmac_ide[ix].regbase) | 
|  | 438 | break; | 
|  | 439 |  | 
|  | 440 | if (ix >= MAX_HWIFS) { | 
|  | 441 | /* Probably a PCI interface... */ | 
|  | 442 | for (i = IDE_DATA_OFFSET; i <= IDE_STATUS_OFFSET; ++i) | 
|  | 443 | hw->io_ports[i] = data_port + i - IDE_DATA_OFFSET; | 
|  | 444 | hw->io_ports[IDE_CONTROL_OFFSET] = ctrl_port; | 
|  | 445 | return; | 
|  | 446 | } | 
|  | 447 |  | 
|  | 448 | for (i = 0; i < 8; ++i) | 
|  | 449 | hw->io_ports[i] = data_port + i * 0x10; | 
|  | 450 | hw->io_ports[8] = data_port + 0x160; | 
|  | 451 |  | 
|  | 452 | if (irq != NULL) | 
|  | 453 | *irq = pmac_ide[ix].irq; | 
| Benjamin Herrenschmidt | 22192cc | 2006-05-20 14:59:53 -0700 | [diff] [blame] | 454 |  | 
|  | 455 | hw->dev = &pmac_ide[ix].mdev->ofdev.dev; | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 456 | } | 
|  | 457 |  | 
|  | 458 | #define PMAC_IDE_REG(x) ((void __iomem *)(IDE_DATA_REG+(x))) | 
|  | 459 |  | 
|  | 460 | /* | 
|  | 461 | * Apply the timings of the proper unit (master/slave) to the shared | 
|  | 462 | * timing register when selecting that unit. This version is for | 
|  | 463 | * ASICs with a single timing register | 
|  | 464 | */ | 
| Jon Loeliger | aacaf9b | 2005-09-17 10:36:54 -0500 | [diff] [blame] | 465 | static void | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 466 | pmac_ide_selectproc(ide_drive_t *drive) | 
|  | 467 | { | 
|  | 468 | pmac_ide_hwif_t* pmif = (pmac_ide_hwif_t *)HWIF(drive)->hwif_data; | 
|  | 469 |  | 
|  | 470 | if (pmif == NULL) | 
|  | 471 | return; | 
|  | 472 |  | 
|  | 473 | if (drive->select.b.unit & 0x01) | 
|  | 474 | writel(pmif->timings[1], PMAC_IDE_REG(IDE_TIMING_CONFIG)); | 
|  | 475 | else | 
|  | 476 | writel(pmif->timings[0], PMAC_IDE_REG(IDE_TIMING_CONFIG)); | 
|  | 477 | (void)readl(PMAC_IDE_REG(IDE_TIMING_CONFIG)); | 
|  | 478 | } | 
|  | 479 |  | 
|  | 480 | /* | 
|  | 481 | * Apply the timings of the proper unit (master/slave) to the shared | 
|  | 482 | * timing register when selecting that unit. This version is for | 
|  | 483 | * ASICs with a dual timing register (Kauai) | 
|  | 484 | */ | 
| Jon Loeliger | aacaf9b | 2005-09-17 10:36:54 -0500 | [diff] [blame] | 485 | static void | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 486 | pmac_ide_kauai_selectproc(ide_drive_t *drive) | 
|  | 487 | { | 
|  | 488 | pmac_ide_hwif_t* pmif = (pmac_ide_hwif_t *)HWIF(drive)->hwif_data; | 
|  | 489 |  | 
|  | 490 | if (pmif == NULL) | 
|  | 491 | return; | 
|  | 492 |  | 
|  | 493 | if (drive->select.b.unit & 0x01) { | 
|  | 494 | writel(pmif->timings[1], PMAC_IDE_REG(IDE_KAUAI_PIO_CONFIG)); | 
|  | 495 | writel(pmif->timings[3], PMAC_IDE_REG(IDE_KAUAI_ULTRA_CONFIG)); | 
|  | 496 | } else { | 
|  | 497 | writel(pmif->timings[0], PMAC_IDE_REG(IDE_KAUAI_PIO_CONFIG)); | 
|  | 498 | writel(pmif->timings[2], PMAC_IDE_REG(IDE_KAUAI_ULTRA_CONFIG)); | 
|  | 499 | } | 
|  | 500 | (void)readl(PMAC_IDE_REG(IDE_KAUAI_PIO_CONFIG)); | 
|  | 501 | } | 
|  | 502 |  | 
|  | 503 | /* | 
|  | 504 | * Force an update of controller timing values for a given drive | 
|  | 505 | */ | 
| Jon Loeliger | aacaf9b | 2005-09-17 10:36:54 -0500 | [diff] [blame] | 506 | static void | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 507 | pmac_ide_do_update_timings(ide_drive_t *drive) | 
|  | 508 | { | 
|  | 509 | pmac_ide_hwif_t* pmif = (pmac_ide_hwif_t *)HWIF(drive)->hwif_data; | 
|  | 510 |  | 
|  | 511 | if (pmif == NULL) | 
|  | 512 | return; | 
|  | 513 |  | 
|  | 514 | if (pmif->kind == controller_sh_ata6 || | 
|  | 515 | pmif->kind == controller_un_ata6 || | 
|  | 516 | pmif->kind == controller_k2_ata6) | 
|  | 517 | pmac_ide_kauai_selectproc(drive); | 
|  | 518 | else | 
|  | 519 | pmac_ide_selectproc(drive); | 
|  | 520 | } | 
|  | 521 |  | 
|  | 522 | static void | 
|  | 523 | pmac_outbsync(ide_drive_t *drive, u8 value, unsigned long port) | 
|  | 524 | { | 
|  | 525 | u32 tmp; | 
|  | 526 |  | 
|  | 527 | writeb(value, (void __iomem *) port); | 
|  | 528 | tmp = readl(PMAC_IDE_REG(IDE_TIMING_CONFIG)); | 
|  | 529 | } | 
|  | 530 |  | 
|  | 531 | /* | 
|  | 532 | * Send the SET_FEATURE IDE command to the drive and update drive->id with | 
|  | 533 | * the new state. We currently don't use the generic routine as it used to | 
|  | 534 | * cause various trouble, especially with older mediabays. | 
|  | 535 | * This code is sometimes triggering a spurrious interrupt though, I need | 
|  | 536 | * to sort that out sooner or later and see if I can finally get the | 
|  | 537 | * common version to work properly in all cases | 
|  | 538 | */ | 
| Jon Loeliger | aacaf9b | 2005-09-17 10:36:54 -0500 | [diff] [blame] | 539 | static int | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 540 | pmac_ide_do_setfeature(ide_drive_t *drive, u8 command) | 
|  | 541 | { | 
|  | 542 | ide_hwif_t *hwif = HWIF(drive); | 
|  | 543 | int result = 1; | 
|  | 544 |  | 
|  | 545 | disable_irq_nosync(hwif->irq); | 
|  | 546 | udelay(1); | 
|  | 547 | SELECT_DRIVE(drive); | 
|  | 548 | SELECT_MASK(drive, 0); | 
|  | 549 | udelay(1); | 
|  | 550 | /* Get rid of pending error state */ | 
|  | 551 | (void) hwif->INB(IDE_STATUS_REG); | 
|  | 552 | /* Timeout bumped for some powerbooks */ | 
|  | 553 | if (wait_for_ready(drive, 2000)) { | 
|  | 554 | /* Timeout bumped for some powerbooks */ | 
|  | 555 | printk(KERN_ERR "%s: pmac_ide_do_setfeature disk not ready " | 
|  | 556 | "before SET_FEATURE!\n", drive->name); | 
|  | 557 | goto out; | 
|  | 558 | } | 
|  | 559 | udelay(10); | 
|  | 560 | hwif->OUTB(drive->ctl | 2, IDE_CONTROL_REG); | 
|  | 561 | hwif->OUTB(command, IDE_NSECTOR_REG); | 
|  | 562 | hwif->OUTB(SETFEATURES_XFER, IDE_FEATURE_REG); | 
|  | 563 | hwif->OUTBSYNC(drive, WIN_SETFEATURES, IDE_COMMAND_REG); | 
|  | 564 | udelay(1); | 
|  | 565 | /* Timeout bumped for some powerbooks */ | 
|  | 566 | result = wait_for_ready(drive, 2000); | 
|  | 567 | hwif->OUTB(drive->ctl, IDE_CONTROL_REG); | 
|  | 568 | if (result) | 
|  | 569 | printk(KERN_ERR "%s: pmac_ide_do_setfeature disk not ready " | 
|  | 570 | "after SET_FEATURE !\n", drive->name); | 
|  | 571 | out: | 
|  | 572 | SELECT_MASK(drive, 0); | 
|  | 573 | if (result == 0) { | 
|  | 574 | drive->id->dma_ultra &= ~0xFF00; | 
|  | 575 | drive->id->dma_mword &= ~0x0F00; | 
|  | 576 | drive->id->dma_1word &= ~0x0F00; | 
|  | 577 | switch(command) { | 
|  | 578 | case XFER_UDMA_7: | 
|  | 579 | drive->id->dma_ultra |= 0x8080; break; | 
|  | 580 | case XFER_UDMA_6: | 
|  | 581 | drive->id->dma_ultra |= 0x4040; break; | 
|  | 582 | case XFER_UDMA_5: | 
|  | 583 | drive->id->dma_ultra |= 0x2020; break; | 
|  | 584 | case XFER_UDMA_4: | 
|  | 585 | drive->id->dma_ultra |= 0x1010; break; | 
|  | 586 | case XFER_UDMA_3: | 
|  | 587 | drive->id->dma_ultra |= 0x0808; break; | 
|  | 588 | case XFER_UDMA_2: | 
|  | 589 | drive->id->dma_ultra |= 0x0404; break; | 
|  | 590 | case XFER_UDMA_1: | 
|  | 591 | drive->id->dma_ultra |= 0x0202; break; | 
|  | 592 | case XFER_UDMA_0: | 
|  | 593 | drive->id->dma_ultra |= 0x0101; break; | 
|  | 594 | case XFER_MW_DMA_2: | 
|  | 595 | drive->id->dma_mword |= 0x0404; break; | 
|  | 596 | case XFER_MW_DMA_1: | 
|  | 597 | drive->id->dma_mword |= 0x0202; break; | 
|  | 598 | case XFER_MW_DMA_0: | 
|  | 599 | drive->id->dma_mword |= 0x0101; break; | 
|  | 600 | case XFER_SW_DMA_2: | 
|  | 601 | drive->id->dma_1word |= 0x0404; break; | 
|  | 602 | case XFER_SW_DMA_1: | 
|  | 603 | drive->id->dma_1word |= 0x0202; break; | 
|  | 604 | case XFER_SW_DMA_0: | 
|  | 605 | drive->id->dma_1word |= 0x0101; break; | 
|  | 606 | default: break; | 
|  | 607 | } | 
|  | 608 | } | 
|  | 609 | enable_irq(hwif->irq); | 
|  | 610 | return result; | 
|  | 611 | } | 
|  | 612 |  | 
|  | 613 | /* | 
|  | 614 | * Old tuning functions (called on hdparm -p), sets up drive PIO timings | 
|  | 615 | */ | 
| Jon Loeliger | aacaf9b | 2005-09-17 10:36:54 -0500 | [diff] [blame] | 616 | static void | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 617 | pmac_ide_tuneproc(ide_drive_t *drive, u8 pio) | 
|  | 618 | { | 
|  | 619 | ide_pio_data_t d; | 
|  | 620 | u32 *timings; | 
|  | 621 | unsigned accessTicks, recTicks; | 
|  | 622 | unsigned accessTime, recTime; | 
|  | 623 | pmac_ide_hwif_t* pmif = (pmac_ide_hwif_t *)HWIF(drive)->hwif_data; | 
|  | 624 |  | 
|  | 625 | if (pmif == NULL) | 
|  | 626 | return; | 
|  | 627 |  | 
|  | 628 | /* which drive is it ? */ | 
|  | 629 | timings = &pmif->timings[drive->select.b.unit & 0x01]; | 
|  | 630 |  | 
|  | 631 | pio = ide_get_best_pio_mode(drive, pio, 4, &d); | 
|  | 632 |  | 
|  | 633 | switch (pmif->kind) { | 
|  | 634 | case controller_sh_ata6: { | 
|  | 635 | /* 133Mhz cell */ | 
|  | 636 | u32 tr = kauai_lookup_timing(shasta_pio_timings, d.cycle_time); | 
|  | 637 | if (tr == 0) | 
|  | 638 | return; | 
|  | 639 | *timings = ((*timings) & ~TR_133_PIOREG_PIO_MASK) | tr; | 
|  | 640 | break; | 
|  | 641 | } | 
|  | 642 | case controller_un_ata6: | 
|  | 643 | case controller_k2_ata6: { | 
|  | 644 | /* 100Mhz cell */ | 
|  | 645 | u32 tr = kauai_lookup_timing(kauai_pio_timings, d.cycle_time); | 
|  | 646 | if (tr == 0) | 
|  | 647 | return; | 
|  | 648 | *timings = ((*timings) & ~TR_100_PIOREG_PIO_MASK) | tr; | 
|  | 649 | break; | 
|  | 650 | } | 
|  | 651 | case controller_kl_ata4: | 
|  | 652 | /* 66Mhz cell */ | 
|  | 653 | recTime = d.cycle_time - ide_pio_timings[pio].active_time | 
|  | 654 | - ide_pio_timings[pio].setup_time; | 
|  | 655 | recTime = max(recTime, 150U); | 
|  | 656 | accessTime = ide_pio_timings[pio].active_time; | 
|  | 657 | accessTime = max(accessTime, 150U); | 
|  | 658 | accessTicks = SYSCLK_TICKS_66(accessTime); | 
|  | 659 | accessTicks = min(accessTicks, 0x1fU); | 
|  | 660 | recTicks = SYSCLK_TICKS_66(recTime); | 
|  | 661 | recTicks = min(recTicks, 0x1fU); | 
|  | 662 | *timings = ((*timings) & ~TR_66_PIO_MASK) | | 
|  | 663 | (accessTicks << TR_66_PIO_ACCESS_SHIFT) | | 
|  | 664 | (recTicks << TR_66_PIO_RECOVERY_SHIFT); | 
|  | 665 | break; | 
|  | 666 | default: { | 
|  | 667 | /* 33Mhz cell */ | 
|  | 668 | int ebit = 0; | 
|  | 669 | recTime = d.cycle_time - ide_pio_timings[pio].active_time | 
|  | 670 | - ide_pio_timings[pio].setup_time; | 
|  | 671 | recTime = max(recTime, 150U); | 
|  | 672 | accessTime = ide_pio_timings[pio].active_time; | 
|  | 673 | accessTime = max(accessTime, 150U); | 
|  | 674 | accessTicks = SYSCLK_TICKS(accessTime); | 
|  | 675 | accessTicks = min(accessTicks, 0x1fU); | 
|  | 676 | accessTicks = max(accessTicks, 4U); | 
|  | 677 | recTicks = SYSCLK_TICKS(recTime); | 
|  | 678 | recTicks = min(recTicks, 0x1fU); | 
|  | 679 | recTicks = max(recTicks, 5U) - 4; | 
|  | 680 | if (recTicks > 9) { | 
|  | 681 | recTicks--; /* guess, but it's only for PIO0, so... */ | 
|  | 682 | ebit = 1; | 
|  | 683 | } | 
|  | 684 | *timings = ((*timings) & ~TR_33_PIO_MASK) | | 
|  | 685 | (accessTicks << TR_33_PIO_ACCESS_SHIFT) | | 
|  | 686 | (recTicks << TR_33_PIO_RECOVERY_SHIFT); | 
|  | 687 | if (ebit) | 
|  | 688 | *timings |= TR_33_PIO_E; | 
|  | 689 | break; | 
|  | 690 | } | 
|  | 691 | } | 
|  | 692 |  | 
|  | 693 | #ifdef IDE_PMAC_DEBUG | 
|  | 694 | printk(KERN_ERR "%s: Set PIO timing for mode %d, reg: 0x%08x\n", | 
|  | 695 | drive->name, pio,  *timings); | 
|  | 696 | #endif | 
|  | 697 |  | 
|  | 698 | if (drive->select.all == HWIF(drive)->INB(IDE_SELECT_REG)) | 
|  | 699 | pmac_ide_do_update_timings(drive); | 
|  | 700 | } | 
|  | 701 |  | 
|  | 702 | #ifdef CONFIG_BLK_DEV_IDEDMA_PMAC | 
|  | 703 |  | 
|  | 704 | /* | 
|  | 705 | * Calculate KeyLargo ATA/66 UDMA timings | 
|  | 706 | */ | 
| Jon Loeliger | aacaf9b | 2005-09-17 10:36:54 -0500 | [diff] [blame] | 707 | static int | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 708 | set_timings_udma_ata4(u32 *timings, u8 speed) | 
|  | 709 | { | 
|  | 710 | unsigned rdyToPauseTicks, wrDataSetupTicks, addrTicks; | 
|  | 711 |  | 
|  | 712 | if (speed > XFER_UDMA_4) | 
|  | 713 | return 1; | 
|  | 714 |  | 
|  | 715 | rdyToPauseTicks = SYSCLK_TICKS_66(kl66_udma_timings[speed & 0xf].rdy2pause); | 
|  | 716 | wrDataSetupTicks = SYSCLK_TICKS_66(kl66_udma_timings[speed & 0xf].wrDataSetup); | 
|  | 717 | addrTicks = SYSCLK_TICKS_66(kl66_udma_timings[speed & 0xf].addrSetup); | 
|  | 718 |  | 
|  | 719 | *timings = ((*timings) & ~(TR_66_UDMA_MASK | TR_66_MDMA_MASK)) | | 
|  | 720 | (wrDataSetupTicks << TR_66_UDMA_WRDATASETUP_SHIFT) | | 
|  | 721 | (rdyToPauseTicks << TR_66_UDMA_RDY2PAUS_SHIFT) | | 
|  | 722 | (addrTicks <<TR_66_UDMA_ADDRSETUP_SHIFT) | | 
|  | 723 | TR_66_UDMA_EN; | 
|  | 724 | #ifdef IDE_PMAC_DEBUG | 
|  | 725 | printk(KERN_ERR "ide_pmac: Set UDMA timing for mode %d, reg: 0x%08x\n", | 
|  | 726 | speed & 0xf,  *timings); | 
|  | 727 | #endif | 
|  | 728 |  | 
|  | 729 | return 0; | 
|  | 730 | } | 
|  | 731 |  | 
|  | 732 | /* | 
|  | 733 | * Calculate Kauai ATA/100 UDMA timings | 
|  | 734 | */ | 
| Jon Loeliger | aacaf9b | 2005-09-17 10:36:54 -0500 | [diff] [blame] | 735 | static int | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 736 | set_timings_udma_ata6(u32 *pio_timings, u32 *ultra_timings, u8 speed) | 
|  | 737 | { | 
|  | 738 | struct ide_timing *t = ide_timing_find_mode(speed); | 
|  | 739 | u32 tr; | 
|  | 740 |  | 
|  | 741 | if (speed > XFER_UDMA_5 || t == NULL) | 
|  | 742 | return 1; | 
|  | 743 | tr = kauai_lookup_timing(kauai_udma_timings, (int)t->udma); | 
|  | 744 | if (tr == 0) | 
|  | 745 | return 1; | 
|  | 746 | *ultra_timings = ((*ultra_timings) & ~TR_100_UDMAREG_UDMA_MASK) | tr; | 
|  | 747 | *ultra_timings = (*ultra_timings) | TR_100_UDMAREG_UDMA_EN; | 
|  | 748 |  | 
|  | 749 | return 0; | 
|  | 750 | } | 
|  | 751 |  | 
|  | 752 | /* | 
|  | 753 | * Calculate Shasta ATA/133 UDMA timings | 
|  | 754 | */ | 
| Jon Loeliger | aacaf9b | 2005-09-17 10:36:54 -0500 | [diff] [blame] | 755 | static int | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 756 | set_timings_udma_shasta(u32 *pio_timings, u32 *ultra_timings, u8 speed) | 
|  | 757 | { | 
|  | 758 | struct ide_timing *t = ide_timing_find_mode(speed); | 
|  | 759 | u32 tr; | 
|  | 760 |  | 
|  | 761 | if (speed > XFER_UDMA_6 || t == NULL) | 
|  | 762 | return 1; | 
|  | 763 | tr = kauai_lookup_timing(shasta_udma133_timings, (int)t->udma); | 
|  | 764 | if (tr == 0) | 
|  | 765 | return 1; | 
|  | 766 | *ultra_timings = ((*ultra_timings) & ~TR_133_UDMAREG_UDMA_MASK) | tr; | 
|  | 767 | *ultra_timings = (*ultra_timings) | TR_133_UDMAREG_UDMA_EN; | 
|  | 768 |  | 
|  | 769 | return 0; | 
|  | 770 | } | 
|  | 771 |  | 
|  | 772 | /* | 
|  | 773 | * Calculate MDMA timings for all cells | 
|  | 774 | */ | 
| Jon Loeliger | aacaf9b | 2005-09-17 10:36:54 -0500 | [diff] [blame] | 775 | static int | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 776 | set_timings_mdma(ide_drive_t *drive, int intf_type, u32 *timings, u32 *timings2, | 
|  | 777 | u8 speed, int drive_cycle_time) | 
|  | 778 | { | 
|  | 779 | int cycleTime, accessTime = 0, recTime = 0; | 
|  | 780 | unsigned accessTicks, recTicks; | 
|  | 781 | struct mdma_timings_t* tm = NULL; | 
|  | 782 | int i; | 
|  | 783 |  | 
|  | 784 | /* Get default cycle time for mode */ | 
|  | 785 | switch(speed & 0xf) { | 
|  | 786 | case 0: cycleTime = 480; break; | 
|  | 787 | case 1: cycleTime = 150; break; | 
|  | 788 | case 2: cycleTime = 120; break; | 
|  | 789 | default: | 
|  | 790 | return 1; | 
|  | 791 | } | 
|  | 792 | /* Adjust for drive */ | 
|  | 793 | if (drive_cycle_time && drive_cycle_time > cycleTime) | 
|  | 794 | cycleTime = drive_cycle_time; | 
|  | 795 | /* OHare limits according to some old Apple sources */ | 
|  | 796 | if ((intf_type == controller_ohare) && (cycleTime < 150)) | 
|  | 797 | cycleTime = 150; | 
|  | 798 | /* Get the proper timing array for this controller */ | 
|  | 799 | switch(intf_type) { | 
|  | 800 | case controller_sh_ata6: | 
|  | 801 | case controller_un_ata6: | 
|  | 802 | case controller_k2_ata6: | 
|  | 803 | break; | 
|  | 804 | case controller_kl_ata4: | 
|  | 805 | tm = mdma_timings_66; | 
|  | 806 | break; | 
|  | 807 | case controller_kl_ata3: | 
|  | 808 | tm = mdma_timings_33k; | 
|  | 809 | break; | 
|  | 810 | default: | 
|  | 811 | tm = mdma_timings_33; | 
|  | 812 | break; | 
|  | 813 | } | 
|  | 814 | if (tm != NULL) { | 
|  | 815 | /* Lookup matching access & recovery times */ | 
|  | 816 | i = -1; | 
|  | 817 | for (;;) { | 
|  | 818 | if (tm[i+1].cycleTime < cycleTime) | 
|  | 819 | break; | 
|  | 820 | i++; | 
|  | 821 | } | 
|  | 822 | if (i < 0) | 
|  | 823 | return 1; | 
|  | 824 | cycleTime = tm[i].cycleTime; | 
|  | 825 | accessTime = tm[i].accessTime; | 
|  | 826 | recTime = tm[i].recoveryTime; | 
|  | 827 |  | 
|  | 828 | #ifdef IDE_PMAC_DEBUG | 
|  | 829 | printk(KERN_ERR "%s: MDMA, cycleTime: %d, accessTime: %d, recTime: %d\n", | 
|  | 830 | drive->name, cycleTime, accessTime, recTime); | 
|  | 831 | #endif | 
|  | 832 | } | 
|  | 833 | switch(intf_type) { | 
|  | 834 | case controller_sh_ata6: { | 
|  | 835 | /* 133Mhz cell */ | 
|  | 836 | u32 tr = kauai_lookup_timing(shasta_mdma_timings, cycleTime); | 
|  | 837 | if (tr == 0) | 
|  | 838 | return 1; | 
|  | 839 | *timings = ((*timings) & ~TR_133_PIOREG_MDMA_MASK) | tr; | 
|  | 840 | *timings2 = (*timings2) & ~TR_133_UDMAREG_UDMA_EN; | 
|  | 841 | } | 
|  | 842 | case controller_un_ata6: | 
|  | 843 | case controller_k2_ata6: { | 
|  | 844 | /* 100Mhz cell */ | 
|  | 845 | u32 tr = kauai_lookup_timing(kauai_mdma_timings, cycleTime); | 
|  | 846 | if (tr == 0) | 
|  | 847 | return 1; | 
|  | 848 | *timings = ((*timings) & ~TR_100_PIOREG_MDMA_MASK) | tr; | 
|  | 849 | *timings2 = (*timings2) & ~TR_100_UDMAREG_UDMA_EN; | 
|  | 850 | } | 
|  | 851 | break; | 
|  | 852 | case controller_kl_ata4: | 
|  | 853 | /* 66Mhz cell */ | 
|  | 854 | accessTicks = SYSCLK_TICKS_66(accessTime); | 
|  | 855 | accessTicks = min(accessTicks, 0x1fU); | 
|  | 856 | accessTicks = max(accessTicks, 0x1U); | 
|  | 857 | recTicks = SYSCLK_TICKS_66(recTime); | 
|  | 858 | recTicks = min(recTicks, 0x1fU); | 
|  | 859 | recTicks = max(recTicks, 0x3U); | 
|  | 860 | /* Clear out mdma bits and disable udma */ | 
|  | 861 | *timings = ((*timings) & ~(TR_66_MDMA_MASK | TR_66_UDMA_MASK)) | | 
|  | 862 | (accessTicks << TR_66_MDMA_ACCESS_SHIFT) | | 
|  | 863 | (recTicks << TR_66_MDMA_RECOVERY_SHIFT); | 
|  | 864 | break; | 
|  | 865 | case controller_kl_ata3: | 
|  | 866 | /* 33Mhz cell on KeyLargo */ | 
|  | 867 | accessTicks = SYSCLK_TICKS(accessTime); | 
|  | 868 | accessTicks = max(accessTicks, 1U); | 
|  | 869 | accessTicks = min(accessTicks, 0x1fU); | 
|  | 870 | accessTime = accessTicks * IDE_SYSCLK_NS; | 
|  | 871 | recTicks = SYSCLK_TICKS(recTime); | 
|  | 872 | recTicks = max(recTicks, 1U); | 
|  | 873 | recTicks = min(recTicks, 0x1fU); | 
|  | 874 | *timings = ((*timings) & ~TR_33_MDMA_MASK) | | 
|  | 875 | (accessTicks << TR_33_MDMA_ACCESS_SHIFT) | | 
|  | 876 | (recTicks << TR_33_MDMA_RECOVERY_SHIFT); | 
|  | 877 | break; | 
|  | 878 | default: { | 
|  | 879 | /* 33Mhz cell on others */ | 
|  | 880 | int halfTick = 0; | 
|  | 881 | int origAccessTime = accessTime; | 
|  | 882 | int origRecTime = recTime; | 
|  | 883 |  | 
|  | 884 | accessTicks = SYSCLK_TICKS(accessTime); | 
|  | 885 | accessTicks = max(accessTicks, 1U); | 
|  | 886 | accessTicks = min(accessTicks, 0x1fU); | 
|  | 887 | accessTime = accessTicks * IDE_SYSCLK_NS; | 
|  | 888 | recTicks = SYSCLK_TICKS(recTime); | 
|  | 889 | recTicks = max(recTicks, 2U) - 1; | 
|  | 890 | recTicks = min(recTicks, 0x1fU); | 
|  | 891 | recTime = (recTicks + 1) * IDE_SYSCLK_NS; | 
|  | 892 | if ((accessTicks > 1) && | 
|  | 893 | ((accessTime - IDE_SYSCLK_NS/2) >= origAccessTime) && | 
|  | 894 | ((recTime - IDE_SYSCLK_NS/2) >= origRecTime)) { | 
|  | 895 | halfTick = 1; | 
|  | 896 | accessTicks--; | 
|  | 897 | } | 
|  | 898 | *timings = ((*timings) & ~TR_33_MDMA_MASK) | | 
|  | 899 | (accessTicks << TR_33_MDMA_ACCESS_SHIFT) | | 
|  | 900 | (recTicks << TR_33_MDMA_RECOVERY_SHIFT); | 
|  | 901 | if (halfTick) | 
|  | 902 | *timings |= TR_33_MDMA_HALFTICK; | 
|  | 903 | } | 
|  | 904 | } | 
|  | 905 | #ifdef IDE_PMAC_DEBUG | 
|  | 906 | printk(KERN_ERR "%s: Set MDMA timing for mode %d, reg: 0x%08x\n", | 
|  | 907 | drive->name, speed & 0xf,  *timings); | 
|  | 908 | #endif | 
|  | 909 | return 0; | 
|  | 910 | } | 
|  | 911 | #endif /* #ifdef CONFIG_BLK_DEV_IDEDMA_PMAC */ | 
|  | 912 |  | 
|  | 913 | /* | 
|  | 914 | * Speedproc. This function is called by the core to set any of the standard | 
|  | 915 | * timing (PIO, MDMA or UDMA) to both the drive and the controller. | 
|  | 916 | * You may notice we don't use this function on normal "dma check" operation, | 
|  | 917 | * our dedicated function is more precise as it uses the drive provided | 
|  | 918 | * cycle time value. We should probably fix this one to deal with that too... | 
|  | 919 | */ | 
| Jon Loeliger | aacaf9b | 2005-09-17 10:36:54 -0500 | [diff] [blame] | 920 | static int | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 921 | pmac_ide_tune_chipset (ide_drive_t *drive, byte speed) | 
|  | 922 | { | 
|  | 923 | int unit = (drive->select.b.unit & 0x01); | 
|  | 924 | int ret = 0; | 
|  | 925 | pmac_ide_hwif_t* pmif = (pmac_ide_hwif_t *)HWIF(drive)->hwif_data; | 
|  | 926 | u32 *timings, *timings2; | 
|  | 927 |  | 
|  | 928 | if (pmif == NULL) | 
|  | 929 | return 1; | 
|  | 930 |  | 
|  | 931 | timings = &pmif->timings[unit]; | 
|  | 932 | timings2 = &pmif->timings[unit+2]; | 
|  | 933 |  | 
|  | 934 | switch(speed) { | 
|  | 935 | #ifdef CONFIG_BLK_DEV_IDEDMA_PMAC | 
|  | 936 | case XFER_UDMA_6: | 
|  | 937 | if (pmif->kind != controller_sh_ata6) | 
|  | 938 | return 1; | 
|  | 939 | case XFER_UDMA_5: | 
|  | 940 | if (pmif->kind != controller_un_ata6 && | 
|  | 941 | pmif->kind != controller_k2_ata6 && | 
|  | 942 | pmif->kind != controller_sh_ata6) | 
|  | 943 | return 1; | 
|  | 944 | case XFER_UDMA_4: | 
|  | 945 | case XFER_UDMA_3: | 
|  | 946 | if (HWIF(drive)->udma_four == 0) | 
|  | 947 | return 1; | 
|  | 948 | case XFER_UDMA_2: | 
|  | 949 | case XFER_UDMA_1: | 
|  | 950 | case XFER_UDMA_0: | 
|  | 951 | if (pmif->kind == controller_kl_ata4) | 
|  | 952 | ret = set_timings_udma_ata4(timings, speed); | 
|  | 953 | else if (pmif->kind == controller_un_ata6 | 
|  | 954 | || pmif->kind == controller_k2_ata6) | 
|  | 955 | ret = set_timings_udma_ata6(timings, timings2, speed); | 
|  | 956 | else if (pmif->kind == controller_sh_ata6) | 
|  | 957 | ret = set_timings_udma_shasta(timings, timings2, speed); | 
|  | 958 | else | 
|  | 959 | ret = 1; | 
|  | 960 | break; | 
|  | 961 | case XFER_MW_DMA_2: | 
|  | 962 | case XFER_MW_DMA_1: | 
|  | 963 | case XFER_MW_DMA_0: | 
|  | 964 | ret = set_timings_mdma(drive, pmif->kind, timings, timings2, speed, 0); | 
|  | 965 | break; | 
|  | 966 | case XFER_SW_DMA_2: | 
|  | 967 | case XFER_SW_DMA_1: | 
|  | 968 | case XFER_SW_DMA_0: | 
|  | 969 | return 1; | 
|  | 970 | #endif /* CONFIG_BLK_DEV_IDEDMA_PMAC */ | 
|  | 971 | case XFER_PIO_4: | 
|  | 972 | case XFER_PIO_3: | 
|  | 973 | case XFER_PIO_2: | 
|  | 974 | case XFER_PIO_1: | 
|  | 975 | case XFER_PIO_0: | 
|  | 976 | pmac_ide_tuneproc(drive, speed & 0x07); | 
|  | 977 | break; | 
|  | 978 | default: | 
|  | 979 | ret = 1; | 
|  | 980 | } | 
|  | 981 | if (ret) | 
|  | 982 | return ret; | 
|  | 983 |  | 
|  | 984 | ret = pmac_ide_do_setfeature(drive, speed); | 
|  | 985 | if (ret) | 
|  | 986 | return ret; | 
|  | 987 |  | 
|  | 988 | pmac_ide_do_update_timings(drive); | 
|  | 989 | drive->current_speed = speed; | 
|  | 990 |  | 
|  | 991 | return 0; | 
|  | 992 | } | 
|  | 993 |  | 
|  | 994 | /* | 
|  | 995 | * Blast some well known "safe" values to the timing registers at init or | 
|  | 996 | * wakeup from sleep time, before we do real calculation | 
|  | 997 | */ | 
| Jon Loeliger | aacaf9b | 2005-09-17 10:36:54 -0500 | [diff] [blame] | 998 | static void | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 999 | sanitize_timings(pmac_ide_hwif_t *pmif) | 
|  | 1000 | { | 
|  | 1001 | unsigned int value, value2 = 0; | 
|  | 1002 |  | 
|  | 1003 | switch(pmif->kind) { | 
|  | 1004 | case controller_sh_ata6: | 
|  | 1005 | value = 0x0a820c97; | 
|  | 1006 | value2 = 0x00033031; | 
|  | 1007 | break; | 
|  | 1008 | case controller_un_ata6: | 
|  | 1009 | case controller_k2_ata6: | 
|  | 1010 | value = 0x08618a92; | 
|  | 1011 | value2 = 0x00002921; | 
|  | 1012 | break; | 
|  | 1013 | case controller_kl_ata4: | 
|  | 1014 | value = 0x0008438c; | 
|  | 1015 | break; | 
|  | 1016 | case controller_kl_ata3: | 
|  | 1017 | value = 0x00084526; | 
|  | 1018 | break; | 
|  | 1019 | case controller_heathrow: | 
|  | 1020 | case controller_ohare: | 
|  | 1021 | default: | 
|  | 1022 | value = 0x00074526; | 
|  | 1023 | break; | 
|  | 1024 | } | 
|  | 1025 | pmif->timings[0] = pmif->timings[1] = value; | 
|  | 1026 | pmif->timings[2] = pmif->timings[3] = value2; | 
|  | 1027 | } | 
|  | 1028 |  | 
| Jon Loeliger | aacaf9b | 2005-09-17 10:36:54 -0500 | [diff] [blame] | 1029 | unsigned long | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 1030 | pmac_ide_get_base(int index) | 
|  | 1031 | { | 
|  | 1032 | return pmac_ide[index].regbase; | 
|  | 1033 | } | 
|  | 1034 |  | 
| Jon Loeliger | aacaf9b | 2005-09-17 10:36:54 -0500 | [diff] [blame] | 1035 | int | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 1036 | pmac_ide_check_base(unsigned long base) | 
|  | 1037 | { | 
|  | 1038 | int ix; | 
|  | 1039 |  | 
|  | 1040 | for (ix = 0; ix < MAX_HWIFS; ++ix) | 
|  | 1041 | if (base == pmac_ide[ix].regbase) | 
|  | 1042 | return ix; | 
|  | 1043 | return -1; | 
|  | 1044 | } | 
|  | 1045 |  | 
| Jon Loeliger | aacaf9b | 2005-09-17 10:36:54 -0500 | [diff] [blame] | 1046 | int | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 1047 | pmac_ide_get_irq(unsigned long base) | 
|  | 1048 | { | 
|  | 1049 | int ix; | 
|  | 1050 |  | 
|  | 1051 | for (ix = 0; ix < MAX_HWIFS; ++ix) | 
|  | 1052 | if (base == pmac_ide[ix].regbase) | 
|  | 1053 | return pmac_ide[ix].irq; | 
|  | 1054 | return 0; | 
|  | 1055 | } | 
|  | 1056 |  | 
| Jon Loeliger | aacaf9b | 2005-09-17 10:36:54 -0500 | [diff] [blame] | 1057 | static int ide_majors[] = { 3, 22, 33, 34, 56, 57 }; | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 1058 |  | 
|  | 1059 | dev_t __init | 
|  | 1060 | pmac_find_ide_boot(char *bootdevice, int n) | 
|  | 1061 | { | 
|  | 1062 | int i; | 
|  | 1063 |  | 
|  | 1064 | /* | 
|  | 1065 | * Look through the list of IDE interfaces for this one. | 
|  | 1066 | */ | 
|  | 1067 | for (i = 0; i < pmac_ide_count; ++i) { | 
|  | 1068 | char *name; | 
|  | 1069 | if (!pmac_ide[i].node || !pmac_ide[i].node->full_name) | 
|  | 1070 | continue; | 
|  | 1071 | name = pmac_ide[i].node->full_name; | 
|  | 1072 | if (memcmp(name, bootdevice, n) == 0 && name[n] == 0) { | 
|  | 1073 | /* XXX should cope with the 2nd drive as well... */ | 
|  | 1074 | return MKDEV(ide_majors[i], 0); | 
|  | 1075 | } | 
|  | 1076 | } | 
|  | 1077 |  | 
|  | 1078 | return 0; | 
|  | 1079 | } | 
|  | 1080 |  | 
|  | 1081 | /* Suspend call back, should be called after the child devices | 
|  | 1082 | * have actually been suspended | 
|  | 1083 | */ | 
|  | 1084 | static int | 
|  | 1085 | pmac_ide_do_suspend(ide_hwif_t *hwif) | 
|  | 1086 | { | 
|  | 1087 | pmac_ide_hwif_t *pmif = (pmac_ide_hwif_t *)hwif->hwif_data; | 
|  | 1088 |  | 
|  | 1089 | /* We clear the timings */ | 
|  | 1090 | pmif->timings[0] = 0; | 
|  | 1091 | pmif->timings[1] = 0; | 
|  | 1092 |  | 
| Benjamin Herrenschmidt | 616299a | 2005-05-01 08:58:41 -0700 | [diff] [blame] | 1093 | disable_irq(pmif->irq); | 
|  | 1094 |  | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 1095 | /* The media bay will handle itself just fine */ | 
|  | 1096 | if (pmif->mediabay) | 
|  | 1097 | return 0; | 
|  | 1098 |  | 
|  | 1099 | /* Kauai has bus control FCRs directly here */ | 
|  | 1100 | if (pmif->kauai_fcr) { | 
|  | 1101 | u32 fcr = readl(pmif->kauai_fcr); | 
|  | 1102 | fcr &= ~(KAUAI_FCR_UATA_RESET_N | KAUAI_FCR_UATA_ENABLE); | 
|  | 1103 | writel(fcr, pmif->kauai_fcr); | 
|  | 1104 | } | 
|  | 1105 |  | 
|  | 1106 | /* Disable the bus on older machines and the cell on kauai */ | 
|  | 1107 | ppc_md.feature_call(PMAC_FTR_IDE_ENABLE, pmif->node, pmif->aapl_bus_id, | 
|  | 1108 | 0); | 
|  | 1109 |  | 
|  | 1110 | return 0; | 
|  | 1111 | } | 
|  | 1112 |  | 
|  | 1113 | /* Resume call back, should be called before the child devices | 
|  | 1114 | * are resumed | 
|  | 1115 | */ | 
|  | 1116 | static int | 
|  | 1117 | pmac_ide_do_resume(ide_hwif_t *hwif) | 
|  | 1118 | { | 
|  | 1119 | pmac_ide_hwif_t *pmif = (pmac_ide_hwif_t *)hwif->hwif_data; | 
|  | 1120 |  | 
|  | 1121 | /* Hard reset & re-enable controller (do we really need to reset ? -BenH) */ | 
|  | 1122 | if (!pmif->mediabay) { | 
|  | 1123 | ppc_md.feature_call(PMAC_FTR_IDE_RESET, pmif->node, pmif->aapl_bus_id, 1); | 
|  | 1124 | ppc_md.feature_call(PMAC_FTR_IDE_ENABLE, pmif->node, pmif->aapl_bus_id, 1); | 
|  | 1125 | msleep(10); | 
|  | 1126 | ppc_md.feature_call(PMAC_FTR_IDE_RESET, pmif->node, pmif->aapl_bus_id, 0); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 1127 |  | 
|  | 1128 | /* Kauai has it different */ | 
|  | 1129 | if (pmif->kauai_fcr) { | 
|  | 1130 | u32 fcr = readl(pmif->kauai_fcr); | 
|  | 1131 | fcr |= KAUAI_FCR_UATA_RESET_N | KAUAI_FCR_UATA_ENABLE; | 
|  | 1132 | writel(fcr, pmif->kauai_fcr); | 
|  | 1133 | } | 
| Benjamin Herrenschmidt | 616299a | 2005-05-01 08:58:41 -0700 | [diff] [blame] | 1134 |  | 
|  | 1135 | msleep(jiffies_to_msecs(IDE_WAKEUP_DELAY)); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 1136 | } | 
|  | 1137 |  | 
|  | 1138 | /* Sanitize drive timings */ | 
|  | 1139 | sanitize_timings(pmif); | 
|  | 1140 |  | 
| Benjamin Herrenschmidt | 616299a | 2005-05-01 08:58:41 -0700 | [diff] [blame] | 1141 | enable_irq(pmif->irq); | 
|  | 1142 |  | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 1143 | return 0; | 
|  | 1144 | } | 
|  | 1145 |  | 
|  | 1146 | /* | 
|  | 1147 | * Setup, register & probe an IDE channel driven by this driver, this is | 
|  | 1148 | * called by one of the 2 probe functions (macio or PCI). Note that a channel | 
|  | 1149 | * that ends up beeing free of any device is not kept around by this driver | 
|  | 1150 | * (it is kept in 2.4). This introduce an interface numbering change on some | 
|  | 1151 | * rare machines unfortunately, but it's better this way. | 
|  | 1152 | */ | 
|  | 1153 | static int | 
|  | 1154 | pmac_ide_setup_device(pmac_ide_hwif_t *pmif, ide_hwif_t *hwif) | 
|  | 1155 | { | 
|  | 1156 | struct device_node *np = pmif->node; | 
| Jeremy Kerr | 018a3d1 | 2006-07-12 15:40:29 +1000 | [diff] [blame] | 1157 | const int *bidp; | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 1158 |  | 
|  | 1159 | pmif->cable_80 = 0; | 
|  | 1160 | pmif->broken_dma = pmif->broken_dma_warn = 0; | 
|  | 1161 | if (device_is_compatible(np, "shasta-ata")) | 
|  | 1162 | pmif->kind = controller_sh_ata6; | 
|  | 1163 | else if (device_is_compatible(np, "kauai-ata")) | 
|  | 1164 | pmif->kind = controller_un_ata6; | 
|  | 1165 | else if (device_is_compatible(np, "K2-UATA")) | 
|  | 1166 | pmif->kind = controller_k2_ata6; | 
|  | 1167 | else if (device_is_compatible(np, "keylargo-ata")) { | 
|  | 1168 | if (strcmp(np->name, "ata-4") == 0) | 
|  | 1169 | pmif->kind = controller_kl_ata4; | 
|  | 1170 | else | 
|  | 1171 | pmif->kind = controller_kl_ata3; | 
|  | 1172 | } else if (device_is_compatible(np, "heathrow-ata")) | 
|  | 1173 | pmif->kind = controller_heathrow; | 
|  | 1174 | else { | 
|  | 1175 | pmif->kind = controller_ohare; | 
|  | 1176 | pmif->broken_dma = 1; | 
|  | 1177 | } | 
|  | 1178 |  | 
| Jeremy Kerr | 018a3d1 | 2006-07-12 15:40:29 +1000 | [diff] [blame] | 1179 | bidp = get_property(np, "AAPL,bus-id", NULL); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 1180 | pmif->aapl_bus_id =  bidp ? *bidp : 0; | 
|  | 1181 |  | 
|  | 1182 | /* Get cable type from device-tree */ | 
|  | 1183 | if (pmif->kind == controller_kl_ata4 || pmif->kind == controller_un_ata6 | 
|  | 1184 | || pmif->kind == controller_k2_ata6 | 
|  | 1185 | || pmif->kind == controller_sh_ata6) { | 
| Jeremy Kerr | 018a3d1 | 2006-07-12 15:40:29 +1000 | [diff] [blame] | 1186 | const char* cable = get_property(np, "cable-type", NULL); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 1187 | if (cable && !strncmp(cable, "80-", 3)) | 
|  | 1188 | pmif->cable_80 = 1; | 
|  | 1189 | } | 
|  | 1190 | /* G5's seem to have incorrect cable type in device-tree. Let's assume | 
|  | 1191 | * they have a 80 conductor cable, this seem to be always the case unless | 
|  | 1192 | * the user mucked around | 
|  | 1193 | */ | 
|  | 1194 | if (device_is_compatible(np, "K2-UATA") || | 
|  | 1195 | device_is_compatible(np, "shasta-ata")) | 
|  | 1196 | pmif->cable_80 = 1; | 
|  | 1197 |  | 
|  | 1198 | /* On Kauai-type controllers, we make sure the FCR is correct */ | 
|  | 1199 | if (pmif->kauai_fcr) | 
|  | 1200 | writel(KAUAI_FCR_UATA_MAGIC | | 
|  | 1201 | KAUAI_FCR_UATA_RESET_N | | 
|  | 1202 | KAUAI_FCR_UATA_ENABLE, pmif->kauai_fcr); | 
|  | 1203 |  | 
|  | 1204 | pmif->mediabay = 0; | 
|  | 1205 |  | 
|  | 1206 | /* Make sure we have sane timings */ | 
|  | 1207 | sanitize_timings(pmif); | 
|  | 1208 |  | 
|  | 1209 | #ifndef CONFIG_PPC64 | 
|  | 1210 | /* XXX FIXME: Media bay stuff need re-organizing */ | 
|  | 1211 | if (np->parent && np->parent->name | 
|  | 1212 | && strcasecmp(np->parent->name, "media-bay") == 0) { | 
| Benjamin Herrenschmidt | 8c87093 | 2005-06-27 14:36:34 -0700 | [diff] [blame] | 1213 | #ifdef CONFIG_PMAC_MEDIABAY | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 1214 | media_bay_set_ide_infos(np->parent, pmif->regbase, pmif->irq, hwif->index); | 
| Benjamin Herrenschmidt | 8c87093 | 2005-06-27 14:36:34 -0700 | [diff] [blame] | 1215 | #endif /* CONFIG_PMAC_MEDIABAY */ | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 1216 | pmif->mediabay = 1; | 
|  | 1217 | if (!bidp) | 
|  | 1218 | pmif->aapl_bus_id = 1; | 
|  | 1219 | } else if (pmif->kind == controller_ohare) { | 
|  | 1220 | /* The code below is having trouble on some ohare machines | 
|  | 1221 | * (timing related ?). Until I can put my hand on one of these | 
|  | 1222 | * units, I keep the old way | 
|  | 1223 | */ | 
|  | 1224 | ppc_md.feature_call(PMAC_FTR_IDE_ENABLE, np, 0, 1); | 
|  | 1225 | } else | 
|  | 1226 | #endif | 
|  | 1227 | { | 
|  | 1228 | /* This is necessary to enable IDE when net-booting */ | 
|  | 1229 | ppc_md.feature_call(PMAC_FTR_IDE_RESET, np, pmif->aapl_bus_id, 1); | 
|  | 1230 | ppc_md.feature_call(PMAC_FTR_IDE_ENABLE, np, pmif->aapl_bus_id, 1); | 
|  | 1231 | msleep(10); | 
|  | 1232 | ppc_md.feature_call(PMAC_FTR_IDE_RESET, np, pmif->aapl_bus_id, 0); | 
|  | 1233 | msleep(jiffies_to_msecs(IDE_WAKEUP_DELAY)); | 
|  | 1234 | } | 
|  | 1235 |  | 
|  | 1236 | /* Setup MMIO ops */ | 
|  | 1237 | default_hwif_mmiops(hwif); | 
|  | 1238 | hwif->OUTBSYNC = pmac_outbsync; | 
|  | 1239 |  | 
|  | 1240 | /* Tell common code _not_ to mess with resources */ | 
|  | 1241 | hwif->mmio = 2; | 
|  | 1242 | hwif->hwif_data = pmif; | 
|  | 1243 | pmac_ide_init_hwif_ports(&hwif->hw, pmif->regbase, 0, &hwif->irq); | 
|  | 1244 | memcpy(hwif->io_ports, hwif->hw.io_ports, sizeof(hwif->io_ports)); | 
|  | 1245 | hwif->chipset = ide_pmac; | 
|  | 1246 | hwif->noprobe = !hwif->io_ports[IDE_DATA_OFFSET] || pmif->mediabay; | 
|  | 1247 | hwif->hold = pmif->mediabay; | 
|  | 1248 | hwif->udma_four = pmif->cable_80; | 
|  | 1249 | hwif->drives[0].unmask = 1; | 
|  | 1250 | hwif->drives[1].unmask = 1; | 
|  | 1251 | hwif->tuneproc = pmac_ide_tuneproc; | 
|  | 1252 | if (pmif->kind == controller_un_ata6 | 
|  | 1253 | || pmif->kind == controller_k2_ata6 | 
|  | 1254 | || pmif->kind == controller_sh_ata6) | 
|  | 1255 | hwif->selectproc = pmac_ide_kauai_selectproc; | 
|  | 1256 | else | 
|  | 1257 | hwif->selectproc = pmac_ide_selectproc; | 
|  | 1258 | hwif->speedproc = pmac_ide_tune_chipset; | 
|  | 1259 |  | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 1260 | printk(KERN_INFO "ide%d: Found Apple %s controller, bus ID %d%s, irq %d\n", | 
|  | 1261 | hwif->index, model_name[pmif->kind], pmif->aapl_bus_id, | 
|  | 1262 | pmif->mediabay ? " (mediabay)" : "", hwif->irq); | 
|  | 1263 |  | 
| Benjamin Herrenschmidt | 8c87093 | 2005-06-27 14:36:34 -0700 | [diff] [blame] | 1264 | #ifdef CONFIG_PMAC_MEDIABAY | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 1265 | if (pmif->mediabay && check_media_bay_by_base(pmif->regbase, MB_CD) == 0) | 
|  | 1266 | hwif->noprobe = 0; | 
| Benjamin Herrenschmidt | 8c87093 | 2005-06-27 14:36:34 -0700 | [diff] [blame] | 1267 | #endif /* CONFIG_PMAC_MEDIABAY */ | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 1268 |  | 
|  | 1269 | hwif->sg_max_nents = MAX_DCMDS; | 
|  | 1270 |  | 
|  | 1271 | #ifdef CONFIG_BLK_DEV_IDEDMA_PMAC | 
|  | 1272 | /* has a DBDMA controller channel */ | 
|  | 1273 | if (pmif->dma_regs) | 
|  | 1274 | pmac_ide_setup_dma(pmif, hwif); | 
|  | 1275 | #endif /* CONFIG_BLK_DEV_IDEDMA_PMAC */ | 
|  | 1276 |  | 
|  | 1277 | /* We probe the hwif now */ | 
|  | 1278 | probe_hwif_init(hwif); | 
|  | 1279 |  | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 1280 | return 0; | 
|  | 1281 | } | 
|  | 1282 |  | 
|  | 1283 | /* | 
|  | 1284 | * Attach to a macio probed interface | 
|  | 1285 | */ | 
|  | 1286 | static int __devinit | 
| Jeff Mahoney | 5e65577 | 2005-07-06 15:44:41 -0400 | [diff] [blame] | 1287 | pmac_ide_macio_attach(struct macio_dev *mdev, const struct of_device_id *match) | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 1288 | { | 
|  | 1289 | void __iomem *base; | 
|  | 1290 | unsigned long regbase; | 
|  | 1291 | int irq; | 
|  | 1292 | ide_hwif_t *hwif; | 
|  | 1293 | pmac_ide_hwif_t *pmif; | 
|  | 1294 | int i, rc; | 
|  | 1295 |  | 
|  | 1296 | i = 0; | 
|  | 1297 | while (i < MAX_HWIFS && (ide_hwifs[i].io_ports[IDE_DATA_OFFSET] != 0 | 
|  | 1298 | || pmac_ide[i].node != NULL)) | 
|  | 1299 | ++i; | 
|  | 1300 | if (i >= MAX_HWIFS) { | 
|  | 1301 | printk(KERN_ERR "ide-pmac: MacIO interface attach with no slot\n"); | 
|  | 1302 | printk(KERN_ERR "          %s\n", mdev->ofdev.node->full_name); | 
|  | 1303 | return -ENODEV; | 
|  | 1304 | } | 
|  | 1305 |  | 
|  | 1306 | pmif = &pmac_ide[i]; | 
|  | 1307 | hwif = &ide_hwifs[i]; | 
|  | 1308 |  | 
| Benjamin Herrenschmidt | cc5d018 | 2005-12-13 18:01:21 +1100 | [diff] [blame] | 1309 | if (macio_resource_count(mdev) == 0) { | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 1310 | printk(KERN_WARNING "ide%d: no address for %s\n", | 
|  | 1311 | i, mdev->ofdev.node->full_name); | 
|  | 1312 | return -ENXIO; | 
|  | 1313 | } | 
|  | 1314 |  | 
|  | 1315 | /* Request memory resource for IO ports */ | 
|  | 1316 | if (macio_request_resource(mdev, 0, "ide-pmac (ports)")) { | 
|  | 1317 | printk(KERN_ERR "ide%d: can't request mmio resource !\n", i); | 
|  | 1318 | return -EBUSY; | 
|  | 1319 | } | 
|  | 1320 |  | 
|  | 1321 | /* XXX This is bogus. Should be fixed in the registry by checking | 
|  | 1322 | * the kind of host interrupt controller, a bit like gatwick | 
|  | 1323 | * fixes in irq.c. That works well enough for the single case | 
|  | 1324 | * where that happens though... | 
|  | 1325 | */ | 
|  | 1326 | if (macio_irq_count(mdev) == 0) { | 
|  | 1327 | printk(KERN_WARNING "ide%d: no intrs for device %s, using 13\n", | 
|  | 1328 | i, mdev->ofdev.node->full_name); | 
| Benjamin Herrenschmidt | 69917c2 | 2006-09-22 12:56:30 +1000 | [diff] [blame] | 1329 | irq = irq_create_mapping(NULL, 13); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 1330 | } else | 
|  | 1331 | irq = macio_irq(mdev, 0); | 
|  | 1332 |  | 
|  | 1333 | base = ioremap(macio_resource_start(mdev, 0), 0x400); | 
|  | 1334 | regbase = (unsigned long) base; | 
|  | 1335 |  | 
|  | 1336 | hwif->pci_dev = mdev->bus->pdev; | 
|  | 1337 | hwif->gendev.parent = &mdev->ofdev.dev; | 
|  | 1338 |  | 
|  | 1339 | pmif->mdev = mdev; | 
|  | 1340 | pmif->node = mdev->ofdev.node; | 
|  | 1341 | pmif->regbase = regbase; | 
|  | 1342 | pmif->irq = irq; | 
|  | 1343 | pmif->kauai_fcr = NULL; | 
|  | 1344 | #ifdef CONFIG_BLK_DEV_IDEDMA_PMAC | 
|  | 1345 | if (macio_resource_count(mdev) >= 2) { | 
|  | 1346 | if (macio_request_resource(mdev, 1, "ide-pmac (dma)")) | 
|  | 1347 | printk(KERN_WARNING "ide%d: can't request DMA resource !\n", i); | 
|  | 1348 | else | 
|  | 1349 | pmif->dma_regs = ioremap(macio_resource_start(mdev, 1), 0x1000); | 
|  | 1350 | } else | 
|  | 1351 | pmif->dma_regs = NULL; | 
|  | 1352 | #endif /* CONFIG_BLK_DEV_IDEDMA_PMAC */ | 
|  | 1353 | dev_set_drvdata(&mdev->ofdev.dev, hwif); | 
|  | 1354 |  | 
|  | 1355 | rc = pmac_ide_setup_device(pmif, hwif); | 
|  | 1356 | if (rc != 0) { | 
|  | 1357 | /* The inteface is released to the common IDE layer */ | 
|  | 1358 | dev_set_drvdata(&mdev->ofdev.dev, NULL); | 
|  | 1359 | iounmap(base); | 
|  | 1360 | if (pmif->dma_regs) | 
|  | 1361 | iounmap(pmif->dma_regs); | 
|  | 1362 | memset(pmif, 0, sizeof(*pmif)); | 
|  | 1363 | macio_release_resource(mdev, 0); | 
|  | 1364 | if (pmif->dma_regs) | 
|  | 1365 | macio_release_resource(mdev, 1); | 
|  | 1366 | } | 
|  | 1367 |  | 
|  | 1368 | return rc; | 
|  | 1369 | } | 
|  | 1370 |  | 
|  | 1371 | static int | 
| David Brownell | 8b4b8a2 | 2006-08-14 23:11:03 -0700 | [diff] [blame] | 1372 | pmac_ide_macio_suspend(struct macio_dev *mdev, pm_message_t mesg) | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 1373 | { | 
|  | 1374 | ide_hwif_t	*hwif = (ide_hwif_t *)dev_get_drvdata(&mdev->ofdev.dev); | 
|  | 1375 | int		rc = 0; | 
|  | 1376 |  | 
| David Brownell | 8b4b8a2 | 2006-08-14 23:11:03 -0700 | [diff] [blame] | 1377 | if (mesg.event != mdev->ofdev.dev.power.power_state.event | 
|  | 1378 | && mesg.event == PM_EVENT_SUSPEND) { | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 1379 | rc = pmac_ide_do_suspend(hwif); | 
|  | 1380 | if (rc == 0) | 
| David Brownell | 8b4b8a2 | 2006-08-14 23:11:03 -0700 | [diff] [blame] | 1381 | mdev->ofdev.dev.power.power_state = mesg; | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 1382 | } | 
|  | 1383 |  | 
|  | 1384 | return rc; | 
|  | 1385 | } | 
|  | 1386 |  | 
|  | 1387 | static int | 
|  | 1388 | pmac_ide_macio_resume(struct macio_dev *mdev) | 
|  | 1389 | { | 
|  | 1390 | ide_hwif_t	*hwif = (ide_hwif_t *)dev_get_drvdata(&mdev->ofdev.dev); | 
|  | 1391 | int		rc = 0; | 
|  | 1392 |  | 
| Pavel Machek | ca078ba | 2005-09-03 15:56:57 -0700 | [diff] [blame] | 1393 | if (mdev->ofdev.dev.power.power_state.event != PM_EVENT_ON) { | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 1394 | rc = pmac_ide_do_resume(hwif); | 
|  | 1395 | if (rc == 0) | 
| Pavel Machek | 829ca9a | 2005-09-03 15:56:56 -0700 | [diff] [blame] | 1396 | mdev->ofdev.dev.power.power_state = PMSG_ON; | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 1397 | } | 
|  | 1398 |  | 
|  | 1399 | return rc; | 
|  | 1400 | } | 
|  | 1401 |  | 
|  | 1402 | /* | 
|  | 1403 | * Attach to a PCI probed interface | 
|  | 1404 | */ | 
|  | 1405 | static int __devinit | 
|  | 1406 | pmac_ide_pci_attach(struct pci_dev *pdev, const struct pci_device_id *id) | 
|  | 1407 | { | 
|  | 1408 | ide_hwif_t *hwif; | 
|  | 1409 | struct device_node *np; | 
|  | 1410 | pmac_ide_hwif_t *pmif; | 
|  | 1411 | void __iomem *base; | 
|  | 1412 | unsigned long rbase, rlen; | 
|  | 1413 | int i, rc; | 
|  | 1414 |  | 
|  | 1415 | np = pci_device_to_OF_node(pdev); | 
|  | 1416 | if (np == NULL) { | 
|  | 1417 | printk(KERN_ERR "ide-pmac: cannot find MacIO node for Kauai ATA interface\n"); | 
|  | 1418 | return -ENODEV; | 
|  | 1419 | } | 
|  | 1420 | i = 0; | 
|  | 1421 | while (i < MAX_HWIFS && (ide_hwifs[i].io_ports[IDE_DATA_OFFSET] != 0 | 
|  | 1422 | || pmac_ide[i].node != NULL)) | 
|  | 1423 | ++i; | 
|  | 1424 | if (i >= MAX_HWIFS) { | 
|  | 1425 | printk(KERN_ERR "ide-pmac: PCI interface attach with no slot\n"); | 
|  | 1426 | printk(KERN_ERR "          %s\n", np->full_name); | 
|  | 1427 | return -ENODEV; | 
|  | 1428 | } | 
|  | 1429 |  | 
|  | 1430 | pmif = &pmac_ide[i]; | 
|  | 1431 | hwif = &ide_hwifs[i]; | 
|  | 1432 |  | 
|  | 1433 | if (pci_enable_device(pdev)) { | 
|  | 1434 | printk(KERN_WARNING "ide%i: Can't enable PCI device for %s\n", | 
|  | 1435 | i, np->full_name); | 
|  | 1436 | return -ENXIO; | 
|  | 1437 | } | 
|  | 1438 | pci_set_master(pdev); | 
|  | 1439 |  | 
|  | 1440 | if (pci_request_regions(pdev, "Kauai ATA")) { | 
|  | 1441 | printk(KERN_ERR "ide%d: Cannot obtain PCI resources for %s\n", | 
|  | 1442 | i, np->full_name); | 
|  | 1443 | return -ENXIO; | 
|  | 1444 | } | 
|  | 1445 |  | 
|  | 1446 | hwif->pci_dev = pdev; | 
|  | 1447 | hwif->gendev.parent = &pdev->dev; | 
|  | 1448 | pmif->mdev = NULL; | 
|  | 1449 | pmif->node = np; | 
|  | 1450 |  | 
|  | 1451 | rbase = pci_resource_start(pdev, 0); | 
|  | 1452 | rlen = pci_resource_len(pdev, 0); | 
|  | 1453 |  | 
|  | 1454 | base = ioremap(rbase, rlen); | 
|  | 1455 | pmif->regbase = (unsigned long) base + 0x2000; | 
|  | 1456 | #ifdef CONFIG_BLK_DEV_IDEDMA_PMAC | 
|  | 1457 | pmif->dma_regs = base + 0x1000; | 
|  | 1458 | #endif /* CONFIG_BLK_DEV_IDEDMA_PMAC */ | 
|  | 1459 | pmif->kauai_fcr = base; | 
|  | 1460 | pmif->irq = pdev->irq; | 
|  | 1461 |  | 
|  | 1462 | pci_set_drvdata(pdev, hwif); | 
|  | 1463 |  | 
|  | 1464 | rc = pmac_ide_setup_device(pmif, hwif); | 
|  | 1465 | if (rc != 0) { | 
|  | 1466 | /* The inteface is released to the common IDE layer */ | 
|  | 1467 | pci_set_drvdata(pdev, NULL); | 
|  | 1468 | iounmap(base); | 
|  | 1469 | memset(pmif, 0, sizeof(*pmif)); | 
|  | 1470 | pci_release_regions(pdev); | 
|  | 1471 | } | 
|  | 1472 |  | 
|  | 1473 | return rc; | 
|  | 1474 | } | 
|  | 1475 |  | 
|  | 1476 | static int | 
| David Brownell | 8b4b8a2 | 2006-08-14 23:11:03 -0700 | [diff] [blame] | 1477 | pmac_ide_pci_suspend(struct pci_dev *pdev, pm_message_t mesg) | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 1478 | { | 
|  | 1479 | ide_hwif_t	*hwif = (ide_hwif_t *)pci_get_drvdata(pdev); | 
|  | 1480 | int		rc = 0; | 
|  | 1481 |  | 
| David Brownell | 8b4b8a2 | 2006-08-14 23:11:03 -0700 | [diff] [blame] | 1482 | if (mesg.event != pdev->dev.power.power_state.event | 
|  | 1483 | && mesg.event == PM_EVENT_SUSPEND) { | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 1484 | rc = pmac_ide_do_suspend(hwif); | 
|  | 1485 | if (rc == 0) | 
| David Brownell | 8b4b8a2 | 2006-08-14 23:11:03 -0700 | [diff] [blame] | 1486 | pdev->dev.power.power_state = mesg; | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 1487 | } | 
|  | 1488 |  | 
|  | 1489 | return rc; | 
|  | 1490 | } | 
|  | 1491 |  | 
|  | 1492 | static int | 
|  | 1493 | pmac_ide_pci_resume(struct pci_dev *pdev) | 
|  | 1494 | { | 
|  | 1495 | ide_hwif_t	*hwif = (ide_hwif_t *)pci_get_drvdata(pdev); | 
|  | 1496 | int		rc = 0; | 
|  | 1497 |  | 
| Pavel Machek | ca078ba | 2005-09-03 15:56:57 -0700 | [diff] [blame] | 1498 | if (pdev->dev.power.power_state.event != PM_EVENT_ON) { | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 1499 | rc = pmac_ide_do_resume(hwif); | 
|  | 1500 | if (rc == 0) | 
| Pavel Machek | 829ca9a | 2005-09-03 15:56:56 -0700 | [diff] [blame] | 1501 | pdev->dev.power.power_state = PMSG_ON; | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 1502 | } | 
|  | 1503 |  | 
|  | 1504 | return rc; | 
|  | 1505 | } | 
|  | 1506 |  | 
| Jeff Mahoney | 5e65577 | 2005-07-06 15:44:41 -0400 | [diff] [blame] | 1507 | static struct of_device_id pmac_ide_macio_match[] = | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 1508 | { | 
|  | 1509 | { | 
|  | 1510 | .name 		= "IDE", | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 1511 | }, | 
|  | 1512 | { | 
|  | 1513 | .name 		= "ATA", | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 1514 | }, | 
|  | 1515 | { | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 1516 | .type		= "ide", | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 1517 | }, | 
|  | 1518 | { | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 1519 | .type		= "ata", | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 1520 | }, | 
|  | 1521 | {}, | 
|  | 1522 | }; | 
|  | 1523 |  | 
|  | 1524 | static struct macio_driver pmac_ide_macio_driver = | 
|  | 1525 | { | 
|  | 1526 | .name 		= "ide-pmac", | 
|  | 1527 | .match_table	= pmac_ide_macio_match, | 
|  | 1528 | .probe		= pmac_ide_macio_attach, | 
|  | 1529 | .suspend	= pmac_ide_macio_suspend, | 
|  | 1530 | .resume		= pmac_ide_macio_resume, | 
|  | 1531 | }; | 
|  | 1532 |  | 
|  | 1533 | static struct pci_device_id pmac_ide_pci_match[] = { | 
| Olof Johansson | 7fce260 | 2005-11-13 16:06:48 -0800 | [diff] [blame] | 1534 | { PCI_VENDOR_ID_APPLE, PCI_DEVICE_ID_APPLE_UNI_N_ATA, | 
|  | 1535 | PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, | 
|  | 1536 | { PCI_VENDOR_ID_APPLE, PCI_DEVICE_ID_APPLE_IPID_ATA100, | 
|  | 1537 | PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, | 
|  | 1538 | { PCI_VENDOR_ID_APPLE, PCI_DEVICE_ID_APPLE_K2_ATA100, | 
|  | 1539 | PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 1540 | { PCI_VENDOR_ID_APPLE, PCI_DEVICE_ID_APPLE_SH_ATA, | 
|  | 1541 | PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, | 
| Olof Johansson | 7fce260 | 2005-11-13 16:06:48 -0800 | [diff] [blame] | 1542 | { PCI_VENDOR_ID_APPLE, PCI_DEVICE_ID_APPLE_IPID2_ATA, | 
|  | 1543 | PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 1544 | }; | 
|  | 1545 |  | 
|  | 1546 | static struct pci_driver pmac_ide_pci_driver = { | 
|  | 1547 | .name		= "ide-pmac", | 
|  | 1548 | .id_table	= pmac_ide_pci_match, | 
|  | 1549 | .probe		= pmac_ide_pci_attach, | 
|  | 1550 | .suspend	= pmac_ide_pci_suspend, | 
|  | 1551 | .resume		= pmac_ide_pci_resume, | 
|  | 1552 | }; | 
|  | 1553 | MODULE_DEVICE_TABLE(pci, pmac_ide_pci_match); | 
|  | 1554 |  | 
|  | 1555 | void __init | 
|  | 1556 | pmac_ide_probe(void) | 
|  | 1557 | { | 
| Benjamin Herrenschmidt | e822250 | 2006-03-28 23:15:54 +1100 | [diff] [blame] | 1558 | if (!machine_is(powermac)) | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 1559 | return; | 
|  | 1560 |  | 
|  | 1561 | #ifdef CONFIG_BLK_DEV_IDE_PMAC_ATA100FIRST | 
|  | 1562 | pci_register_driver(&pmac_ide_pci_driver); | 
|  | 1563 | macio_register_driver(&pmac_ide_macio_driver); | 
|  | 1564 | #else | 
|  | 1565 | macio_register_driver(&pmac_ide_macio_driver); | 
|  | 1566 | pci_register_driver(&pmac_ide_pci_driver); | 
| Benjamin Herrenschmidt | 1beb6a7 | 2005-12-14 13:10:10 +1100 | [diff] [blame] | 1567 | #endif | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 1568 | } | 
|  | 1569 |  | 
|  | 1570 | #ifdef CONFIG_BLK_DEV_IDEDMA_PMAC | 
|  | 1571 |  | 
|  | 1572 | /* | 
|  | 1573 | * pmac_ide_build_dmatable builds the DBDMA command list | 
|  | 1574 | * for a transfer and sets the DBDMA channel to point to it. | 
|  | 1575 | */ | 
| Jon Loeliger | aacaf9b | 2005-09-17 10:36:54 -0500 | [diff] [blame] | 1576 | static int | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 1577 | pmac_ide_build_dmatable(ide_drive_t *drive, struct request *rq) | 
|  | 1578 | { | 
|  | 1579 | struct dbdma_cmd *table; | 
|  | 1580 | int i, count = 0; | 
|  | 1581 | ide_hwif_t *hwif = HWIF(drive); | 
|  | 1582 | pmac_ide_hwif_t* pmif = (pmac_ide_hwif_t *)hwif->hwif_data; | 
|  | 1583 | volatile struct dbdma_regs __iomem *dma = pmif->dma_regs; | 
|  | 1584 | struct scatterlist *sg; | 
|  | 1585 | int wr = (rq_data_dir(rq) == WRITE); | 
|  | 1586 |  | 
|  | 1587 | /* DMA table is already aligned */ | 
|  | 1588 | table = (struct dbdma_cmd *) pmif->dma_table_cpu; | 
|  | 1589 |  | 
|  | 1590 | /* Make sure DMA controller is stopped (necessary ?) */ | 
|  | 1591 | writel((RUN|PAUSE|FLUSH|WAKE|DEAD) << 16, &dma->control); | 
|  | 1592 | while (readl(&dma->status) & RUN) | 
|  | 1593 | udelay(1); | 
|  | 1594 |  | 
|  | 1595 | hwif->sg_nents = i = ide_build_sglist(drive, rq); | 
|  | 1596 |  | 
|  | 1597 | if (!i) | 
|  | 1598 | return 0; | 
|  | 1599 |  | 
|  | 1600 | /* Build DBDMA commands list */ | 
|  | 1601 | sg = hwif->sg_table; | 
|  | 1602 | while (i && sg_dma_len(sg)) { | 
|  | 1603 | u32 cur_addr; | 
|  | 1604 | u32 cur_len; | 
|  | 1605 |  | 
|  | 1606 | cur_addr = sg_dma_address(sg); | 
|  | 1607 | cur_len = sg_dma_len(sg); | 
|  | 1608 |  | 
|  | 1609 | if (pmif->broken_dma && cur_addr & (L1_CACHE_BYTES - 1)) { | 
|  | 1610 | if (pmif->broken_dma_warn == 0) { | 
|  | 1611 | printk(KERN_WARNING "%s: DMA on non aligned address," | 
|  | 1612 | "switching to PIO on Ohare chipset\n", drive->name); | 
|  | 1613 | pmif->broken_dma_warn = 1; | 
|  | 1614 | } | 
|  | 1615 | goto use_pio_instead; | 
|  | 1616 | } | 
|  | 1617 | while (cur_len) { | 
|  | 1618 | unsigned int tc = (cur_len < 0xfe00)? cur_len: 0xfe00; | 
|  | 1619 |  | 
|  | 1620 | if (count++ >= MAX_DCMDS) { | 
|  | 1621 | printk(KERN_WARNING "%s: DMA table too small\n", | 
|  | 1622 | drive->name); | 
|  | 1623 | goto use_pio_instead; | 
|  | 1624 | } | 
|  | 1625 | st_le16(&table->command, wr? OUTPUT_MORE: INPUT_MORE); | 
|  | 1626 | st_le16(&table->req_count, tc); | 
|  | 1627 | st_le32(&table->phy_addr, cur_addr); | 
|  | 1628 | table->cmd_dep = 0; | 
|  | 1629 | table->xfer_status = 0; | 
|  | 1630 | table->res_count = 0; | 
|  | 1631 | cur_addr += tc; | 
|  | 1632 | cur_len -= tc; | 
|  | 1633 | ++table; | 
|  | 1634 | } | 
|  | 1635 | sg++; | 
|  | 1636 | i--; | 
|  | 1637 | } | 
|  | 1638 |  | 
|  | 1639 | /* convert the last command to an input/output last command */ | 
|  | 1640 | if (count) { | 
|  | 1641 | st_le16(&table[-1].command, wr? OUTPUT_LAST: INPUT_LAST); | 
|  | 1642 | /* add the stop command to the end of the list */ | 
|  | 1643 | memset(table, 0, sizeof(struct dbdma_cmd)); | 
|  | 1644 | st_le16(&table->command, DBDMA_STOP); | 
|  | 1645 | mb(); | 
|  | 1646 | writel(hwif->dmatable_dma, &dma->cmdptr); | 
|  | 1647 | return 1; | 
|  | 1648 | } | 
|  | 1649 |  | 
|  | 1650 | printk(KERN_DEBUG "%s: empty DMA table?\n", drive->name); | 
|  | 1651 | use_pio_instead: | 
|  | 1652 | pci_unmap_sg(hwif->pci_dev, | 
|  | 1653 | hwif->sg_table, | 
|  | 1654 | hwif->sg_nents, | 
|  | 1655 | hwif->sg_dma_direction); | 
|  | 1656 | return 0; /* revert to PIO for this request */ | 
|  | 1657 | } | 
|  | 1658 |  | 
|  | 1659 | /* Teardown mappings after DMA has completed.  */ | 
| Jon Loeliger | aacaf9b | 2005-09-17 10:36:54 -0500 | [diff] [blame] | 1660 | static void | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 1661 | pmac_ide_destroy_dmatable (ide_drive_t *drive) | 
|  | 1662 | { | 
|  | 1663 | ide_hwif_t *hwif = drive->hwif; | 
|  | 1664 | struct pci_dev *dev = HWIF(drive)->pci_dev; | 
|  | 1665 | struct scatterlist *sg = hwif->sg_table; | 
|  | 1666 | int nents = hwif->sg_nents; | 
|  | 1667 |  | 
|  | 1668 | if (nents) { | 
|  | 1669 | pci_unmap_sg(dev, sg, nents, hwif->sg_dma_direction); | 
|  | 1670 | hwif->sg_nents = 0; | 
|  | 1671 | } | 
|  | 1672 | } | 
|  | 1673 |  | 
|  | 1674 | /* | 
|  | 1675 | * Pick up best MDMA timing for the drive and apply it | 
|  | 1676 | */ | 
| Jon Loeliger | aacaf9b | 2005-09-17 10:36:54 -0500 | [diff] [blame] | 1677 | static int | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 1678 | pmac_ide_mdma_enable(ide_drive_t *drive, u16 mode) | 
|  | 1679 | { | 
|  | 1680 | ide_hwif_t *hwif = HWIF(drive); | 
|  | 1681 | pmac_ide_hwif_t* pmif = (pmac_ide_hwif_t *)hwif->hwif_data; | 
|  | 1682 | int drive_cycle_time; | 
|  | 1683 | struct hd_driveid *id = drive->id; | 
|  | 1684 | u32 *timings, *timings2; | 
|  | 1685 | u32 timing_local[2]; | 
|  | 1686 | int ret; | 
|  | 1687 |  | 
|  | 1688 | /* which drive is it ? */ | 
|  | 1689 | timings = &pmif->timings[drive->select.b.unit & 0x01]; | 
|  | 1690 | timings2 = &pmif->timings[(drive->select.b.unit & 0x01) + 2]; | 
|  | 1691 |  | 
|  | 1692 | /* Check if drive provide explicit cycle time */ | 
|  | 1693 | if ((id->field_valid & 2) && (id->eide_dma_time)) | 
|  | 1694 | drive_cycle_time = id->eide_dma_time; | 
|  | 1695 | else | 
|  | 1696 | drive_cycle_time = 0; | 
|  | 1697 |  | 
|  | 1698 | /* Copy timings to local image */ | 
|  | 1699 | timing_local[0] = *timings; | 
|  | 1700 | timing_local[1] = *timings2; | 
|  | 1701 |  | 
|  | 1702 | /* Calculate controller timings */ | 
|  | 1703 | ret = set_timings_mdma(	drive, pmif->kind, | 
|  | 1704 | &timing_local[0], | 
|  | 1705 | &timing_local[1], | 
|  | 1706 | mode, | 
|  | 1707 | drive_cycle_time); | 
|  | 1708 | if (ret) | 
|  | 1709 | return 0; | 
|  | 1710 |  | 
|  | 1711 | /* Set feature on drive */ | 
|  | 1712 | printk(KERN_INFO "%s: Enabling MultiWord DMA %d\n", drive->name, mode & 0xf); | 
|  | 1713 | ret = pmac_ide_do_setfeature(drive, mode); | 
|  | 1714 | if (ret) { | 
|  | 1715 | printk(KERN_WARNING "%s: Failed !\n", drive->name); | 
|  | 1716 | return 0; | 
|  | 1717 | } | 
|  | 1718 |  | 
|  | 1719 | /* Apply timings to controller */ | 
|  | 1720 | *timings = timing_local[0]; | 
|  | 1721 | *timings2 = timing_local[1]; | 
|  | 1722 |  | 
|  | 1723 | /* Set speed info in drive */ | 
|  | 1724 | drive->current_speed = mode; | 
|  | 1725 | if (!drive->init_speed) | 
|  | 1726 | drive->init_speed = mode; | 
|  | 1727 |  | 
|  | 1728 | return 1; | 
|  | 1729 | } | 
|  | 1730 |  | 
|  | 1731 | /* | 
|  | 1732 | * Pick up best UDMA timing for the drive and apply it | 
|  | 1733 | */ | 
| Jon Loeliger | aacaf9b | 2005-09-17 10:36:54 -0500 | [diff] [blame] | 1734 | static int | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 1735 | pmac_ide_udma_enable(ide_drive_t *drive, u16 mode) | 
|  | 1736 | { | 
|  | 1737 | ide_hwif_t *hwif = HWIF(drive); | 
|  | 1738 | pmac_ide_hwif_t* pmif = (pmac_ide_hwif_t *)hwif->hwif_data; | 
|  | 1739 | u32 *timings, *timings2; | 
|  | 1740 | u32 timing_local[2]; | 
|  | 1741 | int ret; | 
|  | 1742 |  | 
|  | 1743 | /* which drive is it ? */ | 
|  | 1744 | timings = &pmif->timings[drive->select.b.unit & 0x01]; | 
|  | 1745 | timings2 = &pmif->timings[(drive->select.b.unit & 0x01) + 2]; | 
|  | 1746 |  | 
|  | 1747 | /* Copy timings to local image */ | 
|  | 1748 | timing_local[0] = *timings; | 
|  | 1749 | timing_local[1] = *timings2; | 
|  | 1750 |  | 
|  | 1751 | /* Calculate timings for interface */ | 
|  | 1752 | if (pmif->kind == controller_un_ata6 | 
|  | 1753 | || pmif->kind == controller_k2_ata6) | 
|  | 1754 | ret = set_timings_udma_ata6(	&timing_local[0], | 
|  | 1755 | &timing_local[1], | 
|  | 1756 | mode); | 
|  | 1757 | else if (pmif->kind == controller_sh_ata6) | 
|  | 1758 | ret = set_timings_udma_shasta(	&timing_local[0], | 
|  | 1759 | &timing_local[1], | 
|  | 1760 | mode); | 
|  | 1761 | else | 
|  | 1762 | ret = set_timings_udma_ata4(&timing_local[0], mode); | 
|  | 1763 | if (ret) | 
|  | 1764 | return 0; | 
|  | 1765 |  | 
|  | 1766 | /* Set feature on drive */ | 
|  | 1767 | printk(KERN_INFO "%s: Enabling Ultra DMA %d\n", drive->name, mode & 0x0f); | 
|  | 1768 | ret = pmac_ide_do_setfeature(drive, mode); | 
|  | 1769 | if (ret) { | 
|  | 1770 | printk(KERN_WARNING "%s: Failed !\n", drive->name); | 
|  | 1771 | return 0; | 
|  | 1772 | } | 
|  | 1773 |  | 
|  | 1774 | /* Apply timings to controller */ | 
|  | 1775 | *timings = timing_local[0]; | 
|  | 1776 | *timings2 = timing_local[1]; | 
|  | 1777 |  | 
|  | 1778 | /* Set speed info in drive */ | 
|  | 1779 | drive->current_speed = mode; | 
|  | 1780 | if (!drive->init_speed) | 
|  | 1781 | drive->init_speed = mode; | 
|  | 1782 |  | 
|  | 1783 | return 1; | 
|  | 1784 | } | 
|  | 1785 |  | 
|  | 1786 | /* | 
|  | 1787 | * Check what is the best DMA timing setting for the drive and | 
|  | 1788 | * call appropriate functions to apply it. | 
|  | 1789 | */ | 
| Jon Loeliger | aacaf9b | 2005-09-17 10:36:54 -0500 | [diff] [blame] | 1790 | static int | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 1791 | pmac_ide_dma_check(ide_drive_t *drive) | 
|  | 1792 | { | 
|  | 1793 | struct hd_driveid *id = drive->id; | 
|  | 1794 | ide_hwif_t *hwif = HWIF(drive); | 
|  | 1795 | pmac_ide_hwif_t* pmif = (pmac_ide_hwif_t *)hwif->hwif_data; | 
|  | 1796 | int enable = 1; | 
|  | 1797 | int map; | 
|  | 1798 | drive->using_dma = 0; | 
|  | 1799 |  | 
|  | 1800 | if (drive->media == ide_floppy) | 
|  | 1801 | enable = 0; | 
|  | 1802 | if (((id->capability & 1) == 0) && !__ide_dma_good_drive(drive)) | 
|  | 1803 | enable = 0; | 
|  | 1804 | if (__ide_dma_bad_drive(drive)) | 
|  | 1805 | enable = 0; | 
|  | 1806 |  | 
|  | 1807 | if (enable) { | 
|  | 1808 | short mode; | 
|  | 1809 |  | 
|  | 1810 | map = XFER_MWDMA; | 
|  | 1811 | if (pmif->kind == controller_kl_ata4 | 
|  | 1812 | || pmif->kind == controller_un_ata6 | 
|  | 1813 | || pmif->kind == controller_k2_ata6 | 
|  | 1814 | || pmif->kind == controller_sh_ata6) { | 
|  | 1815 | map |= XFER_UDMA; | 
|  | 1816 | if (pmif->cable_80) { | 
|  | 1817 | map |= XFER_UDMA_66; | 
|  | 1818 | if (pmif->kind == controller_un_ata6 || | 
|  | 1819 | pmif->kind == controller_k2_ata6 || | 
|  | 1820 | pmif->kind == controller_sh_ata6) | 
|  | 1821 | map |= XFER_UDMA_100; | 
|  | 1822 | if (pmif->kind == controller_sh_ata6) | 
|  | 1823 | map |= XFER_UDMA_133; | 
|  | 1824 | } | 
|  | 1825 | } | 
|  | 1826 | mode = ide_find_best_mode(drive, map); | 
|  | 1827 | if (mode & XFER_UDMA) | 
|  | 1828 | drive->using_dma = pmac_ide_udma_enable(drive, mode); | 
|  | 1829 | else if (mode & XFER_MWDMA) | 
|  | 1830 | drive->using_dma = pmac_ide_mdma_enable(drive, mode); | 
|  | 1831 | hwif->OUTB(0, IDE_CONTROL_REG); | 
|  | 1832 | /* Apply settings to controller */ | 
|  | 1833 | pmac_ide_do_update_timings(drive); | 
|  | 1834 | } | 
|  | 1835 | return 0; | 
|  | 1836 | } | 
|  | 1837 |  | 
|  | 1838 | /* | 
|  | 1839 | * Prepare a DMA transfer. We build the DMA table, adjust the timings for | 
|  | 1840 | * a read on KeyLargo ATA/66 and mark us as waiting for DMA completion | 
|  | 1841 | */ | 
| Jon Loeliger | aacaf9b | 2005-09-17 10:36:54 -0500 | [diff] [blame] | 1842 | static int | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 1843 | pmac_ide_dma_setup(ide_drive_t *drive) | 
|  | 1844 | { | 
|  | 1845 | ide_hwif_t *hwif = HWIF(drive); | 
|  | 1846 | pmac_ide_hwif_t* pmif = (pmac_ide_hwif_t *)hwif->hwif_data; | 
|  | 1847 | struct request *rq = HWGROUP(drive)->rq; | 
|  | 1848 | u8 unit = (drive->select.b.unit & 0x01); | 
|  | 1849 | u8 ata4; | 
|  | 1850 |  | 
|  | 1851 | if (pmif == NULL) | 
|  | 1852 | return 1; | 
|  | 1853 | ata4 = (pmif->kind == controller_kl_ata4); | 
|  | 1854 |  | 
|  | 1855 | if (!pmac_ide_build_dmatable(drive, rq)) { | 
|  | 1856 | ide_map_sg(drive, rq); | 
|  | 1857 | return 1; | 
|  | 1858 | } | 
|  | 1859 |  | 
|  | 1860 | /* Apple adds 60ns to wrDataSetup on reads */ | 
|  | 1861 | if (ata4 && (pmif->timings[unit] & TR_66_UDMA_EN)) { | 
|  | 1862 | writel(pmif->timings[unit] + (!rq_data_dir(rq) ? 0x00800000UL : 0), | 
|  | 1863 | PMAC_IDE_REG(IDE_TIMING_CONFIG)); | 
|  | 1864 | (void)readl(PMAC_IDE_REG(IDE_TIMING_CONFIG)); | 
|  | 1865 | } | 
|  | 1866 |  | 
|  | 1867 | drive->waiting_for_dma = 1; | 
|  | 1868 |  | 
|  | 1869 | return 0; | 
|  | 1870 | } | 
|  | 1871 |  | 
| Jon Loeliger | aacaf9b | 2005-09-17 10:36:54 -0500 | [diff] [blame] | 1872 | static void | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 1873 | pmac_ide_dma_exec_cmd(ide_drive_t *drive, u8 command) | 
|  | 1874 | { | 
|  | 1875 | /* issue cmd to drive */ | 
|  | 1876 | ide_execute_command(drive, command, &ide_dma_intr, 2*WAIT_CMD, NULL); | 
|  | 1877 | } | 
|  | 1878 |  | 
|  | 1879 | /* | 
|  | 1880 | * Kick the DMA controller into life after the DMA command has been issued | 
|  | 1881 | * to the drive. | 
|  | 1882 | */ | 
| Jon Loeliger | aacaf9b | 2005-09-17 10:36:54 -0500 | [diff] [blame] | 1883 | static void | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 1884 | pmac_ide_dma_start(ide_drive_t *drive) | 
|  | 1885 | { | 
|  | 1886 | pmac_ide_hwif_t* pmif = (pmac_ide_hwif_t *)HWIF(drive)->hwif_data; | 
|  | 1887 | volatile struct dbdma_regs __iomem *dma; | 
|  | 1888 |  | 
|  | 1889 | dma = pmif->dma_regs; | 
|  | 1890 |  | 
|  | 1891 | writel((RUN << 16) | RUN, &dma->control); | 
|  | 1892 | /* Make sure it gets to the controller right now */ | 
|  | 1893 | (void)readl(&dma->control); | 
|  | 1894 | } | 
|  | 1895 |  | 
|  | 1896 | /* | 
|  | 1897 | * After a DMA transfer, make sure the controller is stopped | 
|  | 1898 | */ | 
| Jon Loeliger | aacaf9b | 2005-09-17 10:36:54 -0500 | [diff] [blame] | 1899 | static int | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 1900 | pmac_ide_dma_end (ide_drive_t *drive) | 
|  | 1901 | { | 
|  | 1902 | pmac_ide_hwif_t* pmif = (pmac_ide_hwif_t *)HWIF(drive)->hwif_data; | 
|  | 1903 | volatile struct dbdma_regs __iomem *dma; | 
|  | 1904 | u32 dstat; | 
|  | 1905 |  | 
|  | 1906 | if (pmif == NULL) | 
|  | 1907 | return 0; | 
|  | 1908 | dma = pmif->dma_regs; | 
|  | 1909 |  | 
|  | 1910 | drive->waiting_for_dma = 0; | 
|  | 1911 | dstat = readl(&dma->status); | 
|  | 1912 | writel(((RUN|WAKE|DEAD) << 16), &dma->control); | 
|  | 1913 | pmac_ide_destroy_dmatable(drive); | 
|  | 1914 | /* verify good dma status. we don't check for ACTIVE beeing 0. We should... | 
|  | 1915 | * in theory, but with ATAPI decices doing buffer underruns, that would | 
|  | 1916 | * cause us to disable DMA, which isn't what we want | 
|  | 1917 | */ | 
|  | 1918 | return (dstat & (RUN|DEAD)) != RUN; | 
|  | 1919 | } | 
|  | 1920 |  | 
|  | 1921 | /* | 
|  | 1922 | * Check out that the interrupt we got was for us. We can't always know this | 
|  | 1923 | * for sure with those Apple interfaces (well, we could on the recent ones but | 
|  | 1924 | * that's not implemented yet), on the other hand, we don't have shared interrupts | 
|  | 1925 | * so it's not really a problem | 
|  | 1926 | */ | 
| Jon Loeliger | aacaf9b | 2005-09-17 10:36:54 -0500 | [diff] [blame] | 1927 | static int | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 1928 | pmac_ide_dma_test_irq (ide_drive_t *drive) | 
|  | 1929 | { | 
|  | 1930 | pmac_ide_hwif_t* pmif = (pmac_ide_hwif_t *)HWIF(drive)->hwif_data; | 
|  | 1931 | volatile struct dbdma_regs __iomem *dma; | 
|  | 1932 | unsigned long status, timeout; | 
|  | 1933 |  | 
|  | 1934 | if (pmif == NULL) | 
|  | 1935 | return 0; | 
|  | 1936 | dma = pmif->dma_regs; | 
|  | 1937 |  | 
|  | 1938 | /* We have to things to deal with here: | 
|  | 1939 | * | 
|  | 1940 | * - The dbdma won't stop if the command was started | 
|  | 1941 | * but completed with an error without transferring all | 
|  | 1942 | * datas. This happens when bad blocks are met during | 
|  | 1943 | * a multi-block transfer. | 
|  | 1944 | * | 
|  | 1945 | * - The dbdma fifo hasn't yet finished flushing to | 
|  | 1946 | * to system memory when the disk interrupt occurs. | 
|  | 1947 | * | 
|  | 1948 | */ | 
|  | 1949 |  | 
|  | 1950 | /* If ACTIVE is cleared, the STOP command have passed and | 
|  | 1951 | * transfer is complete. | 
|  | 1952 | */ | 
|  | 1953 | status = readl(&dma->status); | 
|  | 1954 | if (!(status & ACTIVE)) | 
|  | 1955 | return 1; | 
|  | 1956 | if (!drive->waiting_for_dma) | 
|  | 1957 | printk(KERN_WARNING "ide%d, ide_dma_test_irq \ | 
|  | 1958 | called while not waiting\n", HWIF(drive)->index); | 
|  | 1959 |  | 
|  | 1960 | /* If dbdma didn't execute the STOP command yet, the | 
|  | 1961 | * active bit is still set. We consider that we aren't | 
|  | 1962 | * sharing interrupts (which is hopefully the case with | 
|  | 1963 | * those controllers) and so we just try to flush the | 
|  | 1964 | * channel for pending data in the fifo | 
|  | 1965 | */ | 
|  | 1966 | udelay(1); | 
|  | 1967 | writel((FLUSH << 16) | FLUSH, &dma->control); | 
|  | 1968 | timeout = 0; | 
|  | 1969 | for (;;) { | 
|  | 1970 | udelay(1); | 
|  | 1971 | status = readl(&dma->status); | 
|  | 1972 | if ((status & FLUSH) == 0) | 
|  | 1973 | break; | 
|  | 1974 | if (++timeout > 100) { | 
|  | 1975 | printk(KERN_WARNING "ide%d, ide_dma_test_irq \ | 
|  | 1976 | timeout flushing channel\n", HWIF(drive)->index); | 
|  | 1977 | break; | 
|  | 1978 | } | 
|  | 1979 | } | 
|  | 1980 | return 1; | 
|  | 1981 | } | 
|  | 1982 |  | 
| Jon Loeliger | aacaf9b | 2005-09-17 10:36:54 -0500 | [diff] [blame] | 1983 | static int | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 1984 | pmac_ide_dma_host_off (ide_drive_t *drive) | 
|  | 1985 | { | 
|  | 1986 | return 0; | 
|  | 1987 | } | 
|  | 1988 |  | 
| Jon Loeliger | aacaf9b | 2005-09-17 10:36:54 -0500 | [diff] [blame] | 1989 | static int | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 1990 | pmac_ide_dma_host_on (ide_drive_t *drive) | 
|  | 1991 | { | 
|  | 1992 | return 0; | 
|  | 1993 | } | 
|  | 1994 |  | 
| Jon Loeliger | aacaf9b | 2005-09-17 10:36:54 -0500 | [diff] [blame] | 1995 | static int | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 1996 | pmac_ide_dma_lostirq (ide_drive_t *drive) | 
|  | 1997 | { | 
|  | 1998 | pmac_ide_hwif_t* pmif = (pmac_ide_hwif_t *)HWIF(drive)->hwif_data; | 
|  | 1999 | volatile struct dbdma_regs __iomem *dma; | 
|  | 2000 | unsigned long status; | 
|  | 2001 |  | 
|  | 2002 | if (pmif == NULL) | 
|  | 2003 | return 0; | 
|  | 2004 | dma = pmif->dma_regs; | 
|  | 2005 |  | 
|  | 2006 | status = readl(&dma->status); | 
|  | 2007 | printk(KERN_ERR "ide-pmac lost interrupt, dma status: %lx\n", status); | 
|  | 2008 | return 0; | 
|  | 2009 | } | 
|  | 2010 |  | 
|  | 2011 | /* | 
|  | 2012 | * Allocate the data structures needed for using DMA with an interface | 
|  | 2013 | * and fill the proper list of functions pointers | 
|  | 2014 | */ | 
|  | 2015 | static void __init | 
|  | 2016 | pmac_ide_setup_dma(pmac_ide_hwif_t *pmif, ide_hwif_t *hwif) | 
|  | 2017 | { | 
|  | 2018 | /* We won't need pci_dev if we switch to generic consistent | 
|  | 2019 | * DMA routines ... | 
|  | 2020 | */ | 
|  | 2021 | if (hwif->pci_dev == NULL) | 
|  | 2022 | return; | 
|  | 2023 | /* | 
|  | 2024 | * Allocate space for the DBDMA commands. | 
|  | 2025 | * The +2 is +1 for the stop command and +1 to allow for | 
|  | 2026 | * aligning the start address to a multiple of 16 bytes. | 
|  | 2027 | */ | 
|  | 2028 | pmif->dma_table_cpu = (struct dbdma_cmd*)pci_alloc_consistent( | 
|  | 2029 | hwif->pci_dev, | 
|  | 2030 | (MAX_DCMDS + 2) * sizeof(struct dbdma_cmd), | 
|  | 2031 | &hwif->dmatable_dma); | 
|  | 2032 | if (pmif->dma_table_cpu == NULL) { | 
|  | 2033 | printk(KERN_ERR "%s: unable to allocate DMA command list\n", | 
|  | 2034 | hwif->name); | 
|  | 2035 | return; | 
|  | 2036 | } | 
|  | 2037 |  | 
|  | 2038 | hwif->ide_dma_off_quietly = &__ide_dma_off_quietly; | 
|  | 2039 | hwif->ide_dma_on = &__ide_dma_on; | 
|  | 2040 | hwif->ide_dma_check = &pmac_ide_dma_check; | 
|  | 2041 | hwif->dma_setup = &pmac_ide_dma_setup; | 
|  | 2042 | hwif->dma_exec_cmd = &pmac_ide_dma_exec_cmd; | 
|  | 2043 | hwif->dma_start = &pmac_ide_dma_start; | 
|  | 2044 | hwif->ide_dma_end = &pmac_ide_dma_end; | 
|  | 2045 | hwif->ide_dma_test_irq = &pmac_ide_dma_test_irq; | 
|  | 2046 | hwif->ide_dma_host_off = &pmac_ide_dma_host_off; | 
|  | 2047 | hwif->ide_dma_host_on = &pmac_ide_dma_host_on; | 
|  | 2048 | hwif->ide_dma_timeout = &__ide_dma_timeout; | 
|  | 2049 | hwif->ide_dma_lostirq = &pmac_ide_dma_lostirq; | 
|  | 2050 |  | 
|  | 2051 | hwif->atapi_dma = 1; | 
|  | 2052 | switch(pmif->kind) { | 
|  | 2053 | case controller_sh_ata6: | 
|  | 2054 | hwif->ultra_mask = pmif->cable_80 ? 0x7f : 0x07; | 
|  | 2055 | hwif->mwdma_mask = 0x07; | 
|  | 2056 | hwif->swdma_mask = 0x00; | 
|  | 2057 | break; | 
|  | 2058 | case controller_un_ata6: | 
|  | 2059 | case controller_k2_ata6: | 
|  | 2060 | hwif->ultra_mask = pmif->cable_80 ? 0x3f : 0x07; | 
|  | 2061 | hwif->mwdma_mask = 0x07; | 
|  | 2062 | hwif->swdma_mask = 0x00; | 
|  | 2063 | break; | 
|  | 2064 | case controller_kl_ata4: | 
|  | 2065 | hwif->ultra_mask = pmif->cable_80 ? 0x1f : 0x07; | 
|  | 2066 | hwif->mwdma_mask = 0x07; | 
|  | 2067 | hwif->swdma_mask = 0x00; | 
|  | 2068 | break; | 
|  | 2069 | default: | 
|  | 2070 | hwif->ultra_mask = 0x00; | 
|  | 2071 | hwif->mwdma_mask = 0x07; | 
|  | 2072 | hwif->swdma_mask = 0x00; | 
|  | 2073 | break; | 
|  | 2074 | } | 
|  | 2075 | } | 
|  | 2076 |  | 
|  | 2077 | #endif /* CONFIG_BLK_DEV_IDEDMA_PMAC */ |