linux/drivers/dma/dw/pci.c
<<
>>
Prefs
   1/*
   2 * PCI driver for the Synopsys DesignWare DMA Controller
   3 *
   4 * Copyright (C) 2013 Intel Corporation
   5 * Author: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
   6 *
   7 * This program is free software; you can redistribute it and/or modify
   8 * it under the terms of the GNU General Public License version 2 as
   9 * published by the Free Software Foundation.
  10 */
  11
  12#include <linux/module.h>
  13#include <linux/pci.h>
  14#include <linux/device.h>
  15
  16#include "internal.h"
  17
  18static int dw_pci_probe(struct pci_dev *pdev, const struct pci_device_id *pid)
  19{
  20        struct dw_dma_chip *chip;
  21        struct dw_dma_platform_data *pdata = (void *)pid->driver_data;
  22        int ret;
  23
  24        ret = pcim_enable_device(pdev);
  25        if (ret)
  26                return ret;
  27
  28        ret = pcim_iomap_regions(pdev, 1 << 0, pci_name(pdev));
  29        if (ret) {
  30                dev_err(&pdev->dev, "I/O memory remapping failed\n");
  31                return ret;
  32        }
  33
  34        pci_set_master(pdev);
  35        pci_try_set_mwi(pdev);
  36
  37        ret = pci_set_dma_mask(pdev, DMA_BIT_MASK(32));
  38        if (ret)
  39                return ret;
  40
  41        ret = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(32));
  42        if (ret)
  43                return ret;
  44
  45        chip = devm_kzalloc(&pdev->dev, sizeof(*chip), GFP_KERNEL);
  46        if (!chip)
  47                return -ENOMEM;
  48
  49        chip->dev = &pdev->dev;
  50        chip->regs = pcim_iomap_table(pdev)[0];
  51        chip->irq = pdev->irq;
  52
  53        ret = dw_dma_probe(chip, pdata);
  54        if (ret)
  55                return ret;
  56
  57        pci_set_drvdata(pdev, chip);
  58
  59        return 0;
  60}
  61
  62static void dw_pci_remove(struct pci_dev *pdev)
  63{
  64        struct dw_dma_chip *chip = pci_get_drvdata(pdev);
  65        int ret;
  66
  67        ret = dw_dma_remove(chip);
  68        if (ret)
  69                dev_warn(&pdev->dev, "can't remove device properly: %d\n", ret);
  70}
  71
  72#ifdef CONFIG_PM_SLEEP
  73
  74static int dw_pci_suspend_late(struct device *dev)
  75{
  76        struct pci_dev *pci = to_pci_dev(dev);
  77        struct dw_dma_chip *chip = pci_get_drvdata(pci);
  78
  79        return dw_dma_disable(chip);
  80};
  81
  82static int dw_pci_resume_early(struct device *dev)
  83{
  84        struct pci_dev *pci = to_pci_dev(dev);
  85        struct dw_dma_chip *chip = pci_get_drvdata(pci);
  86
  87        return dw_dma_enable(chip);
  88};
  89
  90#endif /* CONFIG_PM_SLEEP */
  91
  92static const struct dev_pm_ops dw_pci_dev_pm_ops = {
  93        SET_LATE_SYSTEM_SLEEP_PM_OPS(dw_pci_suspend_late, dw_pci_resume_early)
  94};
  95
  96static const struct pci_device_id dw_pci_id_table[] = {
  97        /* Medfield */
  98        { PCI_VDEVICE(INTEL, 0x0827) },
  99        { PCI_VDEVICE(INTEL, 0x0830) },
 100
 101        /* BayTrail */
 102        { PCI_VDEVICE(INTEL, 0x0f06) },
 103        { PCI_VDEVICE(INTEL, 0x0f40) },
 104
 105        /* Braswell */
 106        { PCI_VDEVICE(INTEL, 0x2286) },
 107        { PCI_VDEVICE(INTEL, 0x22c0) },
 108
 109        /* Haswell */
 110        { PCI_VDEVICE(INTEL, 0x9c60) },
 111
 112        /* Broadwell */
 113        { PCI_VDEVICE(INTEL, 0x9ce0) },
 114
 115        { }
 116};
 117MODULE_DEVICE_TABLE(pci, dw_pci_id_table);
 118
 119static struct pci_driver dw_pci_driver = {
 120        .name           = "dw_dmac_pci",
 121        .id_table       = dw_pci_id_table,
 122        .probe          = dw_pci_probe,
 123        .remove         = dw_pci_remove,
 124        .driver = {
 125                .pm     = &dw_pci_dev_pm_ops,
 126        },
 127};
 128
 129module_pci_driver(dw_pci_driver);
 130
 131MODULE_LICENSE("GPL v2");
 132MODULE_DESCRIPTION("Synopsys DesignWare DMA Controller PCI driver");
 133MODULE_AUTHOR("Andy Shevchenko <andriy.shevchenko@linux.intel.com>");
 134