diff options
author | Bartlomiej Zolnierkiewicz <bzolnier@gmail.com> | 2008-06-15 15:00:22 -0400 |
---|---|---|
committer | Bartlomiej Zolnierkiewicz <bzolnier@gmail.com> | 2008-06-15 15:00:22 -0400 |
commit | 6c987183fcc3c6cb9eb77fd0b3e8ca1ac98a4813 (patch) | |
tree | 14176c7fdd1a0892f4bb593d64fd7cd9cac45aa4 | |
parent | 21bd33a656a60daadc475ce330272f4410ae27b7 (diff) |
opti621: program devices timings separately in ->set_pio_mode
* Set drive->drive_data to 'pio + XFER_PIO_0' instead of 'pio',
then simplify selecting maximum adress setup timing.
* Remove no longer needed compute_pios() and opti621_port_init_devs().
* Program devices timings separately in ->set_pio_mode.
Based on a bugreport from Juergen Kosel & inspired by pata_opti.c code.
Tested-by: Juergen Kosel <juergen.kosel@gmx.de>
Signed-off-by: Bartlomiej Zolnierkiewicz <bzolnier@gmail.com>
-rw-r--r-- | drivers/ide/pci/opti621.c | 80 |
1 files changed, 15 insertions, 65 deletions
diff --git a/drivers/ide/pci/opti621.c b/drivers/ide/pci/opti621.c index 7547fa2d83ac..c746e6f06077 100644 --- a/drivers/ide/pci/opti621.c +++ b/drivers/ide/pci/opti621.c | |||
@@ -115,34 +115,6 @@ static int reg_base; | |||
115 | 115 | ||
116 | static DEFINE_SPINLOCK(opti621_lock); | 116 | static DEFINE_SPINLOCK(opti621_lock); |
117 | 117 | ||
118 | /* there are stored pio numbers from other calls of opti621_set_pio_mode */ | ||
119 | static void compute_pios(ide_drive_t *drive, const u8 pio) | ||
120 | /* Store values into drive->drive_data | ||
121 | * second_contr - 0 for primary controller, 1 for secondary | ||
122 | * slave_drive - 0 -> pio is for master, 1 -> pio is for slave | ||
123 | * pio - PIO mode for selected drive (for other we don't know) | ||
124 | */ | ||
125 | { | ||
126 | int d; | ||
127 | ide_hwif_t *hwif = HWIF(drive); | ||
128 | |||
129 | drive->drive_data = pio; | ||
130 | |||
131 | for (d = 0; d < 2; ++d) { | ||
132 | drive = &hwif->drives[d]; | ||
133 | if (drive->present) { | ||
134 | if (drive->drive_data == PIO_DONT_KNOW) | ||
135 | drive->drive_data = ide_get_best_pio_mode(drive, 255, 3); | ||
136 | #ifdef OPTI621_DEBUG | ||
137 | printk("%s: Selected PIO mode %d\n", | ||
138 | drive->name, drive->drive_data); | ||
139 | #endif | ||
140 | } else { | ||
141 | drive->drive_data = PIO_NOT_EXIST; | ||
142 | } | ||
143 | } | ||
144 | } | ||
145 | |||
146 | static int cmpt_clk(int time, int bus_speed) | 118 | static int cmpt_clk(int time, int bus_speed) |
147 | /* Returns (rounded up) time in clocks for time in ns, | 119 | /* Returns (rounded up) time in clocks for time in ns, |
148 | * with bus_speed in MHz. | 120 | * with bus_speed in MHz. |
@@ -226,20 +198,19 @@ static void compute_clocks(int pio, pio_clocks_t *clks, int bus_speed) | |||
226 | 198 | ||
227 | static void opti621_set_pio_mode(ide_drive_t *drive, const u8 pio) | 199 | static void opti621_set_pio_mode(ide_drive_t *drive, const u8 pio) |
228 | { | 200 | { |
229 | /* primary and secondary drives share some registers, | 201 | ide_hwif_t *hwif = drive->hwif; |
230 | * so we have to program both drives | 202 | ide_drive_t *pair = ide_get_paired_drive(drive); |
231 | */ | ||
232 | unsigned long flags; | 203 | unsigned long flags; |
233 | u8 pio1 = 0, pio2 = 0; | ||
234 | pio_clocks_t first, second; | 204 | pio_clocks_t first, second; |
235 | int ax, drdy; | 205 | int ax, drdy; |
236 | u8 cycle1, cycle2, misc, clk; | 206 | u8 cycle1, misc, clk, addr_pio = pio; |
237 | ide_hwif_t *hwif = HWIF(drive); | ||
238 | 207 | ||
239 | /* sets drive->drive_data for both drives */ | 208 | drive->drive_data = XFER_PIO_0 + pio; |
240 | compute_pios(drive, pio); | 209 | |
241 | pio1 = hwif->drives[0].drive_data; | 210 | if (pair->present) { |
242 | pio2 = hwif->drives[1].drive_data; | 211 | if (pair->drive_data && pair->drive_data < drive->drive_data) |
212 | addr_pio = pair->drive_data - XFER_PIO_0; | ||
213 | } | ||
243 | 214 | ||
244 | spin_lock_irqsave(&opti621_lock, flags); | 215 | spin_lock_irqsave(&opti621_lock, flags); |
245 | 216 | ||
@@ -259,8 +230,8 @@ static void opti621_set_pio_mode(ide_drive_t *drive, const u8 pio) | |||
259 | 230 | ||
260 | printk(KERN_INFO "%s: CLK = %d MHz\n", hwif->name, clk ? 25 : 33); | 231 | printk(KERN_INFO "%s: CLK = %d MHz\n", hwif->name, clk ? 25 : 33); |
261 | 232 | ||
262 | compute_clocks(pio1, &first, clk ? 25 : 33); | 233 | compute_clocks(pio, &first, clk ? 25 : 33); |
263 | compute_clocks(pio2, &second, clk ? 25 : 33); | 234 | compute_clocks(addr_pio, &second, clk ? 25 : 33); |
264 | 235 | ||
265 | /* ax = max(a1,a2) */ | 236 | /* ax = max(a1,a2) */ |
266 | ax = (first.address_time < second.address_time) ? second.address_time : first.address_time; | 237 | ax = (first.address_time < second.address_time) ? second.address_time : first.address_time; |
@@ -268,37 +239,23 @@ static void opti621_set_pio_mode(ide_drive_t *drive, const u8 pio) | |||
268 | drdy = 2; /* DRDY is default 2 (by OPTi Databook) */ | 239 | drdy = 2; /* DRDY is default 2 (by OPTi Databook) */ |
269 | 240 | ||
270 | cycle1 = ((first.data_time-1)<<4) | (first.recovery_time-2); | 241 | cycle1 = ((first.data_time-1)<<4) | (first.recovery_time-2); |
271 | cycle2 = ((second.data_time-1)<<4) | (second.recovery_time-2); | ||
272 | 242 | ||
273 | misc = ((ax - 1) << 4) | ((drdy - 2) << 1); | 243 | misc = ((ax - 1) << 4) | ((drdy - 2) << 1); |
274 | 244 | ||
275 | #ifdef OPTI621_DEBUG | 245 | #ifdef OPTI621_DEBUG |
276 | printk("%s: master: address: %d, data: %d, " | 246 | printk("%s: address: %d, data: %d, " |
277 | "recovery: %d, drdy: %d [clk]\n", | 247 | "recovery: %d, drdy: %d [clk]\n", |
278 | hwif->name, ax, first.data_time, | 248 | drive->name, ax, first.data_time, |
279 | first.recovery_time, drdy); | 249 | first.recovery_time, drdy); |
280 | printk("%s: slave: address: %d, data: %d, " | ||
281 | "recovery: %d, drdy: %d [clk]\n", | ||
282 | hwif->name, ax, second.data_time, | ||
283 | second.recovery_time, drdy); | ||
284 | #endif | 250 | #endif |
285 | 251 | ||
286 | /* program primary drive */ | 252 | /* select Index-0/1 for Register-A/B */ |
287 | /* select Index-0 for Register-A */ | 253 | write_reg(drive->select.b.unit, MISC_REG); |
288 | write_reg(0, MISC_REG); | ||
289 | /* set read cycle timings */ | 254 | /* set read cycle timings */ |
290 | write_reg(cycle1, READ_REG); | 255 | write_reg(cycle1, READ_REG); |
291 | /* set write cycle timings */ | 256 | /* set write cycle timings */ |
292 | write_reg(cycle1, WRITE_REG); | 257 | write_reg(cycle1, WRITE_REG); |
293 | 258 | ||
294 | /* program secondary drive */ | ||
295 | /* select Index-1 for Register-B */ | ||
296 | write_reg(1, MISC_REG); | ||
297 | /* set read cycle timings */ | ||
298 | write_reg(cycle2, READ_REG); | ||
299 | /* set write cycle timings */ | ||
300 | write_reg(cycle2, WRITE_REG); | ||
301 | |||
302 | /* use Register-A for drive 0 */ | 259 | /* use Register-A for drive 0 */ |
303 | /* use Register-B for drive 1 */ | 260 | /* use Register-B for drive 1 */ |
304 | write_reg(0x85, CNTRL_REG); | 261 | write_reg(0x85, CNTRL_REG); |
@@ -310,14 +267,7 @@ static void opti621_set_pio_mode(ide_drive_t *drive, const u8 pio) | |||
310 | spin_unlock_irqrestore(&opti621_lock, flags); | 267 | spin_unlock_irqrestore(&opti621_lock, flags); |
311 | } | 268 | } |
312 | 269 | ||
313 | static void __devinit opti621_port_init_devs(ide_hwif_t *hwif) | ||
314 | { | ||
315 | hwif->drives[0].drive_data = PIO_DONT_KNOW; | ||
316 | hwif->drives[1].drive_data = PIO_DONT_KNOW; | ||
317 | } | ||
318 | |||
319 | static const struct ide_port_ops opti621_port_ops = { | 270 | static const struct ide_port_ops opti621_port_ops = { |
320 | .port_init_devs = opti621_port_init_devs, | ||
321 | .set_pio_mode = opti621_set_pio_mode, | 271 | .set_pio_mode = opti621_set_pio_mode, |
322 | }; | 272 | }; |
323 | 273 | ||