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 | 810253d44bc92b44b66cd9944b579de54c0cd3ff (patch) | |
tree | 698d7e2c96fe1b54cb36b1dc3c25ddd9cb21287f /drivers/ide | |
parent | 6c987183fcc3c6cb9eb77fd0b3e8ca1ac98a4813 (diff) |
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>
Diffstat (limited to 'drivers/ide')
-rw-r--r-- | drivers/ide/pci/opti621.c | 92 |
1 files changed, 15 insertions, 77 deletions
diff --git a/drivers/ide/pci/opti621.c b/drivers/ide/pci/opti621.c index c746e6f06077..8c715b7a85db 100644 --- a/drivers/ide/pci/opti621.c +++ b/drivers/ide/pci/opti621.c | |||
@@ -81,8 +81,6 @@ | |||
81 | * 0.5 doesn't work. | 81 | * 0.5 doesn't work. |
82 | */ | 82 | */ |
83 | 83 | ||
84 | #define OPTI621_DEBUG /* define for debug messages */ | ||
85 | |||
86 | #include <linux/types.h> | 84 | #include <linux/types.h> |
87 | #include <linux/module.h> | 85 | #include <linux/module.h> |
88 | #include <linux/kernel.h> | 86 | #include <linux/kernel.h> |
@@ -110,23 +108,8 @@ | |||
110 | 108 | ||
111 | static int reg_base; | 109 | static int reg_base; |
112 | 110 | ||
113 | #define PIO_NOT_EXIST 254 | ||
114 | #define PIO_DONT_KNOW 255 | ||
115 | |||
116 | static DEFINE_SPINLOCK(opti621_lock); | 111 | static DEFINE_SPINLOCK(opti621_lock); |
117 | 112 | ||
118 | static int cmpt_clk(int time, int bus_speed) | ||
119 | /* Returns (rounded up) time in clocks for time in ns, | ||
120 | * with bus_speed in MHz. | ||
121 | * Example: bus_speed = 40 MHz, time = 80 ns | ||
122 | * 1000/40 = 25 ns (clk value), | ||
123 | * 80/25 = 3.2, rounded up to 4 (I hope ;-)). | ||
124 | * Use idebus=xx to select right frequency. | ||
125 | */ | ||
126 | { | ||
127 | return ((time*bus_speed+999)/1000); | ||
128 | } | ||
129 | |||
130 | /* Write value to register reg, base of register | 113 | /* Write value to register reg, base of register |
131 | * is at reg_base (0x1f0 primary, 0x170 secondary, | 114 | * is at reg_base (0x1f0 primary, 0x170 secondary, |
132 | * if not changed by PCI configuration). | 115 | * if not changed by PCI configuration). |
@@ -159,51 +142,22 @@ static u8 read_reg(int reg) | |||
159 | return ret; | 142 | return ret; |
160 | } | 143 | } |
161 | 144 | ||
162 | typedef struct pio_clocks_s { | ||
163 | int address_time; /* Address setup (clocks) */ | ||
164 | int data_time; /* Active/data pulse (clocks) */ | ||
165 | int recovery_time; /* Recovery time (clocks) */ | ||
166 | } pio_clocks_t; | ||
167 | |||
168 | static void compute_clocks(int pio, pio_clocks_t *clks, int bus_speed) | ||
169 | { | ||
170 | if (pio != PIO_NOT_EXIST) { | ||
171 | int adr_setup, data_pls; | ||
172 | |||
173 | adr_setup = ide_pio_timings[pio].setup_time; | ||
174 | data_pls = ide_pio_timings[pio].active_time; | ||
175 | clks->address_time = cmpt_clk(adr_setup, bus_speed); | ||
176 | clks->data_time = cmpt_clk(data_pls, bus_speed); | ||
177 | clks->recovery_time = cmpt_clk(ide_pio_timings[pio].cycle_time | ||
178 | - adr_setup-data_pls, bus_speed); | ||
179 | if (clks->address_time < 1) | ||
180 | clks->address_time = 1; | ||
181 | if (clks->address_time > 4) | ||
182 | clks->address_time = 4; | ||
183 | if (clks->data_time < 1) | ||
184 | clks->data_time = 1; | ||
185 | if (clks->data_time > 16) | ||
186 | clks->data_time = 16; | ||
187 | if (clks->recovery_time < 2) | ||
188 | clks->recovery_time = 2; | ||
189 | if (clks->recovery_time > 17) | ||
190 | clks->recovery_time = 17; | ||
191 | } else { | ||
192 | clks->address_time = 1; | ||
193 | clks->data_time = 1; | ||
194 | clks->recovery_time = 2; | ||
195 | /* minimal values */ | ||
196 | } | ||
197 | } | ||
198 | |||
199 | static void opti621_set_pio_mode(ide_drive_t *drive, const u8 pio) | 145 | static void opti621_set_pio_mode(ide_drive_t *drive, const u8 pio) |
200 | { | 146 | { |
201 | ide_hwif_t *hwif = drive->hwif; | 147 | ide_hwif_t *hwif = drive->hwif; |
202 | ide_drive_t *pair = ide_get_paired_drive(drive); | 148 | ide_drive_t *pair = ide_get_paired_drive(drive); |
203 | unsigned long flags; | 149 | unsigned long flags; |
204 | pio_clocks_t first, second; | 150 | u8 tim, misc, addr_pio = pio, clk; |
205 | int ax, drdy; | 151 | |
206 | u8 cycle1, misc, clk, addr_pio = pio; | 152 | /* DRDY is default 2 (by OPTi Databook) */ |
153 | static const u8 addr_timings[2][4] = { | ||
154 | { 0x20, 0x10, 0x00, 0x00 }, /* 33 MHz */ | ||
155 | { 0x10, 0x10, 0x00, 0x00 }, /* 25 MHz */ | ||
156 | }; | ||
157 | static const u8 data_rec_timings[2][4] = { | ||
158 | { 0x5b, 0x45, 0x32, 0x21 }, /* 33 MHz */ | ||
159 | { 0x48, 0x34, 0x21, 0x10 } /* 25 MHz */ | ||
160 | }; | ||
207 | 161 | ||
208 | drive->drive_data = XFER_PIO_0 + pio; | 162 | drive->drive_data = XFER_PIO_0 + pio; |
209 | 163 | ||
@@ -230,31 +184,15 @@ static void opti621_set_pio_mode(ide_drive_t *drive, const u8 pio) | |||
230 | 184 | ||
231 | printk(KERN_INFO "%s: CLK = %d MHz\n", hwif->name, clk ? 25 : 33); | 185 | printk(KERN_INFO "%s: CLK = %d MHz\n", hwif->name, clk ? 25 : 33); |
232 | 186 | ||
233 | compute_clocks(pio, &first, clk ? 25 : 33); | 187 | tim = data_rec_timings[clk][pio]; |
234 | compute_clocks(addr_pio, &second, clk ? 25 : 33); | 188 | misc = addr_timings[clk][addr_pio]; |
235 | |||
236 | /* ax = max(a1,a2) */ | ||
237 | ax = (first.address_time < second.address_time) ? second.address_time : first.address_time; | ||
238 | |||
239 | drdy = 2; /* DRDY is default 2 (by OPTi Databook) */ | ||
240 | |||
241 | cycle1 = ((first.data_time-1)<<4) | (first.recovery_time-2); | ||
242 | |||
243 | misc = ((ax - 1) << 4) | ((drdy - 2) << 1); | ||
244 | |||
245 | #ifdef OPTI621_DEBUG | ||
246 | printk("%s: address: %d, data: %d, " | ||
247 | "recovery: %d, drdy: %d [clk]\n", | ||
248 | drive->name, ax, first.data_time, | ||
249 | first.recovery_time, drdy); | ||
250 | #endif | ||
251 | 189 | ||
252 | /* select Index-0/1 for Register-A/B */ | 190 | /* select Index-0/1 for Register-A/B */ |
253 | write_reg(drive->select.b.unit, MISC_REG); | 191 | write_reg(drive->select.b.unit, MISC_REG); |
254 | /* set read cycle timings */ | 192 | /* set read cycle timings */ |
255 | write_reg(cycle1, READ_REG); | 193 | write_reg(tim, READ_REG); |
256 | /* set write cycle timings */ | 194 | /* set write cycle timings */ |
257 | write_reg(cycle1, WRITE_REG); | 195 | write_reg(tim, WRITE_REG); |
258 | 196 | ||
259 | /* use Register-A for drive 0 */ | 197 | /* use Register-A for drive 0 */ |
260 | /* use Register-B for drive 1 */ | 198 | /* use Register-B for drive 1 */ |