diff options
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/ide/cmd64x.c | 88 |
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 | ||
53 | static u8 quantize_timing(int timing, int quant) | 54 | static 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 | */ | ||
62 | static 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 | */ | ||
101 | static 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 | ||
168 | static void cmd64x_set_dma_mode(ide_drive_t *drive, const u8 speed) | 142 | static 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) | |||
471 | module_init(cmd64x_ide_init); | 441 | module_init(cmd64x_ide_init); |
472 | module_exit(cmd64x_ide_exit); | 442 | module_exit(cmd64x_ide_exit); |
473 | 443 | ||
474 | MODULE_AUTHOR("Eddie Dost, David Miller, Andre Hedrick"); | 444 | MODULE_AUTHOR("Eddie Dost, David Miller, Andre Hedrick, Bartlomiej Zolnierkiewicz"); |
475 | MODULE_DESCRIPTION("PCI driver module for CMD64x IDE"); | 445 | MODULE_DESCRIPTION("PCI driver module for CMD64x IDE"); |
476 | MODULE_LICENSE("GPL"); | 446 | MODULE_LICENSE("GPL"); |