diff options
author | Bartlomiej Zolnierkiewicz <bzolnier@gmail.com> | 2007-05-15 18:51:44 -0400 |
---|---|---|
committer | Bartlomiej Zolnierkiewicz <bzolnier@gmail.com> | 2007-05-15 18:51:44 -0400 |
commit | 3c3f5d2c9f64b47aceb88f8d80fcb70fb9f9809f (patch) | |
tree | a30b4d97b72f14bd2781d73f88c0c3f7abd87616 /drivers/ide | |
parent | a01ba4011aa745be44d0290c5da5cb2dfb4e37ce (diff) |
cs5530/sc1200: add ->speedproc support
* add {cs5530,sc1200}_tunepio() for programming PIO timings
* add {cs5530,sc1200}_tune_chipset() (->speedproc method) for setting
transfer mode and convert {cs5530,sc1200}_config_dma() to use it
* bump driver version
Signed-off-by: Bartlomiej Zolnierkiewicz <bzolnier@gmail.com>
Diffstat (limited to 'drivers/ide')
-rw-r--r-- | drivers/ide/pci/cs5530.c | 57 | ||||
-rw-r--r-- | drivers/ide/pci/sc1200.c | 70 |
2 files changed, 81 insertions, 46 deletions
diff --git a/drivers/ide/pci/cs5530.c b/drivers/ide/pci/cs5530.c index ec52dbec675f..aacb79b4a9cd 100644 --- a/drivers/ide/pci/cs5530.c +++ b/drivers/ide/pci/cs5530.c | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * linux/drivers/ide/pci/cs5530.c Version 0.72 Mar 10 2007 | 2 | * linux/drivers/ide/pci/cs5530.c Version 0.73 Mar 10 2007 |
3 | * | 3 | * |
4 | * Copyright (C) 2000 Andre Hedrick <andre@linux-ide.org> | 4 | * Copyright (C) 2000 Andre Hedrick <andre@linux-ide.org> |
5 | * Copyright (C) 2000 Mark Lord <mlord@pobox.com> | 5 | * Copyright (C) 2000 Mark Lord <mlord@pobox.com> |
@@ -62,6 +62,14 @@ static unsigned int cs5530_pio_timings[2][5] = { | |||
62 | #define CS5530_BAD_PIO(timings) (((timings)&~0x80000000)==0x0000e132) | 62 | #define CS5530_BAD_PIO(timings) (((timings)&~0x80000000)==0x0000e132) |
63 | #define CS5530_BASEREG(hwif) (((hwif)->dma_base & ~0xf) + ((hwif)->channel ? 0x30 : 0x20)) | 63 | #define CS5530_BASEREG(hwif) (((hwif)->dma_base & ~0xf) + ((hwif)->channel ? 0x30 : 0x20)) |
64 | 64 | ||
65 | static void cs5530_tunepio(ide_drive_t *drive, u8 pio) | ||
66 | { | ||
67 | unsigned long basereg = CS5530_BASEREG(drive->hwif); | ||
68 | unsigned int format = (inl(basereg + 4) >> 31) & 1; | ||
69 | |||
70 | outl(cs5530_pio_timings[format][pio], basereg + ((drive->dn & 1)<<3)); | ||
71 | } | ||
72 | |||
65 | /** | 73 | /** |
66 | * cs5530_tuneproc - select/set PIO modes | 74 | * cs5530_tuneproc - select/set PIO modes |
67 | * | 75 | * |
@@ -74,17 +82,10 @@ static unsigned int cs5530_pio_timings[2][5] = { | |||
74 | 82 | ||
75 | static void cs5530_tuneproc (ide_drive_t *drive, u8 pio) /* pio=255 means "autotune" */ | 83 | static void cs5530_tuneproc (ide_drive_t *drive, u8 pio) /* pio=255 means "autotune" */ |
76 | { | 84 | { |
77 | ide_hwif_t *hwif = HWIF(drive); | ||
78 | unsigned int format; | ||
79 | unsigned long basereg = CS5530_BASEREG(hwif); | ||
80 | static u8 modes[5] = { XFER_PIO_0, XFER_PIO_1, XFER_PIO_2, XFER_PIO_3, XFER_PIO_4}; | ||
81 | |||
82 | pio = ide_get_best_pio_mode(drive, pio, 4, NULL); | 85 | pio = ide_get_best_pio_mode(drive, pio, 4, NULL); |
83 | if (!cs5530_set_xfer_mode(drive, modes[pio])) { | 86 | |
84 | format = (inl(basereg + 4) >> 31) & 1; | 87 | if (cs5530_set_xfer_mode(drive, XFER_PIO_0 + pio) == 0) |
85 | outl(cs5530_pio_timings[format][pio], | 88 | cs5530_tunepio(drive, pio); |
86 | basereg+(drive->select.b.unit<<3)); | ||
87 | } | ||
88 | } | 89 | } |
89 | 90 | ||
90 | /** | 91 | /** |
@@ -136,18 +137,27 @@ out: | |||
136 | 137 | ||
137 | static int cs5530_config_dma(ide_drive_t *drive) | 138 | static int cs5530_config_dma(ide_drive_t *drive) |
138 | { | 139 | { |
139 | ide_hwif_t *hwif = drive->hwif; | 140 | if (ide_use_dma(drive)) { |
140 | unsigned int reg, timings = 0; | 141 | u8 mode = ide_max_dma_mode(drive); |
142 | |||
143 | if (mode && drive->hwif->speedproc(drive, mode) == 0) | ||
144 | return 0; | ||
145 | } | ||
146 | |||
147 | return 1; | ||
148 | } | ||
149 | |||
150 | static int cs5530_tune_chipset(ide_drive_t *drive, u8 mode) | ||
151 | { | ||
141 | unsigned long basereg; | 152 | unsigned long basereg; |
142 | u8 unit = drive->dn & 1, mode = 0; | 153 | unsigned int reg, timings = 0; |
143 | 154 | ||
144 | if (ide_use_dma(drive)) | 155 | mode = ide_rate_filter(drive, mode); |
145 | mode = ide_max_dma_mode(drive); | ||
146 | 156 | ||
147 | /* | 157 | /* |
148 | * Tell the drive to switch to the new mode; abort on failure. | 158 | * Tell the drive to switch to the new mode; abort on failure. |
149 | */ | 159 | */ |
150 | if (!mode || cs5530_set_xfer_mode(drive, mode)) | 160 | if (cs5530_set_xfer_mode(drive, mode)) |
151 | return 1; /* failure */ | 161 | return 1; /* failure */ |
152 | 162 | ||
153 | /* | 163 | /* |
@@ -160,14 +170,21 @@ static int cs5530_config_dma(ide_drive_t *drive) | |||
160 | case XFER_MW_DMA_0: timings = 0x00077771; break; | 170 | case XFER_MW_DMA_0: timings = 0x00077771; break; |
161 | case XFER_MW_DMA_1: timings = 0x00012121; break; | 171 | case XFER_MW_DMA_1: timings = 0x00012121; break; |
162 | case XFER_MW_DMA_2: timings = 0x00002020; break; | 172 | case XFER_MW_DMA_2: timings = 0x00002020; break; |
173 | case XFER_PIO_4: | ||
174 | case XFER_PIO_3: | ||
175 | case XFER_PIO_2: | ||
176 | case XFER_PIO_1: | ||
177 | case XFER_PIO_0: | ||
178 | cs5530_tunepio(drive, mode - XFER_PIO_0); | ||
179 | return 0; | ||
163 | default: | 180 | default: |
164 | BUG(); | 181 | BUG(); |
165 | break; | 182 | break; |
166 | } | 183 | } |
167 | basereg = CS5530_BASEREG(hwif); | 184 | basereg = CS5530_BASEREG(drive->hwif); |
168 | reg = inl(basereg + 4); /* get drive0 config register */ | 185 | reg = inl(basereg + 4); /* get drive0 config register */ |
169 | timings |= reg & 0x80000000; /* preserve PIO format bit */ | 186 | timings |= reg & 0x80000000; /* preserve PIO format bit */ |
170 | if (unit == 0) { /* are we configuring drive0? */ | 187 | if ((drive-> dn & 1) == 0) { /* are we configuring drive0? */ |
171 | outl(timings, basereg + 4); /* write drive0 config register */ | 188 | outl(timings, basereg + 4); /* write drive0 config register */ |
172 | } else { | 189 | } else { |
173 | if (timings & 0x00100000) | 190 | if (timings & 0x00100000) |
@@ -293,6 +310,8 @@ static void __devinit init_hwif_cs5530 (ide_hwif_t *hwif) | |||
293 | hwif->serialized = hwif->mate->serialized = 1; | 310 | hwif->serialized = hwif->mate->serialized = 1; |
294 | 311 | ||
295 | hwif->tuneproc = &cs5530_tuneproc; | 312 | hwif->tuneproc = &cs5530_tuneproc; |
313 | hwif->speedproc = &cs5530_tune_chipset; | ||
314 | |||
296 | basereg = CS5530_BASEREG(hwif); | 315 | basereg = CS5530_BASEREG(hwif); |
297 | d0_timings = inl(basereg + 0); | 316 | d0_timings = inl(basereg + 0); |
298 | if (CS5530_BAD_PIO(d0_timings)) { | 317 | if (CS5530_BAD_PIO(d0_timings)) { |
diff --git a/drivers/ide/pci/sc1200.c b/drivers/ide/pci/sc1200.c index 65dcabe48205..c989fd90f377 100644 --- a/drivers/ide/pci/sc1200.c +++ b/drivers/ide/pci/sc1200.c | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * linux/drivers/ide/pci/sc1200.c Version 0.93 Mar 10 2007 | 2 | * linux/drivers/ide/pci/sc1200.c Version 0.94 Mar 10 2007 |
3 | * | 3 | * |
4 | * Copyright (C) 2000-2002 Mark Lord <mlord@pobox.com> | 4 | * Copyright (C) 2000-2002 Mark Lord <mlord@pobox.com> |
5 | * Copyright (C) 2007 Bartlomiej Zolnierkiewicz | 5 | * Copyright (C) 2007 Bartlomiej Zolnierkiewicz |
@@ -95,6 +95,20 @@ static const unsigned int sc1200_pio_timings[4][5] = | |||
95 | */ | 95 | */ |
96 | //#define SC1200_BAD_PIO(timings) (((timings)&~0x80000000)==0x00009172) | 96 | //#define SC1200_BAD_PIO(timings) (((timings)&~0x80000000)==0x00009172) |
97 | 97 | ||
98 | static void sc1200_tunepio(ide_drive_t *drive, u8 pio) | ||
99 | { | ||
100 | ide_hwif_t *hwif = drive->hwif; | ||
101 | struct pci_dev *pdev = hwif->pci_dev; | ||
102 | unsigned int basereg = hwif->channel ? 0x50 : 0x40, format = 0; | ||
103 | |||
104 | pci_read_config_dword(pdev, basereg + 4, &format); | ||
105 | format = (format >> 31) & 1; | ||
106 | if (format) | ||
107 | format += sc1200_get_pci_clock(); | ||
108 | pci_write_config_dword(pdev, basereg + ((drive->dn & 1) << 3), | ||
109 | sc1200_pio_timings[format][pio]); | ||
110 | } | ||
111 | |||
98 | /* | 112 | /* |
99 | * The SC1200 specifies that two drives sharing a cable cannot mix | 113 | * The SC1200 specifies that two drives sharing a cable cannot mix |
100 | * UDMA/MDMA. It has to be one or the other, for the pair, though | 114 | * UDMA/MDMA. It has to be one or the other, for the pair, though |
@@ -124,11 +138,7 @@ out: | |||
124 | return mask; | 138 | return mask; |
125 | } | 139 | } |
126 | 140 | ||
127 | /* | 141 | static int sc1200_tune_chipset(ide_drive_t *drive, u8 mode) |
128 | * sc1200_config_dma2() handles selection/setting of DMA/UDMA modes | ||
129 | * for both the chipset and drive. | ||
130 | */ | ||
131 | static int sc1200_config_dma2 (ide_drive_t *drive, int mode) | ||
132 | { | 142 | { |
133 | ide_hwif_t *hwif = HWIF(drive); | 143 | ide_hwif_t *hwif = HWIF(drive); |
134 | int unit = drive->select.b.unit; | 144 | int unit = drive->select.b.unit; |
@@ -136,14 +146,26 @@ static int sc1200_config_dma2 (ide_drive_t *drive, int mode) | |||
136 | unsigned short pci_clock; | 146 | unsigned short pci_clock; |
137 | unsigned int basereg = hwif->channel ? 0x50 : 0x40; | 147 | unsigned int basereg = hwif->channel ? 0x50 : 0x40; |
138 | 148 | ||
149 | mode = ide_rate_filter(drive, mode); | ||
150 | |||
139 | /* | 151 | /* |
140 | * Tell the drive to switch to the new mode; abort on failure. | 152 | * Tell the drive to switch to the new mode; abort on failure. |
141 | */ | 153 | */ |
142 | if (!mode || sc1200_set_xfer_mode(drive, mode)) { | 154 | if (sc1200_set_xfer_mode(drive, mode)) { |
143 | printk("SC1200: set xfer mode failure\n"); | 155 | printk("SC1200: set xfer mode failure\n"); |
144 | return 1; /* failure */ | 156 | return 1; /* failure */ |
145 | } | 157 | } |
146 | 158 | ||
159 | switch (mode) { | ||
160 | case XFER_PIO_4: | ||
161 | case XFER_PIO_3: | ||
162 | case XFER_PIO_2: | ||
163 | case XFER_PIO_1: | ||
164 | case XFER_PIO_0: | ||
165 | sc1200_tunepio(drive, mode - XFER_PIO_0); | ||
166 | return 0; | ||
167 | } | ||
168 | |||
147 | pci_clock = sc1200_get_pci_clock(); | 169 | pci_clock = sc1200_get_pci_clock(); |
148 | 170 | ||
149 | /* | 171 | /* |
@@ -196,11 +218,9 @@ static int sc1200_config_dma2 (ide_drive_t *drive, int mode) | |||
196 | case PCI_CLK_66: timings = 0x00015151; break; | 218 | case PCI_CLK_66: timings = 0x00015151; break; |
197 | } | 219 | } |
198 | break; | 220 | break; |
199 | } | 221 | default: |
200 | 222 | BUG(); | |
201 | if (timings == 0) { | 223 | break; |
202 | printk("%s: sc1200_config_dma: huh? mode=%02x clk=%x \n", drive->name, mode, pci_clock); | ||
203 | return 1; /* failure */ | ||
204 | } | 224 | } |
205 | 225 | ||
206 | if (unit == 0) { /* are we configuring drive0? */ | 226 | if (unit == 0) { /* are we configuring drive0? */ |
@@ -220,12 +240,14 @@ static int sc1200_config_dma2 (ide_drive_t *drive, int mode) | |||
220 | */ | 240 | */ |
221 | static int sc1200_config_dma (ide_drive_t *drive) | 241 | static int sc1200_config_dma (ide_drive_t *drive) |
222 | { | 242 | { |
223 | u8 mode = 0; | 243 | if (ide_use_dma(drive)) { |
244 | u8 mode = ide_max_dma_mode(drive); | ||
224 | 245 | ||
225 | if (ide_use_dma(drive)) | 246 | if (mode && drive->hwif->speedproc(drive, mode) == 0) |
226 | mode = ide_max_dma_mode(drive); | 247 | return 0; |
248 | } | ||
227 | 249 | ||
228 | return sc1200_config_dma2(drive, mode); | 250 | return 1; |
229 | } | 251 | } |
230 | 252 | ||
231 | 253 | ||
@@ -265,8 +287,6 @@ static int sc1200_ide_dma_end (ide_drive_t *drive) | |||
265 | static void sc1200_tuneproc (ide_drive_t *drive, byte pio) /* mode=255 means "autotune" */ | 287 | static void sc1200_tuneproc (ide_drive_t *drive, byte pio) /* mode=255 means "autotune" */ |
266 | { | 288 | { |
267 | ide_hwif_t *hwif = HWIF(drive); | 289 | ide_hwif_t *hwif = HWIF(drive); |
268 | unsigned int format; | ||
269 | static byte modes[5] = {XFER_PIO_0, XFER_PIO_1, XFER_PIO_2, XFER_PIO_3, XFER_PIO_4}; | ||
270 | int mode = -1; | 290 | int mode = -1; |
271 | 291 | ||
272 | /* | 292 | /* |
@@ -283,21 +303,16 @@ static void sc1200_tuneproc (ide_drive_t *drive, byte pio) /* mode=255 means "au | |||
283 | if (mode != -1) { | 303 | if (mode != -1) { |
284 | printk("SC1200: %s: changing (U)DMA mode\n", drive->name); | 304 | printk("SC1200: %s: changing (U)DMA mode\n", drive->name); |
285 | hwif->dma_off_quietly(drive); | 305 | hwif->dma_off_quietly(drive); |
286 | if (sc1200_config_dma2(drive, mode) == 0) | 306 | if (sc1200_tune_chipset(drive, mode) == 0) |
287 | hwif->dma_host_on(drive); | 307 | hwif->dma_host_on(drive); |
288 | return; | 308 | return; |
289 | } | 309 | } |
290 | 310 | ||
291 | pio = ide_get_best_pio_mode(drive, pio, 4, NULL); | 311 | pio = ide_get_best_pio_mode(drive, pio, 4, NULL); |
292 | printk("SC1200: %s: setting PIO mode%d\n", drive->name, pio); | 312 | printk("SC1200: %s: setting PIO mode%d\n", drive->name, pio); |
293 | if (!sc1200_set_xfer_mode(drive, modes[pio])) { | 313 | |
294 | unsigned int basereg = hwif->channel ? 0x50 : 0x40; | 314 | if (sc1200_set_xfer_mode(drive, XFER_PIO_0 + pio) == 0) |
295 | pci_read_config_dword (hwif->pci_dev, basereg+4, &format); | 315 | sc1200_tunepio(drive, pio); |
296 | format = (format >> 31) & 1; | ||
297 | if (format) | ||
298 | format += sc1200_get_pci_clock(); | ||
299 | pci_write_config_dword(hwif->pci_dev, basereg + (drive->select.b.unit << 3), sc1200_pio_timings[format][pio]); | ||
300 | } | ||
301 | } | 316 | } |
302 | 317 | ||
303 | #ifdef CONFIG_PM | 318 | #ifdef CONFIG_PM |
@@ -447,6 +462,7 @@ static void __devinit init_hwif_sc1200 (ide_hwif_t *hwif) | |||
447 | if (!noautodma) | 462 | if (!noautodma) |
448 | hwif->autodma = 1; | 463 | hwif->autodma = 1; |
449 | hwif->tuneproc = &sc1200_tuneproc; | 464 | hwif->tuneproc = &sc1200_tuneproc; |
465 | hwif->speedproc = &sc1200_tune_chipset; | ||
450 | } | 466 | } |
451 | hwif->atapi_dma = 1; | 467 | hwif->atapi_dma = 1; |
452 | hwif->ultra_mask = 0x07; | 468 | hwif->ultra_mask = 0x07; |