aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/ide
diff options
context:
space:
mode:
authorBartlomiej Zolnierkiewicz <bzolnier@gmail.com>2007-05-15 18:51:44 -0400
committerBartlomiej Zolnierkiewicz <bzolnier@gmail.com>2007-05-15 18:51:44 -0400
commit3c3f5d2c9f64b47aceb88f8d80fcb70fb9f9809f (patch)
treea30b4d97b72f14bd2781d73f88c0c3f7abd87616 /drivers/ide
parenta01ba4011aa745be44d0290c5da5cb2dfb4e37ce (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.c57
-rw-r--r--drivers/ide/pci/sc1200.c70
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
65static 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
75static void cs5530_tuneproc (ide_drive_t *drive, u8 pio) /* pio=255 means "autotune" */ 83static 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
137static int cs5530_config_dma(ide_drive_t *drive) 138static 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
150static 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
98static 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/* 141static 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 */
131static 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 */
221static int sc1200_config_dma (ide_drive_t *drive) 241static 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)
265static void sc1200_tuneproc (ide_drive_t *drive, byte pio) /* mode=255 means "autotune" */ 287static 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;