aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/ide/pci/opti621.c
diff options
context:
space:
mode:
authorBartlomiej Zolnierkiewicz <bzolnier@gmail.com>2008-06-15 15:00:22 -0400
committerBartlomiej Zolnierkiewicz <bzolnier@gmail.com>2008-06-15 15:00:22 -0400
commit810253d44bc92b44b66cd9944b579de54c0cd3ff (patch)
tree698d7e2c96fe1b54cb36b1dc3c25ddd9cb21287f /drivers/ide/pci/opti621.c
parent6c987183fcc3c6cb9eb77fd0b3e8ca1ac98a4813 (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/pci/opti621.c')
-rw-r--r--drivers/ide/pci/opti621.c92
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
111static int reg_base; 109static int reg_base;
112 110
113#define PIO_NOT_EXIST 254
114#define PIO_DONT_KNOW 255
115
116static DEFINE_SPINLOCK(opti621_lock); 111static DEFINE_SPINLOCK(opti621_lock);
117 112
118static 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
162typedef 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
168static 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
199static void opti621_set_pio_mode(ide_drive_t *drive, const u8 pio) 145static 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 */