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/pci/sc1200.c | |
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/pci/sc1200.c')
-rw-r--r-- | drivers/ide/pci/sc1200.c | 70 |
1 files changed, 43 insertions, 27 deletions
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; |