diff options
Diffstat (limited to 'drivers/ide/cmd64x.c')
-rw-r--r-- | drivers/ide/cmd64x.c | 131 |
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 | ||
61 | static u8 quantize_timing(int timing, int quant) | 54 | static 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 | */ | ||
70 | static 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 | */ | ||
116 | static 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 | ||
173 | static void cmd64x_set_pio_mode(ide_drive_t *drive, const u8 pio) | 133 | static 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 | ||
185 | static void cmd64x_set_dma_mode(ide_drive_t *drive, const u8 speed) | 147 | static 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, ®U); |
193 | (void) pci_read_config_byte(dev, pciU, ®U); | 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 | ||
231 | static void cmd648_clear_irq(ide_drive_t *drive) | 186 | static void cmd648_clear_irq(ide_drive_t *drive) |
@@ -488,6 +443,6 @@ static void __exit cmd64x_ide_exit(void) | |||
488 | module_init(cmd64x_ide_init); | 443 | module_init(cmd64x_ide_init); |
489 | module_exit(cmd64x_ide_exit); | 444 | module_exit(cmd64x_ide_exit); |
490 | 445 | ||
491 | MODULE_AUTHOR("Eddie Dost, David Miller, Andre Hedrick"); | 446 | MODULE_AUTHOR("Eddie Dost, David Miller, Andre Hedrick, Bartlomiej Zolnierkiewicz"); |
492 | MODULE_DESCRIPTION("PCI driver module for CMD64x IDE"); | 447 | MODULE_DESCRIPTION("PCI driver module for CMD64x IDE"); |
493 | MODULE_LICENSE("GPL"); | 448 | MODULE_LICENSE("GPL"); |