aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/ide
diff options
context:
space:
mode:
authorBartlomiej Zolnierkiewicz <bzolnier@gmail.com>2007-05-15 18:51:41 -0400
committerBartlomiej Zolnierkiewicz <bzolnier@gmail.com>2007-05-15 18:51:41 -0400
commit4fce3164b84d5b014acbf5a3f57eb3650e154f5b (patch)
tree67aa08d4e0d9ee31b8f79360d53e18b608572393 /drivers/ide
parentf653c34dd3d8bde2c918316fd5ba2e2c4f95afcf (diff)
pdc202xx_old: rewrite mode programming code (v2)
This patch is based on the documentation (I would like to thank Promise for it) and also partially on the older vendor driver. Rewrite mode programming code: * disable 66MHz clock in pdc202xx_tune_chipset() so it is correctly disabled even if both devices on the channel are not DMA capable and after reset * enable/disable IORDY and PREFETCH bits in pdc202xx_tune_chipset() as they need to be setup correctly also for PIO only devices, plus IORDY wasn't disabled for non-IORDY devices and PREFETCH wasn't disabled for ATAPI devices * remove dead code for setting SYNC_ERDDY_EN bits from config_chipset_for_dma() (driver sets ->autotune to 1 so PIO modes are always programmed => lower nibble of register A never equals 4 => "chipset_is_set" is always true) * enable PIO mode programming for all ATAPI devices (it was limited to ->media == ide_cdrom devices) * remove extra reads of registers A/B/C, don't read register D et all * do clearing / programming of registers A/B/C in one go (gets rid of extra PCI config space read/write cycle) * set initial values of drive_conf/AP/BP/CP variables to zero (paranoia for the case when PCI reads fail) * remove XFER_UDMA6 to XFER_UDMA5 remapping case - it can't happen (ide_rate_filter() takes care of it) * fix XFER_MW_DMA0 timings (they were overclocked, use the official ones) * fix bitmasks for clearing bits of register B: - when programming DMA mode bit 0x10 of register B was cleared which resulted in overclocked PIO timing setting (iff PIO0 was used) - when programming PIO mode bits 0x18 weren't cleared so suboptimal timings were used for PIO1-4 if PIO0 was previously set (bit 0x10) and for PIO0/3/4 if PIO1/2 was previously set (bit 0x08) * add FIXME comment about missing locking for 66MHz clock register Also while at it: * remove unused defines * do a few cosmetic / CodingStyle fixes * bump driver version v2: * in pdc202xx_tune_chipset() the old content of drive configuration registers is used only by the debugging code so cover "drive_conf" PCI registers read by #if PDC202XX_DEBUG_DRIVE_INFO (Noticed by Sergei Shtylyov) Signed-off-by: Bartlomiej Zolnierkiewicz <bzolnier@gmail.com>
Diffstat (limited to 'drivers/ide')
-rw-r--r--drivers/ide/pci/pdc202xx_old.c178
1 files changed, 44 insertions, 134 deletions
diff --git a/drivers/ide/pci/pdc202xx_old.c b/drivers/ide/pci/pdc202xx_old.c
index 7146fe3f6ba7..a6dd9c815342 100644
--- a/drivers/ide/pci/pdc202xx_old.c
+++ b/drivers/ide/pci/pdc202xx_old.c
@@ -1,8 +1,9 @@
1/* 1/*
2 * linux/drivers/ide/pci/pdc202xx_old.c Version 0.36 Sept 11, 2002 2 * linux/drivers/ide/pci/pdc202xx_old.c Version 0.50 Mar 3, 2007
3 * 3 *
4 * Copyright (C) 1998-2002 Andre Hedrick <andre@linux-ide.org> 4 * Copyright (C) 1998-2002 Andre Hedrick <andre@linux-ide.org>
5 * Copyright (C) 2006-2007 MontaVista Software, Inc. 5 * Copyright (C) 2006-2007 MontaVista Software, Inc.
6 * Copyright (C) 2007 Bartlomiej Zolnierkiewicz
6 * 7 *
7 * Promise Ultra33 cards with BIOS v1.20 through 1.28 will need this 8 * Promise Ultra33 cards with BIOS v1.20 through 1.28 will need this
8 * compiled into the kernel if you have more than one card installed. 9 * compiled into the kernel if you have more than one card installed.
@@ -60,45 +61,7 @@ static const char *pdc_quirk_drives[] = {
60 NULL 61 NULL
61}; 62};
62 63
63/* A Register */ 64static void pdc_old_disable_66MHz_clock(ide_hwif_t *);
64#define SYNC_ERRDY_EN 0xC0
65
66#define SYNC_IN 0x80 /* control bit, different for master vs. slave drives */
67#define ERRDY_EN 0x40 /* control bit, different for master vs. slave drives */
68#define IORDY_EN 0x20 /* PIO: IOREADY */
69#define PREFETCH_EN 0x10 /* PIO: PREFETCH */
70
71#define PA3 0x08 /* PIO"A" timing */
72#define PA2 0x04 /* PIO"A" timing */
73#define PA1 0x02 /* PIO"A" timing */
74#define PA0 0x01 /* PIO"A" timing */
75
76/* B Register */
77
78#define MB2 0x80 /* DMA"B" timing */
79#define MB1 0x40 /* DMA"B" timing */
80#define MB0 0x20 /* DMA"B" timing */
81
82#define PB4 0x10 /* PIO_FORCE 1:0 */
83
84#define PB3 0x08 /* PIO"B" timing */ /* PIO flow Control mode */
85#define PB2 0x04 /* PIO"B" timing */ /* PIO 4 */
86#define PB1 0x02 /* PIO"B" timing */ /* PIO 3 half */
87#define PB0 0x01 /* PIO"B" timing */ /* PIO 3 other half */
88
89/* C Register */
90#define IORDYp_NO_SPEED 0x4F
91#define SPEED_DIS 0x0F
92
93#define DMARQp 0x80
94#define IORDYp 0x40
95#define DMAR_EN 0x20
96#define DMAW_EN 0x10
97
98#define MC3 0x08 /* DMA"C" timing */
99#define MC2 0x04 /* DMA"C" timing */
100#define MC1 0x02 /* DMA"C" timing */
101#define MC0 0x01 /* DMA"C" timing */
102 65
103static int pdc202xx_tune_chipset (ide_drive_t *drive, u8 xferspeed) 66static int pdc202xx_tune_chipset (ide_drive_t *drive, u8 xferspeed)
104{ 67{
@@ -107,52 +70,25 @@ static int pdc202xx_tune_chipset (ide_drive_t *drive, u8 xferspeed)
107 u8 drive_pci = 0x60 + (drive->dn << 2); 70 u8 drive_pci = 0x60 + (drive->dn << 2);
108 u8 speed = ide_rate_filter(drive, xferspeed); 71 u8 speed = ide_rate_filter(drive, xferspeed);
109 72
110 u32 drive_conf; 73 u8 AP = 0, BP = 0, CP = 0;
111 u8 AP, BP, CP, DP;
112 u8 TA = 0, TB = 0, TC = 0; 74 u8 TA = 0, TB = 0, TC = 0;
113 75
114 if (drive->media != ide_disk && 76#if PDC202XX_DEBUG_DRIVE_INFO
115 drive->media != ide_cdrom && speed < XFER_SW_DMA_0) 77 u32 drive_conf = 0;
116 return -1;
117
118 pci_read_config_dword(dev, drive_pci, &drive_conf); 78 pci_read_config_dword(dev, drive_pci, &drive_conf);
119 pci_read_config_byte(dev, (drive_pci), &AP); 79#endif
120 pci_read_config_byte(dev, (drive_pci)|0x01, &BP);
121 pci_read_config_byte(dev, (drive_pci)|0x02, &CP);
122 pci_read_config_byte(dev, (drive_pci)|0x03, &DP);
123
124 if (speed < XFER_SW_DMA_0) {
125 if ((AP & 0x0F) || (BP & 0x07)) {
126 /* clear PIO modes of lower 8421 bits of A Register */
127 pci_write_config_byte(dev, (drive_pci), AP &~0x0F);
128 pci_read_config_byte(dev, (drive_pci), &AP);
129 80
130 /* clear PIO modes of lower 421 bits of B Register */ 81 /*
131 pci_write_config_byte(dev, (drive_pci)|0x01, BP &~0x07); 82 * TODO: do this once per channel
132 pci_read_config_byte(dev, (drive_pci)|0x01, &BP); 83 */
133 84 if (dev->device != PCI_DEVICE_ID_PROMISE_20246)
134 pci_read_config_byte(dev, (drive_pci), &AP); 85 pdc_old_disable_66MHz_clock(hwif);
135 pci_read_config_byte(dev, (drive_pci)|0x01, &BP);
136 }
137 } else {
138 if ((BP & 0xF0) && (CP & 0x0F)) {
139 /* clear DMA modes of upper 842 bits of B Register */
140 /* clear PIO forced mode upper 1 bit of B Register */
141 pci_write_config_byte(dev, (drive_pci)|0x01, BP &~0xF0);
142 pci_read_config_byte(dev, (drive_pci)|0x01, &BP);
143
144 /* clear DMA modes of lower 8421 bits of C Register */
145 pci_write_config_byte(dev, (drive_pci)|0x02, CP &~0x0F);
146 pci_read_config_byte(dev, (drive_pci)|0x02, &CP);
147 }
148 }
149 86
150 pci_read_config_byte(dev, (drive_pci), &AP); 87 pci_read_config_byte(dev, drive_pci, &AP);
151 pci_read_config_byte(dev, (drive_pci)|0x01, &BP); 88 pci_read_config_byte(dev, drive_pci + 1, &BP);
152 pci_read_config_byte(dev, (drive_pci)|0x02, &CP); 89 pci_read_config_byte(dev, drive_pci + 2, &CP);
153 90
154 switch(speed) { 91 switch(speed) {
155 case XFER_UDMA_6: speed = XFER_UDMA_5;
156 case XFER_UDMA_5: 92 case XFER_UDMA_5:
157 case XFER_UDMA_4: TB = 0x20; TC = 0x01; break; 93 case XFER_UDMA_4: TB = 0x20; TC = 0x01; break;
158 case XFER_UDMA_2: TB = 0x20; TC = 0x01; break; 94 case XFER_UDMA_2: TB = 0x20; TC = 0x01; break;
@@ -161,7 +97,7 @@ static int pdc202xx_tune_chipset (ide_drive_t *drive, u8 xferspeed)
161 case XFER_UDMA_0: 97 case XFER_UDMA_0:
162 case XFER_MW_DMA_2: TB = 0x60; TC = 0x03; break; 98 case XFER_MW_DMA_2: TB = 0x60; TC = 0x03; break;
163 case XFER_MW_DMA_1: TB = 0x60; TC = 0x04; break; 99 case XFER_MW_DMA_1: TB = 0x60; TC = 0x04; break;
164 case XFER_MW_DMA_0: 100 case XFER_MW_DMA_0: TB = 0xE0; TC = 0x0F; break;
165 case XFER_SW_DMA_2: TB = 0x60; TC = 0x05; break; 101 case XFER_SW_DMA_2: TB = 0x60; TC = 0x05; break;
166 case XFER_SW_DMA_1: TB = 0x80; TC = 0x06; break; 102 case XFER_SW_DMA_1: TB = 0x80; TC = 0x06; break;
167 case XFER_SW_DMA_0: TB = 0xC0; TC = 0x0B; break; 103 case XFER_SW_DMA_0: TB = 0xC0; TC = 0x0B; break;
@@ -174,25 +110,39 @@ static int pdc202xx_tune_chipset (ide_drive_t *drive, u8 xferspeed)
174 } 110 }
175 111
176 if (speed < XFER_SW_DMA_0) { 112 if (speed < XFER_SW_DMA_0) {
177 pci_write_config_byte(dev, (drive_pci), AP|TA); 113 /*
178 pci_write_config_byte(dev, (drive_pci)|0x01, BP|TB); 114 * preserve SYNC_INT / ERDDY_EN bits while clearing
115 * Prefetch_EN / IORDY_EN / PA[3:0] bits of register A
116 */
117 AP &= ~0x3f;
118 if (drive->id->capability & 4)
119 AP |= 0x20; /* set IORDY_EN bit */
120 if (drive->media == ide_disk)
121 AP |= 0x10; /* set Prefetch_EN bit */
122 /* clear PB[4:0] bits of register B */
123 BP &= ~0x1f;
124 pci_write_config_byte(dev, drive_pci, AP | TA);
125 pci_write_config_byte(dev, drive_pci + 1, BP | TB);
179 } else { 126 } else {
180 pci_write_config_byte(dev, (drive_pci)|0x01, BP|TB); 127 /* clear MB[2:0] bits of register B */
181 pci_write_config_byte(dev, (drive_pci)|0x02, CP|TC); 128 BP &= ~0xe0;
129 /* clear MC[3:0] bits of register C */
130 CP &= ~0x0f;
131 pci_write_config_byte(dev, drive_pci + 1, BP | TB);
132 pci_write_config_byte(dev, drive_pci + 2, CP | TC);
182 } 133 }
183 134
184#if PDC202XX_DEBUG_DRIVE_INFO 135#if PDC202XX_DEBUG_DRIVE_INFO
185 printk(KERN_DEBUG "%s: %s drive%d 0x%08x ", 136 printk(KERN_DEBUG "%s: %s drive%d 0x%08x ",
186 drive->name, ide_xfer_verbose(speed), 137 drive->name, ide_xfer_verbose(speed),
187 drive->dn, drive_conf); 138 drive->dn, drive_conf);
188 pci_read_config_dword(dev, drive_pci, &drive_conf); 139 pci_read_config_dword(dev, drive_pci, &drive_conf);
189 printk("0x%08x\n", drive_conf); 140 printk("0x%08x\n", drive_conf);
190#endif /* PDC202XX_DEBUG_DRIVE_INFO */ 141#endif
191 142
192 return (ide_config_drive_speed(drive, speed)); 143 return ide_config_drive_speed(drive, speed);
193} 144}
194 145
195
196static void pdc202xx_tune_drive(ide_drive_t *drive, u8 pio) 146static void pdc202xx_tune_drive(ide_drive_t *drive, u8 pio)
197{ 147{
198 pio = ide_get_best_pio_mode(drive, pio, 4, NULL); 148 pio = ide_get_best_pio_mode(drive, pio, 4, NULL);
@@ -210,6 +160,8 @@ static u8 pdc202xx_old_cable_detect (ide_hwif_t *hwif)
210 * Set the control register to use the 66MHz system 160 * Set the control register to use the 66MHz system
211 * clock for UDMA 3/4/5 mode operation when necessary. 161 * clock for UDMA 3/4/5 mode operation when necessary.
212 * 162 *
163 * FIXME: this register is shared by both channels, some locking is needed
164 *
213 * It may also be possible to leave the 66MHz clock on 165 * It may also be possible to leave the 66MHz clock on
214 * and readjust the timing parameters. 166 * and readjust the timing parameters.
215 */ 167 */
@@ -231,55 +183,13 @@ static void pdc_old_disable_66MHz_clock(ide_hwif_t *hwif)
231 183
232static int config_chipset_for_dma (ide_drive_t *drive) 184static int config_chipset_for_dma (ide_drive_t *drive)
233{ 185{
234 struct hd_driveid *id = drive->id; 186 u8 speed = ide_max_dma_mode(drive);
235 ide_hwif_t *hwif = HWIF(drive);
236 struct pci_dev *dev = hwif->pci_dev;
237 u32 drive_conf = 0;
238 u8 drive_pci = 0x60 + (drive->dn << 2);
239 u8 test1 = 0, test2 = 0, speed = -1;
240 u8 AP = 0;
241
242 if (dev->device != PCI_DEVICE_ID_PROMISE_20246)
243 pdc_old_disable_66MHz_clock(drive->hwif);
244 187
245 drive_pci = 0x60 + (drive->dn << 2); 188 if (!speed)
246 pci_read_config_dword(dev, drive_pci, &drive_conf);
247 if ((drive_conf != 0x004ff304) && (drive_conf != 0x004ff3c4))
248 goto chipset_is_set;
249
250 pci_read_config_byte(dev, drive_pci, &test1);
251 if (!(test1 & SYNC_ERRDY_EN)) {
252 if (drive->select.b.unit & 0x01) {
253 pci_read_config_byte(dev, drive_pci - 4, &test2);
254 if ((test2 & SYNC_ERRDY_EN) &&
255 !(test1 & SYNC_ERRDY_EN)) {
256 pci_write_config_byte(dev, drive_pci,
257 test1|SYNC_ERRDY_EN);
258 }
259 } else {
260 pci_write_config_byte(dev, drive_pci,
261 test1|SYNC_ERRDY_EN);
262 }
263 }
264
265chipset_is_set:
266
267 pci_read_config_byte(dev, (drive_pci), &AP);
268 if (id->capability & 4) /* IORDY_EN */
269 pci_write_config_byte(dev, (drive_pci), AP|IORDY_EN);
270 pci_read_config_byte(dev, (drive_pci), &AP);
271 if (drive->media == ide_disk) /* PREFETCH_EN */
272 pci_write_config_byte(dev, (drive_pci), AP|PREFETCH_EN);
273
274 speed = ide_max_dma_mode(drive);
275
276 if (!(speed)) {
277 /* restore original pci-config space */
278 pci_write_config_dword(dev, drive_pci, drive_conf);
279 return 0; 189 return 0;
280 }
281 190
282 (void) hwif->speedproc(drive, speed); 191 (void)pdc202xx_tune_chipset(drive, speed);
192
283 return ide_dma_enable(drive); 193 return ide_dma_enable(drive);
284} 194}
285 195