18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * SL82C105/Winbond 553 IDE driver 48c2ecf20Sopenharmony_ci * 58c2ecf20Sopenharmony_ci * Maintainer unknown. 68c2ecf20Sopenharmony_ci * 78c2ecf20Sopenharmony_ci * Drive tuning added from Rebel.com's kernel sources 88c2ecf20Sopenharmony_ci * -- Russell King (15/11/98) linux@arm.linux.org.uk 98c2ecf20Sopenharmony_ci * 108c2ecf20Sopenharmony_ci * Merge in Russell's HW workarounds, fix various problems 118c2ecf20Sopenharmony_ci * with the timing registers setup. 128c2ecf20Sopenharmony_ci * -- Benjamin Herrenschmidt (01/11/03) benh@kernel.crashing.org 138c2ecf20Sopenharmony_ci * 148c2ecf20Sopenharmony_ci * Copyright (C) 2006-2007,2009 MontaVista Software, Inc. <source@mvista.com> 158c2ecf20Sopenharmony_ci * Copyright (C) 2007 Bartlomiej Zolnierkiewicz 168c2ecf20Sopenharmony_ci */ 178c2ecf20Sopenharmony_ci 188c2ecf20Sopenharmony_ci#include <linux/types.h> 198c2ecf20Sopenharmony_ci#include <linux/module.h> 208c2ecf20Sopenharmony_ci#include <linux/kernel.h> 218c2ecf20Sopenharmony_ci#include <linux/pci.h> 228c2ecf20Sopenharmony_ci#include <linux/ide.h> 238c2ecf20Sopenharmony_ci 248c2ecf20Sopenharmony_ci#include <asm/io.h> 258c2ecf20Sopenharmony_ci 268c2ecf20Sopenharmony_ci#define DRV_NAME "sl82c105" 278c2ecf20Sopenharmony_ci 288c2ecf20Sopenharmony_ci/* 298c2ecf20Sopenharmony_ci * SL82C105 PCI config register 0x40 bits. 308c2ecf20Sopenharmony_ci */ 318c2ecf20Sopenharmony_ci#define CTRL_IDE_IRQB (1 << 30) 328c2ecf20Sopenharmony_ci#define CTRL_IDE_IRQA (1 << 28) 338c2ecf20Sopenharmony_ci#define CTRL_LEGIRQ (1 << 11) 348c2ecf20Sopenharmony_ci#define CTRL_P1F16 (1 << 5) 358c2ecf20Sopenharmony_ci#define CTRL_P1EN (1 << 4) 368c2ecf20Sopenharmony_ci#define CTRL_P0F16 (1 << 1) 378c2ecf20Sopenharmony_ci#define CTRL_P0EN (1 << 0) 388c2ecf20Sopenharmony_ci 398c2ecf20Sopenharmony_ci/* 408c2ecf20Sopenharmony_ci * Convert a PIO mode and cycle time to the required on/off times 418c2ecf20Sopenharmony_ci * for the interface. This has protection against runaway timings. 428c2ecf20Sopenharmony_ci */ 438c2ecf20Sopenharmony_cistatic unsigned int get_pio_timings(ide_drive_t *drive, u8 pio) 448c2ecf20Sopenharmony_ci{ 458c2ecf20Sopenharmony_ci struct ide_timing *t = ide_timing_find_mode(XFER_PIO_0 + pio); 468c2ecf20Sopenharmony_ci unsigned int cmd_on, cmd_off; 478c2ecf20Sopenharmony_ci u8 iordy = 0; 488c2ecf20Sopenharmony_ci 498c2ecf20Sopenharmony_ci cmd_on = (t->active + 29) / 30; 508c2ecf20Sopenharmony_ci cmd_off = (ide_pio_cycle_time(drive, pio) - 30 * cmd_on + 29) / 30; 518c2ecf20Sopenharmony_ci 528c2ecf20Sopenharmony_ci if (cmd_on == 0) 538c2ecf20Sopenharmony_ci cmd_on = 1; 548c2ecf20Sopenharmony_ci 558c2ecf20Sopenharmony_ci if (cmd_off == 0) 568c2ecf20Sopenharmony_ci cmd_off = 1; 578c2ecf20Sopenharmony_ci 588c2ecf20Sopenharmony_ci if (ide_pio_need_iordy(drive, pio)) 598c2ecf20Sopenharmony_ci iordy = 0x40; 608c2ecf20Sopenharmony_ci 618c2ecf20Sopenharmony_ci return (cmd_on - 1) << 8 | (cmd_off - 1) | iordy; 628c2ecf20Sopenharmony_ci} 638c2ecf20Sopenharmony_ci 648c2ecf20Sopenharmony_ci/* 658c2ecf20Sopenharmony_ci * Configure the chipset for PIO mode. 668c2ecf20Sopenharmony_ci */ 678c2ecf20Sopenharmony_cistatic void sl82c105_set_pio_mode(ide_hwif_t *hwif, ide_drive_t *drive) 688c2ecf20Sopenharmony_ci{ 698c2ecf20Sopenharmony_ci struct pci_dev *dev = to_pci_dev(hwif->dev); 708c2ecf20Sopenharmony_ci unsigned long timings = (unsigned long)ide_get_drivedata(drive); 718c2ecf20Sopenharmony_ci int reg = 0x44 + drive->dn * 4; 728c2ecf20Sopenharmony_ci u16 drv_ctrl; 738c2ecf20Sopenharmony_ci const u8 pio = drive->pio_mode - XFER_PIO_0; 748c2ecf20Sopenharmony_ci 758c2ecf20Sopenharmony_ci drv_ctrl = get_pio_timings(drive, pio); 768c2ecf20Sopenharmony_ci 778c2ecf20Sopenharmony_ci /* 788c2ecf20Sopenharmony_ci * Store the PIO timings so that we can restore them 798c2ecf20Sopenharmony_ci * in case DMA will be turned off... 808c2ecf20Sopenharmony_ci */ 818c2ecf20Sopenharmony_ci timings &= 0xffff0000; 828c2ecf20Sopenharmony_ci timings |= drv_ctrl; 838c2ecf20Sopenharmony_ci ide_set_drivedata(drive, (void *)timings); 848c2ecf20Sopenharmony_ci 858c2ecf20Sopenharmony_ci pci_write_config_word(dev, reg, drv_ctrl); 868c2ecf20Sopenharmony_ci pci_read_config_word (dev, reg, &drv_ctrl); 878c2ecf20Sopenharmony_ci 888c2ecf20Sopenharmony_ci printk(KERN_DEBUG "%s: selected %s (%dns) (%04X)\n", drive->name, 898c2ecf20Sopenharmony_ci ide_xfer_verbose(pio + XFER_PIO_0), 908c2ecf20Sopenharmony_ci ide_pio_cycle_time(drive, pio), drv_ctrl); 918c2ecf20Sopenharmony_ci} 928c2ecf20Sopenharmony_ci 938c2ecf20Sopenharmony_ci/* 948c2ecf20Sopenharmony_ci * Configure the chipset for DMA mode. 958c2ecf20Sopenharmony_ci */ 968c2ecf20Sopenharmony_cistatic void sl82c105_set_dma_mode(ide_hwif_t *hwif, ide_drive_t *drive) 978c2ecf20Sopenharmony_ci{ 988c2ecf20Sopenharmony_ci static u16 mwdma_timings[] = {0x0707, 0x0201, 0x0200}; 998c2ecf20Sopenharmony_ci unsigned long timings = (unsigned long)ide_get_drivedata(drive); 1008c2ecf20Sopenharmony_ci u16 drv_ctrl; 1018c2ecf20Sopenharmony_ci const u8 speed = drive->dma_mode; 1028c2ecf20Sopenharmony_ci 1038c2ecf20Sopenharmony_ci drv_ctrl = mwdma_timings[speed - XFER_MW_DMA_0]; 1048c2ecf20Sopenharmony_ci 1058c2ecf20Sopenharmony_ci /* 1068c2ecf20Sopenharmony_ci * Store the DMA timings so that we can actually program 1078c2ecf20Sopenharmony_ci * them when DMA will be turned on... 1088c2ecf20Sopenharmony_ci */ 1098c2ecf20Sopenharmony_ci timings &= 0x0000ffff; 1108c2ecf20Sopenharmony_ci timings |= (unsigned long)drv_ctrl << 16; 1118c2ecf20Sopenharmony_ci ide_set_drivedata(drive, (void *)timings); 1128c2ecf20Sopenharmony_ci} 1138c2ecf20Sopenharmony_ci 1148c2ecf20Sopenharmony_cistatic int sl82c105_test_irq(ide_hwif_t *hwif) 1158c2ecf20Sopenharmony_ci{ 1168c2ecf20Sopenharmony_ci struct pci_dev *dev = to_pci_dev(hwif->dev); 1178c2ecf20Sopenharmony_ci u32 val, mask = hwif->channel ? CTRL_IDE_IRQB : CTRL_IDE_IRQA; 1188c2ecf20Sopenharmony_ci 1198c2ecf20Sopenharmony_ci pci_read_config_dword(dev, 0x40, &val); 1208c2ecf20Sopenharmony_ci 1218c2ecf20Sopenharmony_ci return (val & mask) ? 1 : 0; 1228c2ecf20Sopenharmony_ci} 1238c2ecf20Sopenharmony_ci 1248c2ecf20Sopenharmony_ci/* 1258c2ecf20Sopenharmony_ci * The SL82C105 holds off all IDE interrupts while in DMA mode until 1268c2ecf20Sopenharmony_ci * all DMA activity is completed. Sometimes this causes problems (eg, 1278c2ecf20Sopenharmony_ci * when the drive wants to report an error condition). 1288c2ecf20Sopenharmony_ci * 1298c2ecf20Sopenharmony_ci * 0x7e is a "chip testing" register. Bit 2 resets the DMA controller 1308c2ecf20Sopenharmony_ci * state machine. We need to kick this to work around various bugs. 1318c2ecf20Sopenharmony_ci */ 1328c2ecf20Sopenharmony_cistatic inline void sl82c105_reset_host(struct pci_dev *dev) 1338c2ecf20Sopenharmony_ci{ 1348c2ecf20Sopenharmony_ci u16 val; 1358c2ecf20Sopenharmony_ci 1368c2ecf20Sopenharmony_ci pci_read_config_word(dev, 0x7e, &val); 1378c2ecf20Sopenharmony_ci pci_write_config_word(dev, 0x7e, val | (1 << 2)); 1388c2ecf20Sopenharmony_ci pci_write_config_word(dev, 0x7e, val & ~(1 << 2)); 1398c2ecf20Sopenharmony_ci} 1408c2ecf20Sopenharmony_ci 1418c2ecf20Sopenharmony_ci/* 1428c2ecf20Sopenharmony_ci * If we get an IRQ timeout, it might be that the DMA state machine 1438c2ecf20Sopenharmony_ci * got confused. Fix from Todd Inglett. Details from Winbond. 1448c2ecf20Sopenharmony_ci * 1458c2ecf20Sopenharmony_ci * This function is called when the IDE timer expires, the drive 1468c2ecf20Sopenharmony_ci * indicates that it is READY, and we were waiting for DMA to complete. 1478c2ecf20Sopenharmony_ci */ 1488c2ecf20Sopenharmony_cistatic void sl82c105_dma_lost_irq(ide_drive_t *drive) 1498c2ecf20Sopenharmony_ci{ 1508c2ecf20Sopenharmony_ci ide_hwif_t *hwif = drive->hwif; 1518c2ecf20Sopenharmony_ci struct pci_dev *dev = to_pci_dev(hwif->dev); 1528c2ecf20Sopenharmony_ci u32 val, mask = hwif->channel ? CTRL_IDE_IRQB : CTRL_IDE_IRQA; 1538c2ecf20Sopenharmony_ci u8 dma_cmd; 1548c2ecf20Sopenharmony_ci 1558c2ecf20Sopenharmony_ci printk(KERN_WARNING "sl82c105: lost IRQ, resetting host\n"); 1568c2ecf20Sopenharmony_ci 1578c2ecf20Sopenharmony_ci /* 1588c2ecf20Sopenharmony_ci * Check the raw interrupt from the drive. 1598c2ecf20Sopenharmony_ci */ 1608c2ecf20Sopenharmony_ci pci_read_config_dword(dev, 0x40, &val); 1618c2ecf20Sopenharmony_ci if (val & mask) 1628c2ecf20Sopenharmony_ci printk(KERN_INFO "sl82c105: drive was requesting IRQ, " 1638c2ecf20Sopenharmony_ci "but host lost it\n"); 1648c2ecf20Sopenharmony_ci 1658c2ecf20Sopenharmony_ci /* 1668c2ecf20Sopenharmony_ci * Was DMA enabled? If so, disable it - we're resetting the 1678c2ecf20Sopenharmony_ci * host. The IDE layer will be handling the drive for us. 1688c2ecf20Sopenharmony_ci */ 1698c2ecf20Sopenharmony_ci dma_cmd = inb(hwif->dma_base + ATA_DMA_CMD); 1708c2ecf20Sopenharmony_ci if (dma_cmd & 1) { 1718c2ecf20Sopenharmony_ci outb(dma_cmd & ~1, hwif->dma_base + ATA_DMA_CMD); 1728c2ecf20Sopenharmony_ci printk(KERN_INFO "sl82c105: DMA was enabled\n"); 1738c2ecf20Sopenharmony_ci } 1748c2ecf20Sopenharmony_ci 1758c2ecf20Sopenharmony_ci sl82c105_reset_host(dev); 1768c2ecf20Sopenharmony_ci} 1778c2ecf20Sopenharmony_ci 1788c2ecf20Sopenharmony_ci/* 1798c2ecf20Sopenharmony_ci * ATAPI devices can cause the SL82C105 DMA state machine to go gaga. 1808c2ecf20Sopenharmony_ci * Winbond recommend that the DMA state machine is reset prior to 1818c2ecf20Sopenharmony_ci * setting the bus master DMA enable bit. 1828c2ecf20Sopenharmony_ci * 1838c2ecf20Sopenharmony_ci * The generic IDE core will have disabled the BMEN bit before this 1848c2ecf20Sopenharmony_ci * function is called. 1858c2ecf20Sopenharmony_ci */ 1868c2ecf20Sopenharmony_cistatic void sl82c105_dma_start(ide_drive_t *drive) 1878c2ecf20Sopenharmony_ci{ 1888c2ecf20Sopenharmony_ci ide_hwif_t *hwif = drive->hwif; 1898c2ecf20Sopenharmony_ci struct pci_dev *dev = to_pci_dev(hwif->dev); 1908c2ecf20Sopenharmony_ci int reg = 0x44 + drive->dn * 4; 1918c2ecf20Sopenharmony_ci 1928c2ecf20Sopenharmony_ci pci_write_config_word(dev, reg, 1938c2ecf20Sopenharmony_ci (unsigned long)ide_get_drivedata(drive) >> 16); 1948c2ecf20Sopenharmony_ci 1958c2ecf20Sopenharmony_ci sl82c105_reset_host(dev); 1968c2ecf20Sopenharmony_ci ide_dma_start(drive); 1978c2ecf20Sopenharmony_ci} 1988c2ecf20Sopenharmony_ci 1998c2ecf20Sopenharmony_cistatic void sl82c105_dma_clear(ide_drive_t *drive) 2008c2ecf20Sopenharmony_ci{ 2018c2ecf20Sopenharmony_ci struct pci_dev *dev = to_pci_dev(drive->hwif->dev); 2028c2ecf20Sopenharmony_ci 2038c2ecf20Sopenharmony_ci sl82c105_reset_host(dev); 2048c2ecf20Sopenharmony_ci} 2058c2ecf20Sopenharmony_ci 2068c2ecf20Sopenharmony_cistatic int sl82c105_dma_end(ide_drive_t *drive) 2078c2ecf20Sopenharmony_ci{ 2088c2ecf20Sopenharmony_ci struct pci_dev *dev = to_pci_dev(drive->hwif->dev); 2098c2ecf20Sopenharmony_ci int reg = 0x44 + drive->dn * 4; 2108c2ecf20Sopenharmony_ci int ret = ide_dma_end(drive); 2118c2ecf20Sopenharmony_ci 2128c2ecf20Sopenharmony_ci pci_write_config_word(dev, reg, 2138c2ecf20Sopenharmony_ci (unsigned long)ide_get_drivedata(drive)); 2148c2ecf20Sopenharmony_ci 2158c2ecf20Sopenharmony_ci return ret; 2168c2ecf20Sopenharmony_ci} 2178c2ecf20Sopenharmony_ci 2188c2ecf20Sopenharmony_ci/* 2198c2ecf20Sopenharmony_ci * ATA reset will clear the 16 bits mode in the control 2208c2ecf20Sopenharmony_ci * register, we need to reprogram it 2218c2ecf20Sopenharmony_ci */ 2228c2ecf20Sopenharmony_cistatic void sl82c105_resetproc(ide_drive_t *drive) 2238c2ecf20Sopenharmony_ci{ 2248c2ecf20Sopenharmony_ci struct pci_dev *dev = to_pci_dev(drive->hwif->dev); 2258c2ecf20Sopenharmony_ci u32 val; 2268c2ecf20Sopenharmony_ci 2278c2ecf20Sopenharmony_ci pci_read_config_dword(dev, 0x40, &val); 2288c2ecf20Sopenharmony_ci val |= (CTRL_P1F16 | CTRL_P0F16); 2298c2ecf20Sopenharmony_ci pci_write_config_dword(dev, 0x40, val); 2308c2ecf20Sopenharmony_ci} 2318c2ecf20Sopenharmony_ci 2328c2ecf20Sopenharmony_ci/* 2338c2ecf20Sopenharmony_ci * Return the revision of the Winbond bridge 2348c2ecf20Sopenharmony_ci * which this function is part of. 2358c2ecf20Sopenharmony_ci */ 2368c2ecf20Sopenharmony_cistatic u8 sl82c105_bridge_revision(struct pci_dev *dev) 2378c2ecf20Sopenharmony_ci{ 2388c2ecf20Sopenharmony_ci struct pci_dev *bridge; 2398c2ecf20Sopenharmony_ci 2408c2ecf20Sopenharmony_ci /* 2418c2ecf20Sopenharmony_ci * The bridge should be part of the same device, but function 0. 2428c2ecf20Sopenharmony_ci */ 2438c2ecf20Sopenharmony_ci bridge = pci_get_domain_bus_and_slot(pci_domain_nr(dev->bus), 2448c2ecf20Sopenharmony_ci dev->bus->number, 2458c2ecf20Sopenharmony_ci PCI_DEVFN(PCI_SLOT(dev->devfn), 0)); 2468c2ecf20Sopenharmony_ci if (!bridge) 2478c2ecf20Sopenharmony_ci return -1; 2488c2ecf20Sopenharmony_ci 2498c2ecf20Sopenharmony_ci /* 2508c2ecf20Sopenharmony_ci * Make sure it is a Winbond 553 and is an ISA bridge. 2518c2ecf20Sopenharmony_ci */ 2528c2ecf20Sopenharmony_ci if (bridge->vendor != PCI_VENDOR_ID_WINBOND || 2538c2ecf20Sopenharmony_ci bridge->device != PCI_DEVICE_ID_WINBOND_83C553 || 2548c2ecf20Sopenharmony_ci bridge->class >> 8 != PCI_CLASS_BRIDGE_ISA) { 2558c2ecf20Sopenharmony_ci pci_dev_put(bridge); 2568c2ecf20Sopenharmony_ci return -1; 2578c2ecf20Sopenharmony_ci } 2588c2ecf20Sopenharmony_ci /* 2598c2ecf20Sopenharmony_ci * We need to find function 0's revision, not function 1 2608c2ecf20Sopenharmony_ci */ 2618c2ecf20Sopenharmony_ci pci_dev_put(bridge); 2628c2ecf20Sopenharmony_ci 2638c2ecf20Sopenharmony_ci return bridge->revision; 2648c2ecf20Sopenharmony_ci} 2658c2ecf20Sopenharmony_ci 2668c2ecf20Sopenharmony_ci/* 2678c2ecf20Sopenharmony_ci * Enable the PCI device 2688c2ecf20Sopenharmony_ci * 2698c2ecf20Sopenharmony_ci * --BenH: It's arch fixup code that should enable channels that 2708c2ecf20Sopenharmony_ci * have not been enabled by firmware. I decided we can still enable 2718c2ecf20Sopenharmony_ci * channel 0 here at least, but channel 1 has to be enabled by 2728c2ecf20Sopenharmony_ci * firmware or arch code. We still set both to 16 bits mode. 2738c2ecf20Sopenharmony_ci */ 2748c2ecf20Sopenharmony_cistatic int init_chipset_sl82c105(struct pci_dev *dev) 2758c2ecf20Sopenharmony_ci{ 2768c2ecf20Sopenharmony_ci u32 val; 2778c2ecf20Sopenharmony_ci 2788c2ecf20Sopenharmony_ci pci_read_config_dword(dev, 0x40, &val); 2798c2ecf20Sopenharmony_ci val |= CTRL_P0EN | CTRL_P0F16 | CTRL_P1F16; 2808c2ecf20Sopenharmony_ci pci_write_config_dword(dev, 0x40, val); 2818c2ecf20Sopenharmony_ci 2828c2ecf20Sopenharmony_ci return 0; 2838c2ecf20Sopenharmony_ci} 2848c2ecf20Sopenharmony_ci 2858c2ecf20Sopenharmony_cistatic const struct ide_port_ops sl82c105_port_ops = { 2868c2ecf20Sopenharmony_ci .set_pio_mode = sl82c105_set_pio_mode, 2878c2ecf20Sopenharmony_ci .set_dma_mode = sl82c105_set_dma_mode, 2888c2ecf20Sopenharmony_ci .resetproc = sl82c105_resetproc, 2898c2ecf20Sopenharmony_ci .test_irq = sl82c105_test_irq, 2908c2ecf20Sopenharmony_ci}; 2918c2ecf20Sopenharmony_ci 2928c2ecf20Sopenharmony_cistatic const struct ide_dma_ops sl82c105_dma_ops = { 2938c2ecf20Sopenharmony_ci .dma_host_set = ide_dma_host_set, 2948c2ecf20Sopenharmony_ci .dma_setup = ide_dma_setup, 2958c2ecf20Sopenharmony_ci .dma_start = sl82c105_dma_start, 2968c2ecf20Sopenharmony_ci .dma_end = sl82c105_dma_end, 2978c2ecf20Sopenharmony_ci .dma_test_irq = ide_dma_test_irq, 2988c2ecf20Sopenharmony_ci .dma_lost_irq = sl82c105_dma_lost_irq, 2998c2ecf20Sopenharmony_ci .dma_timer_expiry = ide_dma_sff_timer_expiry, 3008c2ecf20Sopenharmony_ci .dma_clear = sl82c105_dma_clear, 3018c2ecf20Sopenharmony_ci .dma_sff_read_status = ide_dma_sff_read_status, 3028c2ecf20Sopenharmony_ci}; 3038c2ecf20Sopenharmony_ci 3048c2ecf20Sopenharmony_cistatic const struct ide_port_info sl82c105_chipset = { 3058c2ecf20Sopenharmony_ci .name = DRV_NAME, 3068c2ecf20Sopenharmony_ci .init_chipset = init_chipset_sl82c105, 3078c2ecf20Sopenharmony_ci .enablebits = {{0x40,0x01,0x01}, {0x40,0x10,0x10}}, 3088c2ecf20Sopenharmony_ci .port_ops = &sl82c105_port_ops, 3098c2ecf20Sopenharmony_ci .dma_ops = &sl82c105_dma_ops, 3108c2ecf20Sopenharmony_ci .host_flags = IDE_HFLAG_IO_32BIT | 3118c2ecf20Sopenharmony_ci IDE_HFLAG_UNMASK_IRQS | 3128c2ecf20Sopenharmony_ci IDE_HFLAG_SERIALIZE_DMA | 3138c2ecf20Sopenharmony_ci IDE_HFLAG_NO_AUTODMA, 3148c2ecf20Sopenharmony_ci .pio_mask = ATA_PIO5, 3158c2ecf20Sopenharmony_ci .mwdma_mask = ATA_MWDMA2, 3168c2ecf20Sopenharmony_ci}; 3178c2ecf20Sopenharmony_ci 3188c2ecf20Sopenharmony_cistatic int sl82c105_init_one(struct pci_dev *dev, const struct pci_device_id *id) 3198c2ecf20Sopenharmony_ci{ 3208c2ecf20Sopenharmony_ci struct ide_port_info d = sl82c105_chipset; 3218c2ecf20Sopenharmony_ci u8 rev = sl82c105_bridge_revision(dev); 3228c2ecf20Sopenharmony_ci 3238c2ecf20Sopenharmony_ci if (rev <= 5) { 3248c2ecf20Sopenharmony_ci /* 3258c2ecf20Sopenharmony_ci * Never ever EVER under any circumstances enable 3268c2ecf20Sopenharmony_ci * DMA when the bridge is this old. 3278c2ecf20Sopenharmony_ci */ 3288c2ecf20Sopenharmony_ci printk(KERN_INFO DRV_NAME ": Winbond W83C553 bridge " 3298c2ecf20Sopenharmony_ci "revision %d, BM-DMA disabled\n", rev); 3308c2ecf20Sopenharmony_ci d.dma_ops = NULL; 3318c2ecf20Sopenharmony_ci d.mwdma_mask = 0; 3328c2ecf20Sopenharmony_ci d.host_flags &= ~IDE_HFLAG_SERIALIZE_DMA; 3338c2ecf20Sopenharmony_ci } 3348c2ecf20Sopenharmony_ci 3358c2ecf20Sopenharmony_ci return ide_pci_init_one(dev, &d, NULL); 3368c2ecf20Sopenharmony_ci} 3378c2ecf20Sopenharmony_ci 3388c2ecf20Sopenharmony_cistatic const struct pci_device_id sl82c105_pci_tbl[] = { 3398c2ecf20Sopenharmony_ci { PCI_VDEVICE(WINBOND, PCI_DEVICE_ID_WINBOND_82C105), 0 }, 3408c2ecf20Sopenharmony_ci { 0, }, 3418c2ecf20Sopenharmony_ci}; 3428c2ecf20Sopenharmony_ciMODULE_DEVICE_TABLE(pci, sl82c105_pci_tbl); 3438c2ecf20Sopenharmony_ci 3448c2ecf20Sopenharmony_cistatic struct pci_driver sl82c105_pci_driver = { 3458c2ecf20Sopenharmony_ci .name = "W82C105_IDE", 3468c2ecf20Sopenharmony_ci .id_table = sl82c105_pci_tbl, 3478c2ecf20Sopenharmony_ci .probe = sl82c105_init_one, 3488c2ecf20Sopenharmony_ci .remove = ide_pci_remove, 3498c2ecf20Sopenharmony_ci .suspend = ide_pci_suspend, 3508c2ecf20Sopenharmony_ci .resume = ide_pci_resume, 3518c2ecf20Sopenharmony_ci}; 3528c2ecf20Sopenharmony_ci 3538c2ecf20Sopenharmony_cistatic int __init sl82c105_ide_init(void) 3548c2ecf20Sopenharmony_ci{ 3558c2ecf20Sopenharmony_ci return ide_pci_register_driver(&sl82c105_pci_driver); 3568c2ecf20Sopenharmony_ci} 3578c2ecf20Sopenharmony_ci 3588c2ecf20Sopenharmony_cistatic void __exit sl82c105_ide_exit(void) 3598c2ecf20Sopenharmony_ci{ 3608c2ecf20Sopenharmony_ci pci_unregister_driver(&sl82c105_pci_driver); 3618c2ecf20Sopenharmony_ci} 3628c2ecf20Sopenharmony_ci 3638c2ecf20Sopenharmony_cimodule_init(sl82c105_ide_init); 3648c2ecf20Sopenharmony_cimodule_exit(sl82c105_ide_exit); 3658c2ecf20Sopenharmony_ci 3668c2ecf20Sopenharmony_ciMODULE_DESCRIPTION("PCI driver module for W82C105 IDE"); 3678c2ecf20Sopenharmony_ciMODULE_LICENSE("GPL"); 368