aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/ide/pci/cs5530.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/ide/pci/cs5530.c')
-rw-r--r--drivers/ide/pci/cs5530.c57
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
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)) {