aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorBartlomiej Zolnierkiewicz <bzolnier@gmail.com>2010-01-18 02:18:26 -0500
committerDavid S. Miller <davem@davemloft.net>2010-01-19 04:24:58 -0500
commit60349ab99f2742a6f04da86724740498c7b1f885 (patch)
treeb72202c5b424f14b312d5b5fd8315527e2de4610 /drivers
parent31bbb668fbe71a207d38ecd1797f4cd5b8bd710b (diff)
cmd64x: fix PIO and MWDMA timings calculations
Just use the standard ide_timing_compute() helper to calculate PIO and MWDMA timings. This fixes some issues with the open-coded version like allowing faster MWDMA timings than the ones required by the current PIO mode or not accounting for the enhanced MWDMA cycle time specified by the device. Based on libata pata_cmd64x host driver. Signed-off-by: Bartlomiej Zolnierkiewicz <bzolnier@gmail.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/ide/cmd64x.c88
1 files changed, 29 insertions, 59 deletions
diff --git a/drivers/ide/cmd64x.c b/drivers/ide/cmd64x.c
index f2500c8826bb..5c5dd90d032b 100644
--- a/drivers/ide/cmd64x.c
+++ b/drivers/ide/cmd64x.c
@@ -7,6 +7,7 @@
7 * Copyright (C) 1998 David S. Miller (davem@redhat.com) 7 * Copyright (C) 1998 David S. Miller (davem@redhat.com)
8 * 8 *
9 * Copyright (C) 1999-2002 Andre Hedrick <andre@linux-ide.org> 9 * Copyright (C) 1999-2002 Andre Hedrick <andre@linux-ide.org>
10 * Copyright (C) 2007-2010 Bartlomiej Zolnierkiewicz
10 * Copyright (C) 2007,2009 MontaVista Software, Inc. <source@mvista.com> 11 * Copyright (C) 2007,2009 MontaVista Software, Inc. <source@mvista.com>
11 */ 12 */
12 13
@@ -50,72 +51,45 @@
50#define UDIDETCR1 0x7B 51#define UDIDETCR1 0x7B
51#define DTPR1 0x7C 52#define DTPR1 0x7C
52 53
53static u8 quantize_timing(int timing, int quant) 54static void cmd64x_program_timings(ide_drive_t *drive, u8 mode)
54{
55 return (timing + quant - 1) / quant;
56}
57
58/*
59 * This routine calculates active/recovery counts and then writes them into
60 * the chipset registers.
61 */
62static void program_cycle_times (ide_drive_t *drive, int cycle_time, int active_time)
63{ 55{
56 ide_hwif_t *hwif = drive->hwif;
64 struct pci_dev *dev = to_pci_dev(drive->hwif->dev); 57 struct pci_dev *dev = to_pci_dev(drive->hwif->dev);
65 int clock_time = 1000 / (ide_pci_clk ? ide_pci_clk : 33); 58 int bus_speed = ide_pci_clk ? ide_pci_clk : 33;
66 u8 cycle_count, active_count, recovery_count, drwtim; 59 const unsigned long T = 1000000 / bus_speed;
67 static const u8 recovery_values[] = 60 static const u8 recovery_values[] =
68 {15, 15, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 0}; 61 {15, 15, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 0};
62 static const u8 setup_values[] = {0x40, 0x40, 0x40, 0x80, 0, 0xc0};
63 static const u8 arttim_regs[4] = {ARTTIM0, ARTTIM1, ARTTIM23, ARTTIM23};
69 static const u8 drwtim_regs[4] = {DRWTIM0, DRWTIM1, DRWTIM2, DRWTIM3}; 64 static const u8 drwtim_regs[4] = {DRWTIM0, DRWTIM1, DRWTIM2, DRWTIM3};
65 struct ide_timing t;
66 u8 arttim = 0;
70 67
71 cycle_count = quantize_timing( cycle_time, clock_time); 68 ide_timing_compute(drive, mode, &t, T, 0);
72 active_count = quantize_timing(active_time, clock_time);
73 recovery_count = cycle_count - active_count;
74 69
75 /* 70 /*
76 * In case we've got too long recovery phase, try to lengthen 71 * In case we've got too long recovery phase, try to lengthen
77 * the active phase 72 * the active phase
78 */ 73 */
79 if (recovery_count > 16) { 74 if (t.recover > 16) {
80 active_count += recovery_count - 16; 75 t.active += t.recover - 16;
81 recovery_count = 16; 76 t.recover = 16;
82 } 77 }
83 if (active_count > 16) /* shouldn't actually happen... */ 78 if (t.active > 16) /* shouldn't actually happen... */
84 active_count = 16; 79 t.active = 16;
85 80
86 /* 81 /*
87 * Convert values to internal chipset representation 82 * Convert values to internal chipset representation
88 */ 83 */
89 recovery_count = recovery_values[recovery_count]; 84 t.recover = recovery_values[t.recover];
90 active_count &= 0x0f; 85 t.active &= 0x0f;
91 86
92 /* Program the active/recovery counts into the DRWTIM register */ 87 /* Program the active/recovery counts into the DRWTIM register */
93 drwtim = (active_count << 4) | recovery_count; 88 pci_write_config_byte(dev, drwtim_regs[drive->dn],
94 (void) pci_write_config_byte(dev, drwtim_regs[drive->dn], drwtim); 89 (t.active << 4) | t.recover);
95}
96 90
97/* 91 if (mode >= XFER_SW_DMA_0)
98 * This routine writes into the chipset registers 92 return;
99 * PIO setup/active/recovery timings.
100 */
101static void cmd64x_tune_pio(ide_drive_t *drive, const u8 pio)
102{
103 ide_hwif_t *hwif = drive->hwif;
104 struct pci_dev *dev = to_pci_dev(hwif->dev);
105 struct ide_timing *t = ide_timing_find_mode(XFER_PIO_0 + pio);
106 unsigned long setup_count;
107 unsigned int cycle_time;
108 u8 arttim = 0;
109
110 static const u8 setup_values[] = {0x40, 0x40, 0x40, 0x80, 0, 0xc0};
111 static const u8 arttim_regs[4] = {ARTTIM0, ARTTIM1, ARTTIM23, ARTTIM23};
112
113 cycle_time = ide_pio_cycle_time(drive, pio);
114
115 program_cycle_times(drive, cycle_time, t->active);
116
117 setup_count = quantize_timing(t->setup,
118 1000 / (ide_pci_clk ? ide_pci_clk : 33));
119 93
120 /* 94 /*
121 * The primary channel has individual address setup timing registers 95 * The primary channel has individual address setup timing registers
@@ -126,15 +100,15 @@ static void cmd64x_tune_pio(ide_drive_t *drive, const u8 pio)
126 if (hwif->channel) { 100 if (hwif->channel) {
127 ide_drive_t *pair = ide_get_pair_dev(drive); 101 ide_drive_t *pair = ide_get_pair_dev(drive);
128 102
129 ide_set_drivedata(drive, (void *)setup_count); 103 ide_set_drivedata(drive, (void *)(unsigned long)t.setup);
130 104
131 if (pair) 105 if (pair)
132 setup_count = max_t(u8, setup_count, 106 t.setup = max_t(u8, t.setup,
133 (unsigned long)ide_get_drivedata(pair)); 107 (unsigned long)ide_get_drivedata(pair));
134 } 108 }
135 109
136 if (setup_count > 5) /* shouldn't actually happen... */ 110 if (t.setup > 5) /* shouldn't actually happen... */
137 setup_count = 5; 111 t.setup = 5;
138 112
139 /* 113 /*
140 * Program the address setup clocks into the ARTTIM registers. 114 * Program the address setup clocks into the ARTTIM registers.
@@ -144,7 +118,7 @@ static void cmd64x_tune_pio(ide_drive_t *drive, const u8 pio)
144 if (hwif->channel) 118 if (hwif->channel)
145 arttim &= ~ARTTIM23_INTR_CH1; 119 arttim &= ~ARTTIM23_INTR_CH1;
146 arttim &= ~0xc0; 120 arttim &= ~0xc0;
147 arttim |= setup_values[setup_count]; 121 arttim |= setup_values[t.setup];
148 (void) pci_write_config_byte(dev, arttim_regs[drive->dn], arttim); 122 (void) pci_write_config_byte(dev, arttim_regs[drive->dn], arttim);
149} 123}
150 124
@@ -162,7 +136,7 @@ static void cmd64x_set_pio_mode(ide_drive_t *drive, const u8 pio)
162 if (pio == 8 || pio == 9) 136 if (pio == 8 || pio == 9)
163 return; 137 return;
164 138
165 cmd64x_tune_pio(drive, pio); 139 cmd64x_program_timings(drive, XFER_PIO_0 + pio);
166} 140}
167 141
168static void cmd64x_set_dma_mode(ide_drive_t *drive, const u8 speed) 142static void cmd64x_set_dma_mode(ide_drive_t *drive, const u8 speed)
@@ -197,13 +171,9 @@ static void cmd64x_set_dma_mode(ide_drive_t *drive, const u8 speed)
197 regU |= unit ? 0xC2 : 0x31; 171 regU |= unit ? 0xC2 : 0x31;
198 break; 172 break;
199 case XFER_MW_DMA_2: 173 case XFER_MW_DMA_2:
200 program_cycle_times(drive, 120, 70);
201 break;
202 case XFER_MW_DMA_1: 174 case XFER_MW_DMA_1:
203 program_cycle_times(drive, 150, 80);
204 break;
205 case XFER_MW_DMA_0: 175 case XFER_MW_DMA_0:
206 program_cycle_times(drive, 480, 215); 176 cmd64x_program_timings(drive, speed);
207 break; 177 break;
208 } 178 }
209 179
@@ -471,6 +441,6 @@ static void __exit cmd64x_ide_exit(void)
471module_init(cmd64x_ide_init); 441module_init(cmd64x_ide_init);
472module_exit(cmd64x_ide_exit); 442module_exit(cmd64x_ide_exit);
473 443
474MODULE_AUTHOR("Eddie Dost, David Miller, Andre Hedrick"); 444MODULE_AUTHOR("Eddie Dost, David Miller, Andre Hedrick, Bartlomiej Zolnierkiewicz");
475MODULE_DESCRIPTION("PCI driver module for CMD64x IDE"); 445MODULE_DESCRIPTION("PCI driver module for CMD64x IDE");
476MODULE_LICENSE("GPL"); 446MODULE_LICENSE("GPL");