forked from Minki/linux
opti621: use pre-calculated PIO timings
* Use pre-calculated PIO timings in ->set_pio_mode. * Remove no longer needed compute_clocks(), cmpt_clk(), struct pio_clocks_s, PIO_* defines and OPTI621_DEBUG define. There should be no functional changes caused by this patch. 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>
This commit is contained in:
parent
6c987183fc
commit
810253d44b
@ -81,8 +81,6 @@
|
|||||||
* 0.5 doesn't work.
|
* 0.5 doesn't work.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#define OPTI621_DEBUG /* define for debug messages */
|
|
||||||
|
|
||||||
#include <linux/types.h>
|
#include <linux/types.h>
|
||||||
#include <linux/module.h>
|
#include <linux/module.h>
|
||||||
#include <linux/kernel.h>
|
#include <linux/kernel.h>
|
||||||
@ -110,23 +108,8 @@
|
|||||||
|
|
||||||
static int reg_base;
|
static int reg_base;
|
||||||
|
|
||||||
#define PIO_NOT_EXIST 254
|
|
||||||
#define PIO_DONT_KNOW 255
|
|
||||||
|
|
||||||
static DEFINE_SPINLOCK(opti621_lock);
|
static DEFINE_SPINLOCK(opti621_lock);
|
||||||
|
|
||||||
static int cmpt_clk(int time, int bus_speed)
|
|
||||||
/* Returns (rounded up) time in clocks for time in ns,
|
|
||||||
* with bus_speed in MHz.
|
|
||||||
* Example: bus_speed = 40 MHz, time = 80 ns
|
|
||||||
* 1000/40 = 25 ns (clk value),
|
|
||||||
* 80/25 = 3.2, rounded up to 4 (I hope ;-)).
|
|
||||||
* Use idebus=xx to select right frequency.
|
|
||||||
*/
|
|
||||||
{
|
|
||||||
return ((time*bus_speed+999)/1000);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Write value to register reg, base of register
|
/* Write value to register reg, base of register
|
||||||
* is at reg_base (0x1f0 primary, 0x170 secondary,
|
* is at reg_base (0x1f0 primary, 0x170 secondary,
|
||||||
* if not changed by PCI configuration).
|
* if not changed by PCI configuration).
|
||||||
@ -159,51 +142,22 @@ static u8 read_reg(int reg)
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
typedef struct pio_clocks_s {
|
|
||||||
int address_time; /* Address setup (clocks) */
|
|
||||||
int data_time; /* Active/data pulse (clocks) */
|
|
||||||
int recovery_time; /* Recovery time (clocks) */
|
|
||||||
} pio_clocks_t;
|
|
||||||
|
|
||||||
static void compute_clocks(int pio, pio_clocks_t *clks, int bus_speed)
|
|
||||||
{
|
|
||||||
if (pio != PIO_NOT_EXIST) {
|
|
||||||
int adr_setup, data_pls;
|
|
||||||
|
|
||||||
adr_setup = ide_pio_timings[pio].setup_time;
|
|
||||||
data_pls = ide_pio_timings[pio].active_time;
|
|
||||||
clks->address_time = cmpt_clk(adr_setup, bus_speed);
|
|
||||||
clks->data_time = cmpt_clk(data_pls, bus_speed);
|
|
||||||
clks->recovery_time = cmpt_clk(ide_pio_timings[pio].cycle_time
|
|
||||||
- adr_setup-data_pls, bus_speed);
|
|
||||||
if (clks->address_time < 1)
|
|
||||||
clks->address_time = 1;
|
|
||||||
if (clks->address_time > 4)
|
|
||||||
clks->address_time = 4;
|
|
||||||
if (clks->data_time < 1)
|
|
||||||
clks->data_time = 1;
|
|
||||||
if (clks->data_time > 16)
|
|
||||||
clks->data_time = 16;
|
|
||||||
if (clks->recovery_time < 2)
|
|
||||||
clks->recovery_time = 2;
|
|
||||||
if (clks->recovery_time > 17)
|
|
||||||
clks->recovery_time = 17;
|
|
||||||
} else {
|
|
||||||
clks->address_time = 1;
|
|
||||||
clks->data_time = 1;
|
|
||||||
clks->recovery_time = 2;
|
|
||||||
/* minimal values */
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void opti621_set_pio_mode(ide_drive_t *drive, const u8 pio)
|
static void opti621_set_pio_mode(ide_drive_t *drive, const u8 pio)
|
||||||
{
|
{
|
||||||
ide_hwif_t *hwif = drive->hwif;
|
ide_hwif_t *hwif = drive->hwif;
|
||||||
ide_drive_t *pair = ide_get_paired_drive(drive);
|
ide_drive_t *pair = ide_get_paired_drive(drive);
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
pio_clocks_t first, second;
|
u8 tim, misc, addr_pio = pio, clk;
|
||||||
int ax, drdy;
|
|
||||||
u8 cycle1, misc, clk, addr_pio = pio;
|
/* DRDY is default 2 (by OPTi Databook) */
|
||||||
|
static const u8 addr_timings[2][4] = {
|
||||||
|
{ 0x20, 0x10, 0x00, 0x00 }, /* 33 MHz */
|
||||||
|
{ 0x10, 0x10, 0x00, 0x00 }, /* 25 MHz */
|
||||||
|
};
|
||||||
|
static const u8 data_rec_timings[2][4] = {
|
||||||
|
{ 0x5b, 0x45, 0x32, 0x21 }, /* 33 MHz */
|
||||||
|
{ 0x48, 0x34, 0x21, 0x10 } /* 25 MHz */
|
||||||
|
};
|
||||||
|
|
||||||
drive->drive_data = XFER_PIO_0 + pio;
|
drive->drive_data = XFER_PIO_0 + pio;
|
||||||
|
|
||||||
@ -230,31 +184,15 @@ static void opti621_set_pio_mode(ide_drive_t *drive, const u8 pio)
|
|||||||
|
|
||||||
printk(KERN_INFO "%s: CLK = %d MHz\n", hwif->name, clk ? 25 : 33);
|
printk(KERN_INFO "%s: CLK = %d MHz\n", hwif->name, clk ? 25 : 33);
|
||||||
|
|
||||||
compute_clocks(pio, &first, clk ? 25 : 33);
|
tim = data_rec_timings[clk][pio];
|
||||||
compute_clocks(addr_pio, &second, clk ? 25 : 33);
|
misc = addr_timings[clk][addr_pio];
|
||||||
|
|
||||||
/* ax = max(a1,a2) */
|
|
||||||
ax = (first.address_time < second.address_time) ? second.address_time : first.address_time;
|
|
||||||
|
|
||||||
drdy = 2; /* DRDY is default 2 (by OPTi Databook) */
|
|
||||||
|
|
||||||
cycle1 = ((first.data_time-1)<<4) | (first.recovery_time-2);
|
|
||||||
|
|
||||||
misc = ((ax - 1) << 4) | ((drdy - 2) << 1);
|
|
||||||
|
|
||||||
#ifdef OPTI621_DEBUG
|
|
||||||
printk("%s: address: %d, data: %d, "
|
|
||||||
"recovery: %d, drdy: %d [clk]\n",
|
|
||||||
drive->name, ax, first.data_time,
|
|
||||||
first.recovery_time, drdy);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* select Index-0/1 for Register-A/B */
|
/* select Index-0/1 for Register-A/B */
|
||||||
write_reg(drive->select.b.unit, MISC_REG);
|
write_reg(drive->select.b.unit, MISC_REG);
|
||||||
/* set read cycle timings */
|
/* set read cycle timings */
|
||||||
write_reg(cycle1, READ_REG);
|
write_reg(tim, READ_REG);
|
||||||
/* set write cycle timings */
|
/* set write cycle timings */
|
||||||
write_reg(cycle1, WRITE_REG);
|
write_reg(tim, WRITE_REG);
|
||||||
|
|
||||||
/* use Register-A for drive 0 */
|
/* use Register-A for drive 0 */
|
||||||
/* use Register-B for drive 1 */
|
/* use Register-B for drive 1 */
|
||||||
|
Loading…
Reference in New Issue
Block a user