diff options
Diffstat (limited to 'drivers/ide/pci/cs5530.c')
-rw-r--r-- | drivers/ide/pci/cs5530.c | 57 |
1 files changed, 38 insertions, 19 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)) { |