aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/ide/cmd64x.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/ide/cmd64x.c')
-rw-r--r--drivers/ide/cmd64x.c131
1 files changed, 43 insertions, 88 deletions
diff --git a/drivers/ide/cmd64x.c b/drivers/ide/cmd64x.c
index ca0c46f6580a..5f80312e636b 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
@@ -20,14 +21,6 @@
20 21
21#define DRV_NAME "cmd64x" 22#define DRV_NAME "cmd64x"
22 23
23#define CMD_DEBUG 0
24
25#if CMD_DEBUG
26#define cmdprintk(x...) printk(x)
27#else
28#define cmdprintk(x...)
29#endif
30
31/* 24/*
32 * CMD64x specific registers definition. 25 * CMD64x specific registers definition.
33 */ 26 */
@@ -58,79 +51,42 @@
58#define UDIDETCR1 0x7B 51#define UDIDETCR1 0x7B
59#define DTPR1 0x7C 52#define DTPR1 0x7C
60 53
61static u8 quantize_timing(int timing, int quant) 54static void cmd64x_program_timings(ide_drive_t *drive, u8 mode)
62{
63 return (timing + quant - 1) / quant;
64}
65
66/*
67 * This routine calculates active/recovery counts and then writes them into
68 * the chipset registers.
69 */
70static void program_cycle_times (ide_drive_t *drive, int cycle_time, int active_time)
71{ 55{
56 ide_hwif_t *hwif = drive->hwif;
72 struct pci_dev *dev = to_pci_dev(drive->hwif->dev); 57 struct pci_dev *dev = to_pci_dev(drive->hwif->dev);
73 int clock_time = 1000 / (ide_pci_clk ? ide_pci_clk : 33); 58 int bus_speed = ide_pci_clk ? ide_pci_clk : 33;
74 u8 cycle_count, active_count, recovery_count, drwtim; 59 const unsigned long T = 1000000 / bus_speed;
75 static const u8 recovery_values[] = 60 static const u8 recovery_values[] =
76 {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};
77 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;
78 67
79 cmdprintk("program_cycle_times parameters: total=%d, active=%d\n", 68 ide_timing_compute(drive, mode, &t, T, 0);
80 cycle_time, active_time);
81
82 cycle_count = quantize_timing( cycle_time, clock_time);
83 active_count = quantize_timing(active_time, clock_time);
84 recovery_count = cycle_count - active_count;
85 69
86 /* 70 /*
87 * 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
88 * the active phase 72 * the active phase
89 */ 73 */
90 if (recovery_count > 16) { 74 if (t.recover > 16) {
91 active_count += recovery_count - 16; 75 t.active += t.recover - 16;
92 recovery_count = 16; 76 t.recover = 16;
93 } 77 }
94 if (active_count > 16) /* shouldn't actually happen... */ 78 if (t.active > 16) /* shouldn't actually happen... */
95 active_count = 16; 79 t.active = 16;
96
97 cmdprintk("Final counts: total=%d, active=%d, recovery=%d\n",
98 cycle_count, active_count, recovery_count);
99 80
100 /* 81 /*
101 * Convert values to internal chipset representation 82 * Convert values to internal chipset representation
102 */ 83 */
103 recovery_count = recovery_values[recovery_count]; 84 t.recover = recovery_values[t.recover];
104 active_count &= 0x0f; 85 t.active &= 0x0f;
105 86
106 /* Program the active/recovery counts into the DRWTIM register */ 87 /* Program the active/recovery counts into the DRWTIM register */
107 drwtim = (active_count << 4) | recovery_count; 88 pci_write_config_byte(dev, drwtim_regs[drive->dn],
108 (void) pci_write_config_byte(dev, drwtim_regs[drive->dn], drwtim); 89 (t.active << 4) | t.recover);
109 cmdprintk("Write 0x%02x to reg 0x%x\n", drwtim, drwtim_regs[drive->dn]);
110}
111
112/*
113 * This routine writes into the chipset registers
114 * PIO setup/active/recovery timings.
115 */
116static void cmd64x_tune_pio(ide_drive_t *drive, const u8 pio)
117{
118 ide_hwif_t *hwif = drive->hwif;
119 struct pci_dev *dev = to_pci_dev(hwif->dev);
120 struct ide_timing *t = ide_timing_find_mode(XFER_PIO_0 + pio);
121 unsigned long setup_count;
122 unsigned int cycle_time;
123 u8 arttim = 0;
124
125 static const u8 setup_values[] = {0x40, 0x40, 0x40, 0x80, 0, 0xc0};
126 static const u8 arttim_regs[4] = {ARTTIM0, ARTTIM1, ARTTIM23, ARTTIM23};
127
128 cycle_time = ide_pio_cycle_time(drive, pio);
129
130 program_cycle_times(drive, cycle_time, t->active);
131
132 setup_count = quantize_timing(t->setup,
133 1000 / (ide_pci_clk ? ide_pci_clk : 33));
134 90
135 /* 91 /*
136 * The primary channel has individual address setup timing registers 92 * The primary channel has individual address setup timing registers
@@ -141,16 +97,21 @@ static void cmd64x_tune_pio(ide_drive_t *drive, const u8 pio)
141 if (hwif->channel) { 97 if (hwif->channel) {
142 ide_drive_t *pair = ide_get_pair_dev(drive); 98 ide_drive_t *pair = ide_get_pair_dev(drive);
143 99
144 ide_set_drivedata(drive, (void *)setup_count); 100 if (pair) {
101 struct ide_timing tp;
145 102
146 if (pair) 103 ide_timing_compute(pair, pair->pio_mode, &tp, T, 0);
147 setup_count = max_t(u8, setup_count, 104 ide_timing_merge(&t, &tp, &t, IDE_TIMING_SETUP);
148 (unsigned long)ide_get_drivedata(pair)); 105 if (pair->dma_mode) {
106 ide_timing_compute(pair, pair->dma_mode,
107 &tp, T, 0);
108 ide_timing_merge(&tp, &t, &t, IDE_TIMING_SETUP);
109 }
110 }
149 } 111 }
150 112
151 if (setup_count > 5) /* shouldn't actually happen... */ 113 if (t.setup > 5) /* shouldn't actually happen... */
152 setup_count = 5; 114 t.setup = 5;
153 cmdprintk("Final address setup count: %d\n", setup_count);
154 115
155 /* 116 /*
156 * Program the address setup clocks into the ARTTIM registers. 117 * Program the address setup clocks into the ARTTIM registers.
@@ -160,9 +121,8 @@ static void cmd64x_tune_pio(ide_drive_t *drive, const u8 pio)
160 if (hwif->channel) 121 if (hwif->channel)
161 arttim &= ~ARTTIM23_INTR_CH1; 122 arttim &= ~ARTTIM23_INTR_CH1;
162 arttim &= ~0xc0; 123 arttim &= ~0xc0;
163 arttim |= setup_values[setup_count]; 124 arttim |= setup_values[t.setup];
164 (void) pci_write_config_byte(dev, arttim_regs[drive->dn], arttim); 125 (void) pci_write_config_byte(dev, arttim_regs[drive->dn], arttim);
165 cmdprintk("Write 0x%02x to reg 0x%x\n", arttim, arttim_regs[drive->dn]);
166} 126}
167 127
168/* 128/*
@@ -170,8 +130,10 @@ static void cmd64x_tune_pio(ide_drive_t *drive, const u8 pio)
170 * Special cases are 8: prefetch off, 9: prefetch on (both never worked) 130 * Special cases are 8: prefetch off, 9: prefetch on (both never worked)
171 */ 131 */
172 132
173static void cmd64x_set_pio_mode(ide_drive_t *drive, const u8 pio) 133static void cmd64x_set_pio_mode(ide_hwif_t *hwif, ide_drive_t *drive)
174{ 134{
135 const u8 pio = drive->pio_mode - XFER_PIO_0;
136
175 /* 137 /*
176 * Filter out the prefetch control values 138 * Filter out the prefetch control values
177 * to prevent PIO5 from being programmed 139 * to prevent PIO5 from being programmed
@@ -179,20 +141,18 @@ static void cmd64x_set_pio_mode(ide_drive_t *drive, const u8 pio)
179 if (pio == 8 || pio == 9) 141 if (pio == 8 || pio == 9)
180 return; 142 return;
181 143
182 cmd64x_tune_pio(drive, pio); 144 cmd64x_program_timings(drive, XFER_PIO_0 + pio);
183} 145}
184 146
185static void cmd64x_set_dma_mode(ide_drive_t *drive, const u8 speed) 147static void cmd64x_set_dma_mode(ide_hwif_t *hwif, ide_drive_t *drive)
186{ 148{
187 ide_hwif_t *hwif = drive->hwif;
188 struct pci_dev *dev = to_pci_dev(hwif->dev); 149 struct pci_dev *dev = to_pci_dev(hwif->dev);
189 u8 unit = drive->dn & 0x01; 150 u8 unit = drive->dn & 0x01;
190 u8 regU = 0, pciU = hwif->channel ? UDIDETCR1 : UDIDETCR0; 151 u8 regU = 0, pciU = hwif->channel ? UDIDETCR1 : UDIDETCR0;
152 const u8 speed = drive->dma_mode;
191 153
192 if (speed >= XFER_SW_DMA_0) { 154 pci_read_config_byte(dev, pciU, &regU);
193 (void) pci_read_config_byte(dev, pciU, &regU); 155 regU &= ~(unit ? 0xCA : 0x35);
194 regU &= ~(unit ? 0xCA : 0x35);
195 }
196 156
197 switch(speed) { 157 switch(speed) {
198 case XFER_UDMA_5: 158 case XFER_UDMA_5:
@@ -214,18 +174,13 @@ static void cmd64x_set_dma_mode(ide_drive_t *drive, const u8 speed)
214 regU |= unit ? 0xC2 : 0x31; 174 regU |= unit ? 0xC2 : 0x31;
215 break; 175 break;
216 case XFER_MW_DMA_2: 176 case XFER_MW_DMA_2:
217 program_cycle_times(drive, 120, 70);
218 break;
219 case XFER_MW_DMA_1: 177 case XFER_MW_DMA_1:
220 program_cycle_times(drive, 150, 80);
221 break;
222 case XFER_MW_DMA_0: 178 case XFER_MW_DMA_0:
223 program_cycle_times(drive, 480, 215); 179 cmd64x_program_timings(drive, speed);
224 break; 180 break;
225 } 181 }
226 182
227 if (speed >= XFER_SW_DMA_0) 183 pci_write_config_byte(dev, pciU, regU);
228 (void) pci_write_config_byte(dev, pciU, regU);
229} 184}
230 185
231static void cmd648_clear_irq(ide_drive_t *drive) 186static void cmd648_clear_irq(ide_drive_t *drive)
@@ -488,6 +443,6 @@ static void __exit cmd64x_ide_exit(void)
488module_init(cmd64x_ide_init); 443module_init(cmd64x_ide_init);
489module_exit(cmd64x_ide_exit); 444module_exit(cmd64x_ide_exit);
490 445
491MODULE_AUTHOR("Eddie Dost, David Miller, Andre Hedrick"); 446MODULE_AUTHOR("Eddie Dost, David Miller, Andre Hedrick, Bartlomiej Zolnierkiewicz");
492MODULE_DESCRIPTION("PCI driver module for CMD64x IDE"); 447MODULE_DESCRIPTION("PCI driver module for CMD64x IDE");
493MODULE_LICENSE("GPL"); 448MODULE_LICENSE("GPL");