diff options
Diffstat (limited to 'drivers/ide/sl82c105.c')
-rw-r--r-- | drivers/ide/sl82c105.c | 371 |
1 files changed, 371 insertions, 0 deletions
diff --git a/drivers/ide/sl82c105.c b/drivers/ide/sl82c105.c new file mode 100644 index 000000000000..84dc33602ff8 --- /dev/null +++ b/drivers/ide/sl82c105.c | |||
@@ -0,0 +1,371 @@ | |||
1 | /* | ||
2 | * SL82C105/Winbond 553 IDE driver | ||
3 | * | ||
4 | * Maintainer unknown. | ||
5 | * | ||
6 | * Drive tuning added from Rebel.com's kernel sources | ||
7 | * -- Russell King (15/11/98) linux@arm.linux.org.uk | ||
8 | * | ||
9 | * Merge in Russell's HW workarounds, fix various problems | ||
10 | * with the timing registers setup. | ||
11 | * -- Benjamin Herrenschmidt (01/11/03) benh@kernel.crashing.org | ||
12 | * | ||
13 | * Copyright (C) 2006-2007 MontaVista Software, Inc. <source@mvista.com> | ||
14 | * Copyright (C) 2007 Bartlomiej Zolnierkiewicz | ||
15 | */ | ||
16 | |||
17 | #include <linux/types.h> | ||
18 | #include <linux/module.h> | ||
19 | #include <linux/kernel.h> | ||
20 | #include <linux/pci.h> | ||
21 | #include <linux/ide.h> | ||
22 | |||
23 | #include <asm/io.h> | ||
24 | |||
25 | #define DRV_NAME "sl82c105" | ||
26 | |||
27 | #undef DEBUG | ||
28 | |||
29 | #ifdef DEBUG | ||
30 | #define DBG(arg) printk arg | ||
31 | #else | ||
32 | #define DBG(fmt,...) | ||
33 | #endif | ||
34 | /* | ||
35 | * SL82C105 PCI config register 0x40 bits. | ||
36 | */ | ||
37 | #define CTRL_IDE_IRQB (1 << 30) | ||
38 | #define CTRL_IDE_IRQA (1 << 28) | ||
39 | #define CTRL_LEGIRQ (1 << 11) | ||
40 | #define CTRL_P1F16 (1 << 5) | ||
41 | #define CTRL_P1EN (1 << 4) | ||
42 | #define CTRL_P0F16 (1 << 1) | ||
43 | #define CTRL_P0EN (1 << 0) | ||
44 | |||
45 | /* | ||
46 | * Convert a PIO mode and cycle time to the required on/off times | ||
47 | * for the interface. This has protection against runaway timings. | ||
48 | */ | ||
49 | static unsigned int get_pio_timings(ide_drive_t *drive, u8 pio) | ||
50 | { | ||
51 | struct ide_timing *t = ide_timing_find_mode(XFER_PIO_0 + pio); | ||
52 | unsigned int cmd_on, cmd_off; | ||
53 | u8 iordy = 0; | ||
54 | |||
55 | cmd_on = (t->active + 29) / 30; | ||
56 | cmd_off = (ide_pio_cycle_time(drive, pio) - 30 * cmd_on + 29) / 30; | ||
57 | |||
58 | if (cmd_on == 0) | ||
59 | cmd_on = 1; | ||
60 | |||
61 | if (cmd_off == 0) | ||
62 | cmd_off = 1; | ||
63 | |||
64 | if (pio > 2 || ata_id_has_iordy(drive->id)) | ||
65 | iordy = 0x40; | ||
66 | |||
67 | return (cmd_on - 1) << 8 | (cmd_off - 1) | iordy; | ||
68 | } | ||
69 | |||
70 | /* | ||
71 | * Configure the chipset for PIO mode. | ||
72 | */ | ||
73 | static void sl82c105_set_pio_mode(ide_drive_t *drive, const u8 pio) | ||
74 | { | ||
75 | struct pci_dev *dev = to_pci_dev(drive->hwif->dev); | ||
76 | int reg = 0x44 + drive->dn * 4; | ||
77 | u16 drv_ctrl; | ||
78 | |||
79 | drv_ctrl = get_pio_timings(drive, pio); | ||
80 | |||
81 | /* | ||
82 | * Store the PIO timings so that we can restore them | ||
83 | * in case DMA will be turned off... | ||
84 | */ | ||
85 | drive->drive_data &= 0xffff0000; | ||
86 | drive->drive_data |= drv_ctrl; | ||
87 | |||
88 | pci_write_config_word(dev, reg, drv_ctrl); | ||
89 | pci_read_config_word (dev, reg, &drv_ctrl); | ||
90 | |||
91 | printk(KERN_DEBUG "%s: selected %s (%dns) (%04X)\n", drive->name, | ||
92 | ide_xfer_verbose(pio + XFER_PIO_0), | ||
93 | ide_pio_cycle_time(drive, pio), drv_ctrl); | ||
94 | } | ||
95 | |||
96 | /* | ||
97 | * Configure the chipset for DMA mode. | ||
98 | */ | ||
99 | static void sl82c105_set_dma_mode(ide_drive_t *drive, const u8 speed) | ||
100 | { | ||
101 | static u16 mwdma_timings[] = {0x0707, 0x0201, 0x0200}; | ||
102 | u16 drv_ctrl; | ||
103 | |||
104 | DBG(("sl82c105_tune_chipset(drive:%s, speed:%s)\n", | ||
105 | drive->name, ide_xfer_verbose(speed))); | ||
106 | |||
107 | drv_ctrl = mwdma_timings[speed - XFER_MW_DMA_0]; | ||
108 | |||
109 | /* | ||
110 | * Store the DMA timings so that we can actually program | ||
111 | * them when DMA will be turned on... | ||
112 | */ | ||
113 | drive->drive_data &= 0x0000ffff; | ||
114 | drive->drive_data |= (unsigned long)drv_ctrl << 16; | ||
115 | } | ||
116 | |||
117 | /* | ||
118 | * The SL82C105 holds off all IDE interrupts while in DMA mode until | ||
119 | * all DMA activity is completed. Sometimes this causes problems (eg, | ||
120 | * when the drive wants to report an error condition). | ||
121 | * | ||
122 | * 0x7e is a "chip testing" register. Bit 2 resets the DMA controller | ||
123 | * state machine. We need to kick this to work around various bugs. | ||
124 | */ | ||
125 | static inline void sl82c105_reset_host(struct pci_dev *dev) | ||
126 | { | ||
127 | u16 val; | ||
128 | |||
129 | pci_read_config_word(dev, 0x7e, &val); | ||
130 | pci_write_config_word(dev, 0x7e, val | (1 << 2)); | ||
131 | pci_write_config_word(dev, 0x7e, val & ~(1 << 2)); | ||
132 | } | ||
133 | |||
134 | /* | ||
135 | * If we get an IRQ timeout, it might be that the DMA state machine | ||
136 | * got confused. Fix from Todd Inglett. Details from Winbond. | ||
137 | * | ||
138 | * This function is called when the IDE timer expires, the drive | ||
139 | * indicates that it is READY, and we were waiting for DMA to complete. | ||
140 | */ | ||
141 | static void sl82c105_dma_lost_irq(ide_drive_t *drive) | ||
142 | { | ||
143 | ide_hwif_t *hwif = HWIF(drive); | ||
144 | struct pci_dev *dev = to_pci_dev(hwif->dev); | ||
145 | u32 val, mask = hwif->channel ? CTRL_IDE_IRQB : CTRL_IDE_IRQA; | ||
146 | u8 dma_cmd; | ||
147 | |||
148 | printk("sl82c105: lost IRQ, resetting host\n"); | ||
149 | |||
150 | /* | ||
151 | * Check the raw interrupt from the drive. | ||
152 | */ | ||
153 | pci_read_config_dword(dev, 0x40, &val); | ||
154 | if (val & mask) | ||
155 | printk("sl82c105: drive was requesting IRQ, but host lost it\n"); | ||
156 | |||
157 | /* | ||
158 | * Was DMA enabled? If so, disable it - we're resetting the | ||
159 | * host. The IDE layer will be handling the drive for us. | ||
160 | */ | ||
161 | dma_cmd = inb(hwif->dma_base + ATA_DMA_CMD); | ||
162 | if (dma_cmd & 1) { | ||
163 | outb(dma_cmd & ~1, hwif->dma_base + ATA_DMA_CMD); | ||
164 | printk("sl82c105: DMA was enabled\n"); | ||
165 | } | ||
166 | |||
167 | sl82c105_reset_host(dev); | ||
168 | } | ||
169 | |||
170 | /* | ||
171 | * ATAPI devices can cause the SL82C105 DMA state machine to go gaga. | ||
172 | * Winbond recommend that the DMA state machine is reset prior to | ||
173 | * setting the bus master DMA enable bit. | ||
174 | * | ||
175 | * The generic IDE core will have disabled the BMEN bit before this | ||
176 | * function is called. | ||
177 | */ | ||
178 | static void sl82c105_dma_start(ide_drive_t *drive) | ||
179 | { | ||
180 | ide_hwif_t *hwif = HWIF(drive); | ||
181 | struct pci_dev *dev = to_pci_dev(hwif->dev); | ||
182 | int reg = 0x44 + drive->dn * 4; | ||
183 | |||
184 | DBG(("%s(drive:%s)\n", __func__, drive->name)); | ||
185 | |||
186 | pci_write_config_word(dev, reg, drive->drive_data >> 16); | ||
187 | |||
188 | sl82c105_reset_host(dev); | ||
189 | ide_dma_start(drive); | ||
190 | } | ||
191 | |||
192 | static void sl82c105_dma_timeout(ide_drive_t *drive) | ||
193 | { | ||
194 | struct pci_dev *dev = to_pci_dev(drive->hwif->dev); | ||
195 | |||
196 | DBG(("sl82c105_dma_timeout(drive:%s)\n", drive->name)); | ||
197 | |||
198 | sl82c105_reset_host(dev); | ||
199 | ide_dma_timeout(drive); | ||
200 | } | ||
201 | |||
202 | static int sl82c105_dma_end(ide_drive_t *drive) | ||
203 | { | ||
204 | struct pci_dev *dev = to_pci_dev(drive->hwif->dev); | ||
205 | int reg = 0x44 + drive->dn * 4; | ||
206 | int ret; | ||
207 | |||
208 | DBG(("%s(drive:%s)\n", __func__, drive->name)); | ||
209 | |||
210 | ret = ide_dma_end(drive); | ||
211 | |||
212 | pci_write_config_word(dev, reg, drive->drive_data); | ||
213 | |||
214 | return ret; | ||
215 | } | ||
216 | |||
217 | /* | ||
218 | * ATA reset will clear the 16 bits mode in the control | ||
219 | * register, we need to reprogram it | ||
220 | */ | ||
221 | static void sl82c105_resetproc(ide_drive_t *drive) | ||
222 | { | ||
223 | struct pci_dev *dev = to_pci_dev(drive->hwif->dev); | ||
224 | u32 val; | ||
225 | |||
226 | DBG(("sl82c105_resetproc(drive:%s)\n", drive->name)); | ||
227 | |||
228 | pci_read_config_dword(dev, 0x40, &val); | ||
229 | val |= (CTRL_P1F16 | CTRL_P0F16); | ||
230 | pci_write_config_dword(dev, 0x40, val); | ||
231 | } | ||
232 | |||
233 | /* | ||
234 | * Return the revision of the Winbond bridge | ||
235 | * which this function is part of. | ||
236 | */ | ||
237 | static u8 sl82c105_bridge_revision(struct pci_dev *dev) | ||
238 | { | ||
239 | struct pci_dev *bridge; | ||
240 | |||
241 | /* | ||
242 | * The bridge should be part of the same device, but function 0. | ||
243 | */ | ||
244 | bridge = pci_get_bus_and_slot(dev->bus->number, | ||
245 | PCI_DEVFN(PCI_SLOT(dev->devfn), 0)); | ||
246 | if (!bridge) | ||
247 | return -1; | ||
248 | |||
249 | /* | ||
250 | * Make sure it is a Winbond 553 and is an ISA bridge. | ||
251 | */ | ||
252 | if (bridge->vendor != PCI_VENDOR_ID_WINBOND || | ||
253 | bridge->device != PCI_DEVICE_ID_WINBOND_83C553 || | ||
254 | bridge->class >> 8 != PCI_CLASS_BRIDGE_ISA) { | ||
255 | pci_dev_put(bridge); | ||
256 | return -1; | ||
257 | } | ||
258 | /* | ||
259 | * We need to find function 0's revision, not function 1 | ||
260 | */ | ||
261 | pci_dev_put(bridge); | ||
262 | |||
263 | return bridge->revision; | ||
264 | } | ||
265 | |||
266 | /* | ||
267 | * Enable the PCI device | ||
268 | * | ||
269 | * --BenH: It's arch fixup code that should enable channels that | ||
270 | * have not been enabled by firmware. I decided we can still enable | ||
271 | * channel 0 here at least, but channel 1 has to be enabled by | ||
272 | * firmware or arch code. We still set both to 16 bits mode. | ||
273 | */ | ||
274 | static unsigned int init_chipset_sl82c105(struct pci_dev *dev) | ||
275 | { | ||
276 | u32 val; | ||
277 | |||
278 | DBG(("init_chipset_sl82c105()\n")); | ||
279 | |||
280 | pci_read_config_dword(dev, 0x40, &val); | ||
281 | val |= CTRL_P0EN | CTRL_P0F16 | CTRL_P1F16; | ||
282 | pci_write_config_dword(dev, 0x40, val); | ||
283 | |||
284 | return dev->irq; | ||
285 | } | ||
286 | |||
287 | static const struct ide_port_ops sl82c105_port_ops = { | ||
288 | .set_pio_mode = sl82c105_set_pio_mode, | ||
289 | .set_dma_mode = sl82c105_set_dma_mode, | ||
290 | .resetproc = sl82c105_resetproc, | ||
291 | }; | ||
292 | |||
293 | static const struct ide_dma_ops sl82c105_dma_ops = { | ||
294 | .dma_host_set = ide_dma_host_set, | ||
295 | .dma_setup = ide_dma_setup, | ||
296 | .dma_exec_cmd = ide_dma_exec_cmd, | ||
297 | .dma_start = sl82c105_dma_start, | ||
298 | .dma_end = sl82c105_dma_end, | ||
299 | .dma_test_irq = ide_dma_test_irq, | ||
300 | .dma_lost_irq = sl82c105_dma_lost_irq, | ||
301 | .dma_timeout = sl82c105_dma_timeout, | ||
302 | }; | ||
303 | |||
304 | static const struct ide_port_info sl82c105_chipset __devinitdata = { | ||
305 | .name = DRV_NAME, | ||
306 | .init_chipset = init_chipset_sl82c105, | ||
307 | .enablebits = {{0x40,0x01,0x01}, {0x40,0x10,0x10}}, | ||
308 | .port_ops = &sl82c105_port_ops, | ||
309 | .dma_ops = &sl82c105_dma_ops, | ||
310 | .host_flags = IDE_HFLAG_IO_32BIT | | ||
311 | IDE_HFLAG_UNMASK_IRQS | | ||
312 | /* FIXME: check for Compatibility mode in generic IDE PCI code */ | ||
313 | #if defined(CONFIG_LOPEC) || defined(CONFIG_SANDPOINT) | ||
314 | IDE_HFLAG_FORCE_LEGACY_IRQS | | ||
315 | #endif | ||
316 | IDE_HFLAG_SERIALIZE_DMA | | ||
317 | IDE_HFLAG_NO_AUTODMA, | ||
318 | .pio_mask = ATA_PIO5, | ||
319 | .mwdma_mask = ATA_MWDMA2, | ||
320 | }; | ||
321 | |||
322 | static int __devinit sl82c105_init_one(struct pci_dev *dev, const struct pci_device_id *id) | ||
323 | { | ||
324 | struct ide_port_info d = sl82c105_chipset; | ||
325 | u8 rev = sl82c105_bridge_revision(dev); | ||
326 | |||
327 | if (rev <= 5) { | ||
328 | /* | ||
329 | * Never ever EVER under any circumstances enable | ||
330 | * DMA when the bridge is this old. | ||
331 | */ | ||
332 | printk(KERN_INFO DRV_NAME ": Winbond W83C553 bridge " | ||
333 | "revision %d, BM-DMA disabled\n", rev); | ||
334 | d.dma_ops = NULL; | ||
335 | d.mwdma_mask = 0; | ||
336 | d.host_flags &= ~IDE_HFLAG_SERIALIZE_DMA; | ||
337 | } | ||
338 | |||
339 | return ide_pci_init_one(dev, &d, NULL); | ||
340 | } | ||
341 | |||
342 | static const struct pci_device_id sl82c105_pci_tbl[] = { | ||
343 | { PCI_VDEVICE(WINBOND, PCI_DEVICE_ID_WINBOND_82C105), 0 }, | ||
344 | { 0, }, | ||
345 | }; | ||
346 | MODULE_DEVICE_TABLE(pci, sl82c105_pci_tbl); | ||
347 | |||
348 | static struct pci_driver sl82c105_pci_driver = { | ||
349 | .name = "W82C105_IDE", | ||
350 | .id_table = sl82c105_pci_tbl, | ||
351 | .probe = sl82c105_init_one, | ||
352 | .remove = ide_pci_remove, | ||
353 | .suspend = ide_pci_suspend, | ||
354 | .resume = ide_pci_resume, | ||
355 | }; | ||
356 | |||
357 | static int __init sl82c105_ide_init(void) | ||
358 | { | ||
359 | return ide_pci_register_driver(&sl82c105_pci_driver); | ||
360 | } | ||
361 | |||
362 | static void __exit sl82c105_ide_exit(void) | ||
363 | { | ||
364 | pci_unregister_driver(&sl82c105_pci_driver); | ||
365 | } | ||
366 | |||
367 | module_init(sl82c105_ide_init); | ||
368 | module_exit(sl82c105_ide_exit); | ||
369 | |||
370 | MODULE_DESCRIPTION("PCI driver module for W82C105 IDE"); | ||
371 | MODULE_LICENSE("GPL"); | ||