diff options
author | Sergei Shtylyov <sshtylyov@ru.mvista.com> | 2007-03-17 16:57:24 -0400 |
---|---|---|
committer | Bartlomiej Zolnierkiewicz <bzolnier@gmail.com> | 2007-03-17 16:57:24 -0400 |
commit | e277a1aaa97abdc1b0a0b8a8c062e29220b00440 (patch) | |
tree | 9ff0abc93858f4e519be55c2f594114000324961 /drivers/ide | |
parent | cd05a1f818073a623455a58e756c5b419fc98db9 (diff) |
cmd64x: fix recovery time calculation (take 3)
The driver wrongly takes the address setup time into account when calculating
the PIO recovery time -- this leads to slight overclocking of the PIO modes 0
and 1 (so, the prayers failed to help, as usual :-). Rework the code to be
calculating recovery clock count as a difference between the total cycle count
and the active count (we don't need to calculate the recovery time itself since
it's not specified for the PIO modes 0 to 2, and for modes 3 and 4 this formula
gives enough recovery time anyway in the chip's supported PCI frequency range).
This patch has been inspired by reading the datasheets and looking at what the
libata driver does; it has been compile-tested only (as usual :-) but anyway,
the new code gives the same or longer recovery times than the old one...
Signed-off-by: Sergei Shtylyov <sshtylyov@ru.mvista.com>
Signed-off-by: Bartlomiej Zolnierkiewicz <bzolnier@gmail.com>
Diffstat (limited to 'drivers/ide')
-rw-r--r-- | drivers/ide/pci/cmd64x.c | 45 |
1 files changed, 20 insertions, 25 deletions
diff --git a/drivers/ide/pci/cmd64x.c b/drivers/ide/pci/cmd64x.c index b0d4825c56a9..561197f7b5bb 100644 --- a/drivers/ide/pci/cmd64x.c +++ b/drivers/ide/pci/cmd64x.c | |||
@@ -1,6 +1,6 @@ | |||
1 | /* $Id: cmd64x.c,v 1.21 2000/01/30 23:23:16 | 1 | /* $Id: cmd64x.c,v 1.21 2000/01/30 23:23:16 |
2 | * | 2 | * |
3 | * linux/drivers/ide/pci/cmd64x.c Version 1.41 Feb 3, 2007 | 3 | * linux/drivers/ide/pci/cmd64x.c Version 1.42 Feb 8, 2007 |
4 | * | 4 | * |
5 | * cmd64x.c: Enable interrupts at initialization time on Ultra/PCI machines. | 5 | * cmd64x.c: Enable interrupts at initialization time on Ultra/PCI machines. |
6 | * Note, this driver is not used at all on other systems because | 6 | * Note, this driver is not used at all on other systems because |
@@ -189,6 +189,11 @@ static int cmd64x_get_info (char *buffer, char **addr, off_t offset, int count) | |||
189 | 189 | ||
190 | #endif /* defined(DISPLAY_CMD64X_TIMINGS) && defined(CONFIG_PROC_FS) */ | 190 | #endif /* defined(DISPLAY_CMD64X_TIMINGS) && defined(CONFIG_PROC_FS) */ |
191 | 191 | ||
192 | static u8 quantize_timing(int timing, int quant) | ||
193 | { | ||
194 | return (timing + quant - 1) / quant; | ||
195 | } | ||
196 | |||
192 | /* | 197 | /* |
193 | * This routine writes the prepared setup/active/recovery counts | 198 | * This routine writes the prepared setup/active/recovery counts |
194 | * for a drive into the cmd646 chipset registers to active them. | 199 | * for a drive into the cmd646 chipset registers to active them. |
@@ -268,47 +273,37 @@ static void program_drive_counts (ide_drive_t *drive, int setup_count, int activ | |||
268 | */ | 273 | */ |
269 | static u8 cmd64x_tune_pio (ide_drive_t *drive, u8 mode_wanted) | 274 | static u8 cmd64x_tune_pio (ide_drive_t *drive, u8 mode_wanted) |
270 | { | 275 | { |
271 | int setup_time, active_time, recovery_time; | 276 | int setup_time, active_time, cycle_time; |
272 | int clock_time, pio_mode, cycle_time; | 277 | u8 cycle_count, setup_count, active_count, recovery_count; |
273 | u8 recovery_count2, cycle_count; | 278 | u8 pio_mode; |
274 | int setup_count, active_count, recovery_count; | 279 | int clock_time = 1000 / system_bus_clock(); |
275 | int bus_speed = system_bus_clock(); | 280 | ide_pio_data_t pio; |
276 | ide_pio_data_t d; | ||
277 | 281 | ||
278 | pio_mode = ide_get_best_pio_mode(drive, mode_wanted, 5, &d); | 282 | pio_mode = ide_get_best_pio_mode(drive, mode_wanted, 5, &pio); |
279 | cycle_time = d.cycle_time; | 283 | cycle_time = pio.cycle_time; |
280 | 284 | ||
281 | /* | ||
282 | * I copied all this complicated stuff from cmd640.c and made a few | ||
283 | * minor changes. For now I am just going to pray that it is correct. | ||
284 | */ | ||
285 | setup_time = ide_pio_timings[pio_mode].setup_time; | 285 | setup_time = ide_pio_timings[pio_mode].setup_time; |
286 | active_time = ide_pio_timings[pio_mode].active_time; | 286 | active_time = ide_pio_timings[pio_mode].active_time; |
287 | recovery_time = cycle_time - (setup_time + active_time); | ||
288 | clock_time = 1000 / bus_speed; | ||
289 | cycle_count = (cycle_time + clock_time - 1) / clock_time; | ||
290 | |||
291 | setup_count = (setup_time + clock_time - 1) / clock_time; | ||
292 | 287 | ||
293 | active_count = (active_time + clock_time - 1) / clock_time; | 288 | setup_count = quantize_timing( setup_time, clock_time); |
289 | cycle_count = quantize_timing( cycle_time, clock_time); | ||
290 | active_count = quantize_timing(active_time, clock_time); | ||
294 | 291 | ||
295 | recovery_count = (recovery_time + clock_time - 1) / clock_time; | 292 | recovery_count = cycle_count - active_count; |
296 | recovery_count2 = cycle_count - (setup_count + active_count); | 293 | /* program_drive_counts() takes care of zero recovery cycles */ |
297 | if (recovery_count2 > recovery_count) | ||
298 | recovery_count = recovery_count2; | ||
299 | if (recovery_count > 16) { | 294 | if (recovery_count > 16) { |
300 | active_count += recovery_count - 16; | 295 | active_count += recovery_count - 16; |
301 | recovery_count = 16; | 296 | recovery_count = 16; |
302 | } | 297 | } |
303 | if (active_count > 16) | 298 | if (active_count > 16) |
304 | active_count = 16; /* maximum allowed by cmd646 */ | 299 | active_count = 16; /* maximum allowed by cmd64x */ |
305 | 300 | ||
306 | program_drive_counts (drive, setup_count, active_count, recovery_count); | 301 | program_drive_counts (drive, setup_count, active_count, recovery_count); |
307 | 302 | ||
308 | cmdprintk("%s: PIO mode wanted %d, selected %d (%dns)%s, " | 303 | cmdprintk("%s: PIO mode wanted %d, selected %d (%dns)%s, " |
309 | "clocks=%d/%d/%d\n", | 304 | "clocks=%d/%d/%d\n", |
310 | drive->name, mode_wanted, pio_mode, cycle_time, | 305 | drive->name, mode_wanted, pio_mode, cycle_time, |
311 | d.overridden ? " (overriding vendor mode)" : "", | 306 | pio.overridden ? " (overriding vendor mode)" : "", |
312 | setup_count, active_count, recovery_count); | 307 | setup_count, active_count, recovery_count); |
313 | 308 | ||
314 | return pio_mode; | 309 | return pio_mode; |