18c2ecf20Sopenharmony_ci/* 28c2ecf20Sopenharmony_ci * Copyright (C) 1998-2000 Andre Hedrick <andre@linux-ide.org> 38c2ecf20Sopenharmony_ci * Copyright (C) 1995-1998 Mark Lord 48c2ecf20Sopenharmony_ci * Copyright (C) 2007-2009 Bartlomiej Zolnierkiewicz 58c2ecf20Sopenharmony_ci * 68c2ecf20Sopenharmony_ci * May be copied or modified under the terms of the GNU General Public License 78c2ecf20Sopenharmony_ci */ 88c2ecf20Sopenharmony_ci 98c2ecf20Sopenharmony_ci#include <linux/types.h> 108c2ecf20Sopenharmony_ci#include <linux/kernel.h> 118c2ecf20Sopenharmony_ci#include <linux/export.h> 128c2ecf20Sopenharmony_ci#include <linux/pci.h> 138c2ecf20Sopenharmony_ci#include <linux/init.h> 148c2ecf20Sopenharmony_ci#include <linux/interrupt.h> 158c2ecf20Sopenharmony_ci#include <linux/ide.h> 168c2ecf20Sopenharmony_ci#include <linux/dma-mapping.h> 178c2ecf20Sopenharmony_ci 188c2ecf20Sopenharmony_ci#include <asm/io.h> 198c2ecf20Sopenharmony_ci 208c2ecf20Sopenharmony_ci/** 218c2ecf20Sopenharmony_ci * ide_setup_pci_baseregs - place a PCI IDE controller native 228c2ecf20Sopenharmony_ci * @dev: PCI device of interface to switch native 238c2ecf20Sopenharmony_ci * @name: Name of interface 248c2ecf20Sopenharmony_ci * 258c2ecf20Sopenharmony_ci * We attempt to place the PCI interface into PCI native mode. If 268c2ecf20Sopenharmony_ci * we succeed the BARs are ok and the controller is in PCI mode. 278c2ecf20Sopenharmony_ci * Returns 0 on success or an errno code. 288c2ecf20Sopenharmony_ci * 298c2ecf20Sopenharmony_ci * FIXME: if we program the interface and then fail to set the BARS 308c2ecf20Sopenharmony_ci * we don't switch it back to legacy mode. Do we actually care ?? 318c2ecf20Sopenharmony_ci */ 328c2ecf20Sopenharmony_ci 338c2ecf20Sopenharmony_cistatic int ide_setup_pci_baseregs(struct pci_dev *dev, const char *name) 348c2ecf20Sopenharmony_ci{ 358c2ecf20Sopenharmony_ci u8 progif = 0; 368c2ecf20Sopenharmony_ci 378c2ecf20Sopenharmony_ci /* 388c2ecf20Sopenharmony_ci * Place both IDE interfaces into PCI "native" mode: 398c2ecf20Sopenharmony_ci */ 408c2ecf20Sopenharmony_ci if (pci_read_config_byte(dev, PCI_CLASS_PROG, &progif) || 418c2ecf20Sopenharmony_ci (progif & 5) != 5) { 428c2ecf20Sopenharmony_ci if ((progif & 0xa) != 0xa) { 438c2ecf20Sopenharmony_ci printk(KERN_INFO "%s %s: device not capable of full " 448c2ecf20Sopenharmony_ci "native PCI mode\n", name, pci_name(dev)); 458c2ecf20Sopenharmony_ci return -EOPNOTSUPP; 468c2ecf20Sopenharmony_ci } 478c2ecf20Sopenharmony_ci printk(KERN_INFO "%s %s: placing both ports into native PCI " 488c2ecf20Sopenharmony_ci "mode\n", name, pci_name(dev)); 498c2ecf20Sopenharmony_ci (void) pci_write_config_byte(dev, PCI_CLASS_PROG, progif|5); 508c2ecf20Sopenharmony_ci if (pci_read_config_byte(dev, PCI_CLASS_PROG, &progif) || 518c2ecf20Sopenharmony_ci (progif & 5) != 5) { 528c2ecf20Sopenharmony_ci printk(KERN_ERR "%s %s: rewrite of PROGIF failed, " 538c2ecf20Sopenharmony_ci "wanted 0x%04x, got 0x%04x\n", 548c2ecf20Sopenharmony_ci name, pci_name(dev), progif | 5, progif); 558c2ecf20Sopenharmony_ci return -EOPNOTSUPP; 568c2ecf20Sopenharmony_ci } 578c2ecf20Sopenharmony_ci } 588c2ecf20Sopenharmony_ci return 0; 598c2ecf20Sopenharmony_ci} 608c2ecf20Sopenharmony_ci 618c2ecf20Sopenharmony_ci#ifdef CONFIG_BLK_DEV_IDEDMA_PCI 628c2ecf20Sopenharmony_cistatic int ide_pci_clear_simplex(unsigned long dma_base, const char *name) 638c2ecf20Sopenharmony_ci{ 648c2ecf20Sopenharmony_ci u8 dma_stat = inb(dma_base + 2); 658c2ecf20Sopenharmony_ci 668c2ecf20Sopenharmony_ci outb(dma_stat & 0x60, dma_base + 2); 678c2ecf20Sopenharmony_ci dma_stat = inb(dma_base + 2); 688c2ecf20Sopenharmony_ci 698c2ecf20Sopenharmony_ci return (dma_stat & 0x80) ? 1 : 0; 708c2ecf20Sopenharmony_ci} 718c2ecf20Sopenharmony_ci 728c2ecf20Sopenharmony_ci/** 738c2ecf20Sopenharmony_ci * ide_pci_dma_base - setup BMIBA 748c2ecf20Sopenharmony_ci * @hwif: IDE interface 758c2ecf20Sopenharmony_ci * @d: IDE port info 768c2ecf20Sopenharmony_ci * 778c2ecf20Sopenharmony_ci * Fetch the DMA Bus-Master-I/O-Base-Address (BMIBA) from PCI space. 788c2ecf20Sopenharmony_ci */ 798c2ecf20Sopenharmony_ci 808c2ecf20Sopenharmony_ciunsigned long ide_pci_dma_base(ide_hwif_t *hwif, const struct ide_port_info *d) 818c2ecf20Sopenharmony_ci{ 828c2ecf20Sopenharmony_ci struct pci_dev *dev = to_pci_dev(hwif->dev); 838c2ecf20Sopenharmony_ci unsigned long dma_base = 0; 848c2ecf20Sopenharmony_ci 858c2ecf20Sopenharmony_ci if (hwif->host_flags & IDE_HFLAG_MMIO) 868c2ecf20Sopenharmony_ci return hwif->dma_base; 878c2ecf20Sopenharmony_ci 888c2ecf20Sopenharmony_ci if (hwif->mate && hwif->mate->dma_base) { 898c2ecf20Sopenharmony_ci dma_base = hwif->mate->dma_base - (hwif->channel ? 0 : 8); 908c2ecf20Sopenharmony_ci } else { 918c2ecf20Sopenharmony_ci u8 baridx = (d->host_flags & IDE_HFLAG_CS5520) ? 2 : 4; 928c2ecf20Sopenharmony_ci 938c2ecf20Sopenharmony_ci dma_base = pci_resource_start(dev, baridx); 948c2ecf20Sopenharmony_ci 958c2ecf20Sopenharmony_ci if (dma_base == 0) { 968c2ecf20Sopenharmony_ci printk(KERN_ERR "%s %s: DMA base is invalid\n", 978c2ecf20Sopenharmony_ci d->name, pci_name(dev)); 988c2ecf20Sopenharmony_ci return 0; 998c2ecf20Sopenharmony_ci } 1008c2ecf20Sopenharmony_ci } 1018c2ecf20Sopenharmony_ci 1028c2ecf20Sopenharmony_ci if (hwif->channel) 1038c2ecf20Sopenharmony_ci dma_base += 8; 1048c2ecf20Sopenharmony_ci 1058c2ecf20Sopenharmony_ci return dma_base; 1068c2ecf20Sopenharmony_ci} 1078c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(ide_pci_dma_base); 1088c2ecf20Sopenharmony_ci 1098c2ecf20Sopenharmony_ciint ide_pci_check_simplex(ide_hwif_t *hwif, const struct ide_port_info *d) 1108c2ecf20Sopenharmony_ci{ 1118c2ecf20Sopenharmony_ci struct pci_dev *dev = to_pci_dev(hwif->dev); 1128c2ecf20Sopenharmony_ci u8 dma_stat; 1138c2ecf20Sopenharmony_ci 1148c2ecf20Sopenharmony_ci if (d->host_flags & (IDE_HFLAG_MMIO | IDE_HFLAG_CS5520)) 1158c2ecf20Sopenharmony_ci goto out; 1168c2ecf20Sopenharmony_ci 1178c2ecf20Sopenharmony_ci if (d->host_flags & IDE_HFLAG_CLEAR_SIMPLEX) { 1188c2ecf20Sopenharmony_ci if (ide_pci_clear_simplex(hwif->dma_base, d->name)) 1198c2ecf20Sopenharmony_ci printk(KERN_INFO "%s %s: simplex device: DMA forced\n", 1208c2ecf20Sopenharmony_ci d->name, pci_name(dev)); 1218c2ecf20Sopenharmony_ci goto out; 1228c2ecf20Sopenharmony_ci } 1238c2ecf20Sopenharmony_ci 1248c2ecf20Sopenharmony_ci /* 1258c2ecf20Sopenharmony_ci * If the device claims "simplex" DMA, this means that only one of 1268c2ecf20Sopenharmony_ci * the two interfaces can be trusted with DMA at any point in time 1278c2ecf20Sopenharmony_ci * (so we should enable DMA only on one of the two interfaces). 1288c2ecf20Sopenharmony_ci * 1298c2ecf20Sopenharmony_ci * FIXME: At this point we haven't probed the drives so we can't make 1308c2ecf20Sopenharmony_ci * the appropriate decision. Really we should defer this problem until 1318c2ecf20Sopenharmony_ci * we tune the drive then try to grab DMA ownership if we want to be 1328c2ecf20Sopenharmony_ci * the DMA end. This has to be become dynamic to handle hot-plug. 1338c2ecf20Sopenharmony_ci */ 1348c2ecf20Sopenharmony_ci dma_stat = hwif->dma_ops->dma_sff_read_status(hwif); 1358c2ecf20Sopenharmony_ci if ((dma_stat & 0x80) && hwif->mate && hwif->mate->dma_base) { 1368c2ecf20Sopenharmony_ci printk(KERN_INFO "%s %s: simplex device: DMA disabled\n", 1378c2ecf20Sopenharmony_ci d->name, pci_name(dev)); 1388c2ecf20Sopenharmony_ci return -1; 1398c2ecf20Sopenharmony_ci } 1408c2ecf20Sopenharmony_ciout: 1418c2ecf20Sopenharmony_ci return 0; 1428c2ecf20Sopenharmony_ci} 1438c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(ide_pci_check_simplex); 1448c2ecf20Sopenharmony_ci 1458c2ecf20Sopenharmony_ci/* 1468c2ecf20Sopenharmony_ci * Set up BM-DMA capability (PnP BIOS should have done this) 1478c2ecf20Sopenharmony_ci */ 1488c2ecf20Sopenharmony_ciint ide_pci_set_master(struct pci_dev *dev, const char *name) 1498c2ecf20Sopenharmony_ci{ 1508c2ecf20Sopenharmony_ci u16 pcicmd; 1518c2ecf20Sopenharmony_ci 1528c2ecf20Sopenharmony_ci pci_read_config_word(dev, PCI_COMMAND, &pcicmd); 1538c2ecf20Sopenharmony_ci 1548c2ecf20Sopenharmony_ci if ((pcicmd & PCI_COMMAND_MASTER) == 0) { 1558c2ecf20Sopenharmony_ci pci_set_master(dev); 1568c2ecf20Sopenharmony_ci 1578c2ecf20Sopenharmony_ci if (pci_read_config_word(dev, PCI_COMMAND, &pcicmd) || 1588c2ecf20Sopenharmony_ci (pcicmd & PCI_COMMAND_MASTER) == 0) { 1598c2ecf20Sopenharmony_ci printk(KERN_ERR "%s %s: error updating PCICMD\n", 1608c2ecf20Sopenharmony_ci name, pci_name(dev)); 1618c2ecf20Sopenharmony_ci return -EIO; 1628c2ecf20Sopenharmony_ci } 1638c2ecf20Sopenharmony_ci } 1648c2ecf20Sopenharmony_ci 1658c2ecf20Sopenharmony_ci return 0; 1668c2ecf20Sopenharmony_ci} 1678c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(ide_pci_set_master); 1688c2ecf20Sopenharmony_ci#endif /* CONFIG_BLK_DEV_IDEDMA_PCI */ 1698c2ecf20Sopenharmony_ci 1708c2ecf20Sopenharmony_civoid ide_setup_pci_noise(struct pci_dev *dev, const struct ide_port_info *d) 1718c2ecf20Sopenharmony_ci{ 1728c2ecf20Sopenharmony_ci printk(KERN_INFO "%s %s: IDE controller (0x%04x:0x%04x rev 0x%02x)\n", 1738c2ecf20Sopenharmony_ci d->name, pci_name(dev), 1748c2ecf20Sopenharmony_ci dev->vendor, dev->device, dev->revision); 1758c2ecf20Sopenharmony_ci} 1768c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(ide_setup_pci_noise); 1778c2ecf20Sopenharmony_ci 1788c2ecf20Sopenharmony_ci 1798c2ecf20Sopenharmony_ci/** 1808c2ecf20Sopenharmony_ci * ide_pci_enable - do PCI enables 1818c2ecf20Sopenharmony_ci * @dev: PCI device 1828c2ecf20Sopenharmony_ci * @bars: PCI BARs mask 1838c2ecf20Sopenharmony_ci * @d: IDE port info 1848c2ecf20Sopenharmony_ci * 1858c2ecf20Sopenharmony_ci * Enable the IDE PCI device. We attempt to enable the device in full 1868c2ecf20Sopenharmony_ci * but if that fails then we only need IO space. The PCI code should 1878c2ecf20Sopenharmony_ci * have setup the proper resources for us already for controllers in 1888c2ecf20Sopenharmony_ci * legacy mode. 1898c2ecf20Sopenharmony_ci * 1908c2ecf20Sopenharmony_ci * Returns zero on success or an error code 1918c2ecf20Sopenharmony_ci */ 1928c2ecf20Sopenharmony_ci 1938c2ecf20Sopenharmony_cistatic int ide_pci_enable(struct pci_dev *dev, int bars, 1948c2ecf20Sopenharmony_ci const struct ide_port_info *d) 1958c2ecf20Sopenharmony_ci{ 1968c2ecf20Sopenharmony_ci int ret; 1978c2ecf20Sopenharmony_ci 1988c2ecf20Sopenharmony_ci if (pci_enable_device(dev)) { 1998c2ecf20Sopenharmony_ci ret = pci_enable_device_io(dev); 2008c2ecf20Sopenharmony_ci if (ret < 0) { 2018c2ecf20Sopenharmony_ci printk(KERN_WARNING "%s %s: couldn't enable device\n", 2028c2ecf20Sopenharmony_ci d->name, pci_name(dev)); 2038c2ecf20Sopenharmony_ci goto out; 2048c2ecf20Sopenharmony_ci } 2058c2ecf20Sopenharmony_ci printk(KERN_WARNING "%s %s: BIOS configuration fixed\n", 2068c2ecf20Sopenharmony_ci d->name, pci_name(dev)); 2078c2ecf20Sopenharmony_ci } 2088c2ecf20Sopenharmony_ci 2098c2ecf20Sopenharmony_ci /* 2108c2ecf20Sopenharmony_ci * assume all devices can do 32-bit DMA for now, we can add 2118c2ecf20Sopenharmony_ci * a DMA mask field to the struct ide_port_info if we need it 2128c2ecf20Sopenharmony_ci * (or let lower level driver set the DMA mask) 2138c2ecf20Sopenharmony_ci */ 2148c2ecf20Sopenharmony_ci ret = dma_set_mask(&dev->dev, DMA_BIT_MASK(32)); 2158c2ecf20Sopenharmony_ci if (ret < 0) { 2168c2ecf20Sopenharmony_ci printk(KERN_ERR "%s %s: can't set DMA mask\n", 2178c2ecf20Sopenharmony_ci d->name, pci_name(dev)); 2188c2ecf20Sopenharmony_ci goto out; 2198c2ecf20Sopenharmony_ci } 2208c2ecf20Sopenharmony_ci 2218c2ecf20Sopenharmony_ci ret = pci_request_selected_regions(dev, bars, d->name); 2228c2ecf20Sopenharmony_ci if (ret < 0) 2238c2ecf20Sopenharmony_ci printk(KERN_ERR "%s %s: can't reserve resources\n", 2248c2ecf20Sopenharmony_ci d->name, pci_name(dev)); 2258c2ecf20Sopenharmony_ciout: 2268c2ecf20Sopenharmony_ci return ret; 2278c2ecf20Sopenharmony_ci} 2288c2ecf20Sopenharmony_ci 2298c2ecf20Sopenharmony_ci/** 2308c2ecf20Sopenharmony_ci * ide_pci_configure - configure an unconfigured device 2318c2ecf20Sopenharmony_ci * @dev: PCI device 2328c2ecf20Sopenharmony_ci * @d: IDE port info 2338c2ecf20Sopenharmony_ci * 2348c2ecf20Sopenharmony_ci * Enable and configure the PCI device we have been passed. 2358c2ecf20Sopenharmony_ci * Returns zero on success or an error code. 2368c2ecf20Sopenharmony_ci */ 2378c2ecf20Sopenharmony_ci 2388c2ecf20Sopenharmony_cistatic int ide_pci_configure(struct pci_dev *dev, const struct ide_port_info *d) 2398c2ecf20Sopenharmony_ci{ 2408c2ecf20Sopenharmony_ci u16 pcicmd = 0; 2418c2ecf20Sopenharmony_ci /* 2428c2ecf20Sopenharmony_ci * PnP BIOS was *supposed* to have setup this device, but we 2438c2ecf20Sopenharmony_ci * can do it ourselves, so long as the BIOS has assigned an IRQ 2448c2ecf20Sopenharmony_ci * (or possibly the device is using a "legacy header" for IRQs). 2458c2ecf20Sopenharmony_ci * Maybe the user deliberately *disabled* the device, 2468c2ecf20Sopenharmony_ci * but we'll eventually ignore it again if no drives respond. 2478c2ecf20Sopenharmony_ci */ 2488c2ecf20Sopenharmony_ci if (ide_setup_pci_baseregs(dev, d->name) || 2498c2ecf20Sopenharmony_ci pci_write_config_word(dev, PCI_COMMAND, pcicmd | PCI_COMMAND_IO)) { 2508c2ecf20Sopenharmony_ci printk(KERN_INFO "%s %s: device disabled (BIOS)\n", 2518c2ecf20Sopenharmony_ci d->name, pci_name(dev)); 2528c2ecf20Sopenharmony_ci return -ENODEV; 2538c2ecf20Sopenharmony_ci } 2548c2ecf20Sopenharmony_ci if (pci_read_config_word(dev, PCI_COMMAND, &pcicmd)) { 2558c2ecf20Sopenharmony_ci printk(KERN_ERR "%s %s: error accessing PCI regs\n", 2568c2ecf20Sopenharmony_ci d->name, pci_name(dev)); 2578c2ecf20Sopenharmony_ci return -EIO; 2588c2ecf20Sopenharmony_ci } 2598c2ecf20Sopenharmony_ci if (!(pcicmd & PCI_COMMAND_IO)) { 2608c2ecf20Sopenharmony_ci printk(KERN_ERR "%s %s: unable to enable IDE controller\n", 2618c2ecf20Sopenharmony_ci d->name, pci_name(dev)); 2628c2ecf20Sopenharmony_ci return -ENXIO; 2638c2ecf20Sopenharmony_ci } 2648c2ecf20Sopenharmony_ci return 0; 2658c2ecf20Sopenharmony_ci} 2668c2ecf20Sopenharmony_ci 2678c2ecf20Sopenharmony_ci/** 2688c2ecf20Sopenharmony_ci * ide_pci_check_iomem - check a register is I/O 2698c2ecf20Sopenharmony_ci * @dev: PCI device 2708c2ecf20Sopenharmony_ci * @d: IDE port info 2718c2ecf20Sopenharmony_ci * @bar: BAR number 2728c2ecf20Sopenharmony_ci * 2738c2ecf20Sopenharmony_ci * Checks if a BAR is configured and points to MMIO space. If so, 2748c2ecf20Sopenharmony_ci * return an error code. Otherwise return 0 2758c2ecf20Sopenharmony_ci */ 2768c2ecf20Sopenharmony_ci 2778c2ecf20Sopenharmony_cistatic int ide_pci_check_iomem(struct pci_dev *dev, const struct ide_port_info *d, 2788c2ecf20Sopenharmony_ci int bar) 2798c2ecf20Sopenharmony_ci{ 2808c2ecf20Sopenharmony_ci ulong flags = pci_resource_flags(dev, bar); 2818c2ecf20Sopenharmony_ci 2828c2ecf20Sopenharmony_ci /* Unconfigured ? */ 2838c2ecf20Sopenharmony_ci if (!flags || pci_resource_len(dev, bar) == 0) 2848c2ecf20Sopenharmony_ci return 0; 2858c2ecf20Sopenharmony_ci 2868c2ecf20Sopenharmony_ci /* I/O space */ 2878c2ecf20Sopenharmony_ci if (flags & IORESOURCE_IO) 2888c2ecf20Sopenharmony_ci return 0; 2898c2ecf20Sopenharmony_ci 2908c2ecf20Sopenharmony_ci /* Bad */ 2918c2ecf20Sopenharmony_ci return -EINVAL; 2928c2ecf20Sopenharmony_ci} 2938c2ecf20Sopenharmony_ci 2948c2ecf20Sopenharmony_ci/** 2958c2ecf20Sopenharmony_ci * ide_hw_configure - configure a struct ide_hw instance 2968c2ecf20Sopenharmony_ci * @dev: PCI device holding interface 2978c2ecf20Sopenharmony_ci * @d: IDE port info 2988c2ecf20Sopenharmony_ci * @port: port number 2998c2ecf20Sopenharmony_ci * @hw: struct ide_hw instance corresponding to this port 3008c2ecf20Sopenharmony_ci * 3018c2ecf20Sopenharmony_ci * Perform the initial set up for the hardware interface structure. This 3028c2ecf20Sopenharmony_ci * is done per interface port rather than per PCI device. There may be 3038c2ecf20Sopenharmony_ci * more than one port per device. 3048c2ecf20Sopenharmony_ci * 3058c2ecf20Sopenharmony_ci * Returns zero on success or an error code. 3068c2ecf20Sopenharmony_ci */ 3078c2ecf20Sopenharmony_ci 3088c2ecf20Sopenharmony_cistatic int ide_hw_configure(struct pci_dev *dev, const struct ide_port_info *d, 3098c2ecf20Sopenharmony_ci unsigned int port, struct ide_hw *hw) 3108c2ecf20Sopenharmony_ci{ 3118c2ecf20Sopenharmony_ci unsigned long ctl = 0, base = 0; 3128c2ecf20Sopenharmony_ci 3138c2ecf20Sopenharmony_ci if ((d->host_flags & IDE_HFLAG_ISA_PORTS) == 0) { 3148c2ecf20Sopenharmony_ci if (ide_pci_check_iomem(dev, d, 2 * port) || 3158c2ecf20Sopenharmony_ci ide_pci_check_iomem(dev, d, 2 * port + 1)) { 3168c2ecf20Sopenharmony_ci printk(KERN_ERR "%s %s: I/O baseregs (BIOS) are " 3178c2ecf20Sopenharmony_ci "reported as MEM for port %d!\n", 3188c2ecf20Sopenharmony_ci d->name, pci_name(dev), port); 3198c2ecf20Sopenharmony_ci return -EINVAL; 3208c2ecf20Sopenharmony_ci } 3218c2ecf20Sopenharmony_ci 3228c2ecf20Sopenharmony_ci ctl = pci_resource_start(dev, 2*port+1); 3238c2ecf20Sopenharmony_ci base = pci_resource_start(dev, 2*port); 3248c2ecf20Sopenharmony_ci } else { 3258c2ecf20Sopenharmony_ci /* Use default values */ 3268c2ecf20Sopenharmony_ci ctl = port ? 0x374 : 0x3f4; 3278c2ecf20Sopenharmony_ci base = port ? 0x170 : 0x1f0; 3288c2ecf20Sopenharmony_ci } 3298c2ecf20Sopenharmony_ci 3308c2ecf20Sopenharmony_ci if (!base || !ctl) { 3318c2ecf20Sopenharmony_ci printk(KERN_ERR "%s %s: bad PCI BARs for port %d, skipping\n", 3328c2ecf20Sopenharmony_ci d->name, pci_name(dev), port); 3338c2ecf20Sopenharmony_ci return -EINVAL; 3348c2ecf20Sopenharmony_ci } 3358c2ecf20Sopenharmony_ci 3368c2ecf20Sopenharmony_ci memset(hw, 0, sizeof(*hw)); 3378c2ecf20Sopenharmony_ci hw->dev = &dev->dev; 3388c2ecf20Sopenharmony_ci ide_std_init_ports(hw, base, ctl | 2); 3398c2ecf20Sopenharmony_ci 3408c2ecf20Sopenharmony_ci return 0; 3418c2ecf20Sopenharmony_ci} 3428c2ecf20Sopenharmony_ci 3438c2ecf20Sopenharmony_ci#ifdef CONFIG_BLK_DEV_IDEDMA_PCI 3448c2ecf20Sopenharmony_ci/** 3458c2ecf20Sopenharmony_ci * ide_hwif_setup_dma - configure DMA interface 3468c2ecf20Sopenharmony_ci * @hwif: IDE interface 3478c2ecf20Sopenharmony_ci * @d: IDE port info 3488c2ecf20Sopenharmony_ci * 3498c2ecf20Sopenharmony_ci * Set up the DMA base for the interface. Enable the master bits as 3508c2ecf20Sopenharmony_ci * necessary and attempt to bring the device DMA into a ready to use 3518c2ecf20Sopenharmony_ci * state 3528c2ecf20Sopenharmony_ci */ 3538c2ecf20Sopenharmony_ci 3548c2ecf20Sopenharmony_ciint ide_hwif_setup_dma(ide_hwif_t *hwif, const struct ide_port_info *d) 3558c2ecf20Sopenharmony_ci{ 3568c2ecf20Sopenharmony_ci struct pci_dev *dev = to_pci_dev(hwif->dev); 3578c2ecf20Sopenharmony_ci 3588c2ecf20Sopenharmony_ci if ((d->host_flags & IDE_HFLAG_NO_AUTODMA) == 0 || 3598c2ecf20Sopenharmony_ci ((dev->class >> 8) == PCI_CLASS_STORAGE_IDE && 3608c2ecf20Sopenharmony_ci (dev->class & 0x80))) { 3618c2ecf20Sopenharmony_ci unsigned long base = ide_pci_dma_base(hwif, d); 3628c2ecf20Sopenharmony_ci 3638c2ecf20Sopenharmony_ci if (base == 0) 3648c2ecf20Sopenharmony_ci return -1; 3658c2ecf20Sopenharmony_ci 3668c2ecf20Sopenharmony_ci hwif->dma_base = base; 3678c2ecf20Sopenharmony_ci 3688c2ecf20Sopenharmony_ci if (hwif->dma_ops == NULL) 3698c2ecf20Sopenharmony_ci hwif->dma_ops = &sff_dma_ops; 3708c2ecf20Sopenharmony_ci 3718c2ecf20Sopenharmony_ci if (ide_pci_check_simplex(hwif, d) < 0) 3728c2ecf20Sopenharmony_ci return -1; 3738c2ecf20Sopenharmony_ci 3748c2ecf20Sopenharmony_ci if (ide_pci_set_master(dev, d->name) < 0) 3758c2ecf20Sopenharmony_ci return -1; 3768c2ecf20Sopenharmony_ci 3778c2ecf20Sopenharmony_ci if (hwif->host_flags & IDE_HFLAG_MMIO) 3788c2ecf20Sopenharmony_ci printk(KERN_INFO " %s: MMIO-DMA\n", hwif->name); 3798c2ecf20Sopenharmony_ci else 3808c2ecf20Sopenharmony_ci printk(KERN_INFO " %s: BM-DMA at 0x%04lx-0x%04lx\n", 3818c2ecf20Sopenharmony_ci hwif->name, base, base + 7); 3828c2ecf20Sopenharmony_ci 3838c2ecf20Sopenharmony_ci hwif->extra_base = base + (hwif->channel ? 8 : 16); 3848c2ecf20Sopenharmony_ci 3858c2ecf20Sopenharmony_ci if (ide_allocate_dma_engine(hwif)) 3868c2ecf20Sopenharmony_ci return -1; 3878c2ecf20Sopenharmony_ci } 3888c2ecf20Sopenharmony_ci 3898c2ecf20Sopenharmony_ci return 0; 3908c2ecf20Sopenharmony_ci} 3918c2ecf20Sopenharmony_ci#endif /* CONFIG_BLK_DEV_IDEDMA_PCI */ 3928c2ecf20Sopenharmony_ci 3938c2ecf20Sopenharmony_ci/** 3948c2ecf20Sopenharmony_ci * ide_setup_pci_controller - set up IDE PCI 3958c2ecf20Sopenharmony_ci * @dev: PCI device 3968c2ecf20Sopenharmony_ci * @bars: PCI BARs mask 3978c2ecf20Sopenharmony_ci * @d: IDE port info 3988c2ecf20Sopenharmony_ci * @noisy: verbose flag 3998c2ecf20Sopenharmony_ci * 4008c2ecf20Sopenharmony_ci * Set up the PCI and controller side of the IDE interface. This brings 4018c2ecf20Sopenharmony_ci * up the PCI side of the device, checks that the device is enabled 4028c2ecf20Sopenharmony_ci * and enables it if need be 4038c2ecf20Sopenharmony_ci */ 4048c2ecf20Sopenharmony_ci 4058c2ecf20Sopenharmony_cistatic int ide_setup_pci_controller(struct pci_dev *dev, int bars, 4068c2ecf20Sopenharmony_ci const struct ide_port_info *d, int noisy) 4078c2ecf20Sopenharmony_ci{ 4088c2ecf20Sopenharmony_ci int ret; 4098c2ecf20Sopenharmony_ci u16 pcicmd; 4108c2ecf20Sopenharmony_ci 4118c2ecf20Sopenharmony_ci if (noisy) 4128c2ecf20Sopenharmony_ci ide_setup_pci_noise(dev, d); 4138c2ecf20Sopenharmony_ci 4148c2ecf20Sopenharmony_ci ret = ide_pci_enable(dev, bars, d); 4158c2ecf20Sopenharmony_ci if (ret < 0) 4168c2ecf20Sopenharmony_ci goto out; 4178c2ecf20Sopenharmony_ci 4188c2ecf20Sopenharmony_ci ret = pci_read_config_word(dev, PCI_COMMAND, &pcicmd); 4198c2ecf20Sopenharmony_ci if (ret < 0) { 4208c2ecf20Sopenharmony_ci printk(KERN_ERR "%s %s: error accessing PCI regs\n", 4218c2ecf20Sopenharmony_ci d->name, pci_name(dev)); 4228c2ecf20Sopenharmony_ci goto out_free_bars; 4238c2ecf20Sopenharmony_ci } 4248c2ecf20Sopenharmony_ci if (!(pcicmd & PCI_COMMAND_IO)) { /* is device disabled? */ 4258c2ecf20Sopenharmony_ci ret = ide_pci_configure(dev, d); 4268c2ecf20Sopenharmony_ci if (ret < 0) 4278c2ecf20Sopenharmony_ci goto out_free_bars; 4288c2ecf20Sopenharmony_ci printk(KERN_INFO "%s %s: device enabled (Linux)\n", 4298c2ecf20Sopenharmony_ci d->name, pci_name(dev)); 4308c2ecf20Sopenharmony_ci } 4318c2ecf20Sopenharmony_ci 4328c2ecf20Sopenharmony_ci goto out; 4338c2ecf20Sopenharmony_ci 4348c2ecf20Sopenharmony_ciout_free_bars: 4358c2ecf20Sopenharmony_ci pci_release_selected_regions(dev, bars); 4368c2ecf20Sopenharmony_ciout: 4378c2ecf20Sopenharmony_ci return ret; 4388c2ecf20Sopenharmony_ci} 4398c2ecf20Sopenharmony_ci 4408c2ecf20Sopenharmony_ci/** 4418c2ecf20Sopenharmony_ci * ide_pci_setup_ports - configure ports/devices on PCI IDE 4428c2ecf20Sopenharmony_ci * @dev: PCI device 4438c2ecf20Sopenharmony_ci * @d: IDE port info 4448c2ecf20Sopenharmony_ci * @hw: struct ide_hw instances corresponding to this PCI IDE device 4458c2ecf20Sopenharmony_ci * @hws: struct ide_hw pointers table to update 4468c2ecf20Sopenharmony_ci * 4478c2ecf20Sopenharmony_ci * Scan the interfaces attached to this device and do any 4488c2ecf20Sopenharmony_ci * necessary per port setup. Attach the devices and ask the 4498c2ecf20Sopenharmony_ci * generic DMA layer to do its work for us. 4508c2ecf20Sopenharmony_ci * 4518c2ecf20Sopenharmony_ci * Normally called automaticall from do_ide_pci_setup_device, 4528c2ecf20Sopenharmony_ci * but is also used directly as a helper function by some controllers 4538c2ecf20Sopenharmony_ci * where the chipset setup is not the default PCI IDE one. 4548c2ecf20Sopenharmony_ci */ 4558c2ecf20Sopenharmony_ci 4568c2ecf20Sopenharmony_civoid ide_pci_setup_ports(struct pci_dev *dev, const struct ide_port_info *d, 4578c2ecf20Sopenharmony_ci struct ide_hw *hw, struct ide_hw **hws) 4588c2ecf20Sopenharmony_ci{ 4598c2ecf20Sopenharmony_ci int channels = (d->host_flags & IDE_HFLAG_SINGLE) ? 1 : 2, port; 4608c2ecf20Sopenharmony_ci u8 tmp; 4618c2ecf20Sopenharmony_ci 4628c2ecf20Sopenharmony_ci /* 4638c2ecf20Sopenharmony_ci * Set up the IDE ports 4648c2ecf20Sopenharmony_ci */ 4658c2ecf20Sopenharmony_ci 4668c2ecf20Sopenharmony_ci for (port = 0; port < channels; ++port) { 4678c2ecf20Sopenharmony_ci const struct ide_pci_enablebit *e = &d->enablebits[port]; 4688c2ecf20Sopenharmony_ci 4698c2ecf20Sopenharmony_ci if (e->reg && (pci_read_config_byte(dev, e->reg, &tmp) || 4708c2ecf20Sopenharmony_ci (tmp & e->mask) != e->val)) { 4718c2ecf20Sopenharmony_ci printk(KERN_INFO "%s %s: IDE port disabled\n", 4728c2ecf20Sopenharmony_ci d->name, pci_name(dev)); 4738c2ecf20Sopenharmony_ci continue; /* port not enabled */ 4748c2ecf20Sopenharmony_ci } 4758c2ecf20Sopenharmony_ci 4768c2ecf20Sopenharmony_ci if (ide_hw_configure(dev, d, port, hw + port)) 4778c2ecf20Sopenharmony_ci continue; 4788c2ecf20Sopenharmony_ci 4798c2ecf20Sopenharmony_ci *(hws + port) = hw + port; 4808c2ecf20Sopenharmony_ci } 4818c2ecf20Sopenharmony_ci} 4828c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(ide_pci_setup_ports); 4838c2ecf20Sopenharmony_ci 4848c2ecf20Sopenharmony_ci/* 4858c2ecf20Sopenharmony_ci * ide_setup_pci_device() looks at the primary/secondary interfaces 4868c2ecf20Sopenharmony_ci * on a PCI IDE device and, if they are enabled, prepares the IDE driver 4878c2ecf20Sopenharmony_ci * for use with them. This generic code works for most PCI chipsets. 4888c2ecf20Sopenharmony_ci * 4898c2ecf20Sopenharmony_ci * One thing that is not standardized is the location of the 4908c2ecf20Sopenharmony_ci * primary/secondary interface "enable/disable" bits. For chipsets that 4918c2ecf20Sopenharmony_ci * we "know" about, this information is in the struct ide_port_info; 4928c2ecf20Sopenharmony_ci * for all other chipsets, we just assume both interfaces are enabled. 4938c2ecf20Sopenharmony_ci */ 4948c2ecf20Sopenharmony_cistatic int do_ide_setup_pci_device(struct pci_dev *dev, 4958c2ecf20Sopenharmony_ci const struct ide_port_info *d, 4968c2ecf20Sopenharmony_ci u8 noisy) 4978c2ecf20Sopenharmony_ci{ 4988c2ecf20Sopenharmony_ci int pciirq, ret; 4998c2ecf20Sopenharmony_ci 5008c2ecf20Sopenharmony_ci /* 5018c2ecf20Sopenharmony_ci * Can we trust the reported IRQ? 5028c2ecf20Sopenharmony_ci */ 5038c2ecf20Sopenharmony_ci pciirq = dev->irq; 5048c2ecf20Sopenharmony_ci 5058c2ecf20Sopenharmony_ci /* 5068c2ecf20Sopenharmony_ci * This allows offboard ide-pci cards the enable a BIOS, 5078c2ecf20Sopenharmony_ci * verify interrupt settings of split-mirror pci-config 5088c2ecf20Sopenharmony_ci * space, place chipset into init-mode, and/or preserve 5098c2ecf20Sopenharmony_ci * an interrupt if the card is not native ide support. 5108c2ecf20Sopenharmony_ci */ 5118c2ecf20Sopenharmony_ci ret = d->init_chipset ? d->init_chipset(dev) : 0; 5128c2ecf20Sopenharmony_ci if (ret < 0) 5138c2ecf20Sopenharmony_ci goto out; 5148c2ecf20Sopenharmony_ci 5158c2ecf20Sopenharmony_ci if (ide_pci_is_in_compatibility_mode(dev)) { 5168c2ecf20Sopenharmony_ci if (noisy) 5178c2ecf20Sopenharmony_ci printk(KERN_INFO "%s %s: not 100%% native mode: will " 5188c2ecf20Sopenharmony_ci "probe irqs later\n", d->name, pci_name(dev)); 5198c2ecf20Sopenharmony_ci pciirq = 0; 5208c2ecf20Sopenharmony_ci } else if (!pciirq && noisy) { 5218c2ecf20Sopenharmony_ci printk(KERN_WARNING "%s %s: bad irq (%d): will probe later\n", 5228c2ecf20Sopenharmony_ci d->name, pci_name(dev), pciirq); 5238c2ecf20Sopenharmony_ci } else if (noisy) { 5248c2ecf20Sopenharmony_ci printk(KERN_INFO "%s %s: 100%% native mode on irq %d\n", 5258c2ecf20Sopenharmony_ci d->name, pci_name(dev), pciirq); 5268c2ecf20Sopenharmony_ci } 5278c2ecf20Sopenharmony_ci 5288c2ecf20Sopenharmony_ci ret = pciirq; 5298c2ecf20Sopenharmony_ciout: 5308c2ecf20Sopenharmony_ci return ret; 5318c2ecf20Sopenharmony_ci} 5328c2ecf20Sopenharmony_ci 5338c2ecf20Sopenharmony_ciint ide_pci_init_two(struct pci_dev *dev1, struct pci_dev *dev2, 5348c2ecf20Sopenharmony_ci const struct ide_port_info *d, void *priv) 5358c2ecf20Sopenharmony_ci{ 5368c2ecf20Sopenharmony_ci struct pci_dev *pdev[] = { dev1, dev2 }; 5378c2ecf20Sopenharmony_ci struct ide_host *host; 5388c2ecf20Sopenharmony_ci int ret, i, n_ports = dev2 ? 4 : 2, bars; 5398c2ecf20Sopenharmony_ci struct ide_hw hw[4], *hws[] = { NULL, NULL, NULL, NULL }; 5408c2ecf20Sopenharmony_ci 5418c2ecf20Sopenharmony_ci if (d->host_flags & IDE_HFLAG_SINGLE) 5428c2ecf20Sopenharmony_ci bars = (1 << 2) - 1; 5438c2ecf20Sopenharmony_ci else 5448c2ecf20Sopenharmony_ci bars = (1 << 4) - 1; 5458c2ecf20Sopenharmony_ci 5468c2ecf20Sopenharmony_ci if ((d->host_flags & IDE_HFLAG_NO_DMA) == 0) { 5478c2ecf20Sopenharmony_ci if (d->host_flags & IDE_HFLAG_CS5520) 5488c2ecf20Sopenharmony_ci bars |= (1 << 2); 5498c2ecf20Sopenharmony_ci else 5508c2ecf20Sopenharmony_ci bars |= (1 << 4); 5518c2ecf20Sopenharmony_ci } 5528c2ecf20Sopenharmony_ci 5538c2ecf20Sopenharmony_ci for (i = 0; i < n_ports / 2; i++) { 5548c2ecf20Sopenharmony_ci ret = ide_setup_pci_controller(pdev[i], bars, d, !i); 5558c2ecf20Sopenharmony_ci if (ret < 0) { 5568c2ecf20Sopenharmony_ci if (i == 1) 5578c2ecf20Sopenharmony_ci pci_release_selected_regions(pdev[0], bars); 5588c2ecf20Sopenharmony_ci goto out; 5598c2ecf20Sopenharmony_ci } 5608c2ecf20Sopenharmony_ci 5618c2ecf20Sopenharmony_ci ide_pci_setup_ports(pdev[i], d, &hw[i*2], &hws[i*2]); 5628c2ecf20Sopenharmony_ci } 5638c2ecf20Sopenharmony_ci 5648c2ecf20Sopenharmony_ci host = ide_host_alloc(d, hws, n_ports); 5658c2ecf20Sopenharmony_ci if (host == NULL) { 5668c2ecf20Sopenharmony_ci ret = -ENOMEM; 5678c2ecf20Sopenharmony_ci goto out_free_bars; 5688c2ecf20Sopenharmony_ci } 5698c2ecf20Sopenharmony_ci 5708c2ecf20Sopenharmony_ci host->dev[0] = &dev1->dev; 5718c2ecf20Sopenharmony_ci if (dev2) 5728c2ecf20Sopenharmony_ci host->dev[1] = &dev2->dev; 5738c2ecf20Sopenharmony_ci 5748c2ecf20Sopenharmony_ci host->host_priv = priv; 5758c2ecf20Sopenharmony_ci host->irq_flags = IRQF_SHARED; 5768c2ecf20Sopenharmony_ci 5778c2ecf20Sopenharmony_ci pci_set_drvdata(pdev[0], host); 5788c2ecf20Sopenharmony_ci if (dev2) 5798c2ecf20Sopenharmony_ci pci_set_drvdata(pdev[1], host); 5808c2ecf20Sopenharmony_ci 5818c2ecf20Sopenharmony_ci for (i = 0; i < n_ports / 2; i++) { 5828c2ecf20Sopenharmony_ci ret = do_ide_setup_pci_device(pdev[i], d, !i); 5838c2ecf20Sopenharmony_ci 5848c2ecf20Sopenharmony_ci /* 5858c2ecf20Sopenharmony_ci * FIXME: Mom, mom, they stole me the helper function to undo 5868c2ecf20Sopenharmony_ci * do_ide_setup_pci_device() on the first device! 5878c2ecf20Sopenharmony_ci */ 5888c2ecf20Sopenharmony_ci if (ret < 0) 5898c2ecf20Sopenharmony_ci goto out_free_bars; 5908c2ecf20Sopenharmony_ci 5918c2ecf20Sopenharmony_ci /* fixup IRQ */ 5928c2ecf20Sopenharmony_ci if (ide_pci_is_in_compatibility_mode(pdev[i])) { 5938c2ecf20Sopenharmony_ci hw[i*2].irq = pci_get_legacy_ide_irq(pdev[i], 0); 5948c2ecf20Sopenharmony_ci hw[i*2 + 1].irq = pci_get_legacy_ide_irq(pdev[i], 1); 5958c2ecf20Sopenharmony_ci } else 5968c2ecf20Sopenharmony_ci hw[i*2 + 1].irq = hw[i*2].irq = ret; 5978c2ecf20Sopenharmony_ci } 5988c2ecf20Sopenharmony_ci 5998c2ecf20Sopenharmony_ci ret = ide_host_register(host, d, hws); 6008c2ecf20Sopenharmony_ci if (ret) 6018c2ecf20Sopenharmony_ci ide_host_free(host); 6028c2ecf20Sopenharmony_ci else 6038c2ecf20Sopenharmony_ci goto out; 6048c2ecf20Sopenharmony_ci 6058c2ecf20Sopenharmony_ciout_free_bars: 6068c2ecf20Sopenharmony_ci i = n_ports / 2; 6078c2ecf20Sopenharmony_ci while (i--) 6088c2ecf20Sopenharmony_ci pci_release_selected_regions(pdev[i], bars); 6098c2ecf20Sopenharmony_ciout: 6108c2ecf20Sopenharmony_ci return ret; 6118c2ecf20Sopenharmony_ci} 6128c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(ide_pci_init_two); 6138c2ecf20Sopenharmony_ci 6148c2ecf20Sopenharmony_ciint ide_pci_init_one(struct pci_dev *dev, const struct ide_port_info *d, 6158c2ecf20Sopenharmony_ci void *priv) 6168c2ecf20Sopenharmony_ci{ 6178c2ecf20Sopenharmony_ci return ide_pci_init_two(dev, NULL, d, priv); 6188c2ecf20Sopenharmony_ci} 6198c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(ide_pci_init_one); 6208c2ecf20Sopenharmony_ci 6218c2ecf20Sopenharmony_civoid ide_pci_remove(struct pci_dev *dev) 6228c2ecf20Sopenharmony_ci{ 6238c2ecf20Sopenharmony_ci struct ide_host *host = pci_get_drvdata(dev); 6248c2ecf20Sopenharmony_ci struct pci_dev *dev2 = host->dev[1] ? to_pci_dev(host->dev[1]) : NULL; 6258c2ecf20Sopenharmony_ci int bars; 6268c2ecf20Sopenharmony_ci 6278c2ecf20Sopenharmony_ci if (host->host_flags & IDE_HFLAG_SINGLE) 6288c2ecf20Sopenharmony_ci bars = (1 << 2) - 1; 6298c2ecf20Sopenharmony_ci else 6308c2ecf20Sopenharmony_ci bars = (1 << 4) - 1; 6318c2ecf20Sopenharmony_ci 6328c2ecf20Sopenharmony_ci if ((host->host_flags & IDE_HFLAG_NO_DMA) == 0) { 6338c2ecf20Sopenharmony_ci if (host->host_flags & IDE_HFLAG_CS5520) 6348c2ecf20Sopenharmony_ci bars |= (1 << 2); 6358c2ecf20Sopenharmony_ci else 6368c2ecf20Sopenharmony_ci bars |= (1 << 4); 6378c2ecf20Sopenharmony_ci } 6388c2ecf20Sopenharmony_ci 6398c2ecf20Sopenharmony_ci ide_host_remove(host); 6408c2ecf20Sopenharmony_ci 6418c2ecf20Sopenharmony_ci if (dev2) 6428c2ecf20Sopenharmony_ci pci_release_selected_regions(dev2, bars); 6438c2ecf20Sopenharmony_ci pci_release_selected_regions(dev, bars); 6448c2ecf20Sopenharmony_ci 6458c2ecf20Sopenharmony_ci if (dev2) 6468c2ecf20Sopenharmony_ci pci_disable_device(dev2); 6478c2ecf20Sopenharmony_ci pci_disable_device(dev); 6488c2ecf20Sopenharmony_ci} 6498c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(ide_pci_remove); 6508c2ecf20Sopenharmony_ci 6518c2ecf20Sopenharmony_ci#ifdef CONFIG_PM 6528c2ecf20Sopenharmony_ciint ide_pci_suspend(struct pci_dev *dev, pm_message_t state) 6538c2ecf20Sopenharmony_ci{ 6548c2ecf20Sopenharmony_ci pci_save_state(dev); 6558c2ecf20Sopenharmony_ci pci_disable_device(dev); 6568c2ecf20Sopenharmony_ci pci_set_power_state(dev, pci_choose_state(dev, state)); 6578c2ecf20Sopenharmony_ci 6588c2ecf20Sopenharmony_ci return 0; 6598c2ecf20Sopenharmony_ci} 6608c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(ide_pci_suspend); 6618c2ecf20Sopenharmony_ci 6628c2ecf20Sopenharmony_ciint ide_pci_resume(struct pci_dev *dev) 6638c2ecf20Sopenharmony_ci{ 6648c2ecf20Sopenharmony_ci struct ide_host *host = pci_get_drvdata(dev); 6658c2ecf20Sopenharmony_ci int rc; 6668c2ecf20Sopenharmony_ci 6678c2ecf20Sopenharmony_ci pci_set_power_state(dev, PCI_D0); 6688c2ecf20Sopenharmony_ci 6698c2ecf20Sopenharmony_ci rc = pci_enable_device(dev); 6708c2ecf20Sopenharmony_ci if (rc) 6718c2ecf20Sopenharmony_ci return rc; 6728c2ecf20Sopenharmony_ci 6738c2ecf20Sopenharmony_ci pci_restore_state(dev); 6748c2ecf20Sopenharmony_ci pci_set_master(dev); 6758c2ecf20Sopenharmony_ci 6768c2ecf20Sopenharmony_ci if (host->init_chipset) 6778c2ecf20Sopenharmony_ci host->init_chipset(dev); 6788c2ecf20Sopenharmony_ci 6798c2ecf20Sopenharmony_ci return 0; 6808c2ecf20Sopenharmony_ci} 6818c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(ide_pci_resume); 6828c2ecf20Sopenharmony_ci#endif 683