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 struct dw_dma_platform_data mrfld_pdata = {
  19        .nr_channels = 8,
  20        .is_private = true,
  21        .is_memcpy = true,
  22        .is_idma32 = true,
  23        .chan_allocation_order = CHAN_ALLOCATION_ASCENDING,
  24        .chan_priority = CHAN_PRIORITY_ASCENDING,
  25        .block_size = 131071,
  26        .nr_masters = 1,
  27        .data_width = {4},
  28};
  29
  30static int dw_pci_probe(struct pci_dev *pdev, const struct pci_device_id *pid)
  31{
  32        const struct dw_dma_platform_data *pdata = (void *)pid->driver_data;
  33        struct dw_dma_chip *chip;
  34        int ret;
  35
  36        ret = pcim_enable_device(pdev);
  37        if (ret)
  38                return ret;
  39
  40        ret = pcim_iomap_regions(pdev, 1 << 0, pci_name(pdev));
  41        if (ret) {
  42                dev_err(&pdev->dev, "I/O memory remapping failed\n");
  43                return ret;
  44        }
  45
  46        pci_set_master(pdev);
  47        pci_try_set_mwi(pdev);
  48
  49        ret = pci_set_dma_mask(pdev, DMA_BIT_MASK(32));
  50        if (ret)
  51                return ret;
  52
  53        ret = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(32));
  54        if (ret)
  55                return ret;
  56
  57        chip = devm_kzalloc(&pdev->dev, sizeof(*chip), GFP_KERNEL);
  58        if (!chip)
  59                return -ENOMEM;
  60
  61        chip->dev = &pdev->dev;
  62        chip->id = pdev->devfn;
  63        chip->regs = pcim_iomap_table(pdev)[0];
  64        chip->irq = pdev->irq;
  65        chip->pdata = pdata;
  66
  67        ret = dw_dma_probe(chip);
  68        if (ret)
  69                return ret;
  70
  71        pci_set_drvdata(pdev, chip);
  72
  73        return 0;
  74}
  75
  76static void dw_pci_remove(struct pci_dev *pdev)
  77{
  78        struct dw_dma_chip *chip = pci_get_drvdata(pdev);
  79        int ret;
  80
  81        ret = dw_dma_remove(chip);
  82        if (ret)
  83                dev_warn(&pdev->dev, "can't remove device properly: %d\n", ret);
  84}
  85
  86#ifdef CONFIG_PM_SLEEP
  87
  88static int dw_pci_suspend_late(struct device *dev)
  89{
  90        struct pci_dev *pci = to_pci_dev(dev);
  91        struct dw_dma_chip *chip = pci_get_drvdata(pci);
  92
  93        return dw_dma_disable(chip);
  94};
  95
  96static int dw_pci_resume_early(struct device *dev)
  97{
  98        struct pci_dev *pci = to_pci_dev(dev);
  99        struct dw_dma_chip *chip = pci_get_drvdata(pci);
 100
 101        return dw_dma_enable(chip);
 102};
 103
 104#endif /* CONFIG_PM_SLEEP */
 105
 106static const struct dev_pm_ops dw_pci_dev_pm_ops = {
 107        SET_LATE_SYSTEM_SLEEP_PM_OPS(dw_pci_suspend_late, dw_pci_resume_early)
 108};
 109
 110static const struct pci_device_id dw_pci_id_table[] = {
 111        /* Medfield (GPDMA) */
 112        { PCI_VDEVICE(INTEL, 0x0827) },
 113
 114        /* BayTrail */
 115        { PCI_VDEVICE(INTEL, 0x0f06) },
 116        { PCI_VDEVICE(INTEL, 0x0f40) },
 117
 118        /* Merrifield iDMA 32-bit (GPDMA) */
 119        { PCI_VDEVICE(INTEL, 0x11a2), (kernel_ulong_t)&mrfld_pdata },
 120
 121        /* Braswell */
 122        { PCI_VDEVICE(INTEL, 0x2286) },
 123        { PCI_VDEVICE(INTEL, 0x22c0) },
 124
 125        /* Haswell */
 126        { PCI_VDEVICE(INTEL, 0x9c60) },
 127
 128        /* Broadwell */
 129        { PCI_VDEVICE(INTEL, 0x9ce0) },
 130
 131        { }
 132};
 133MODULE_DEVICE_TABLE(pci, dw_pci_id_table);
 134
 135static struct pci_driver dw_pci_driver = {
 136        .name           = "dw_dmac_pci",
 137        .id_table       = dw_pci_id_table,
 138        .probe          = dw_pci_probe,
 139        .remove         = dw_pci_remove,
 140        .driver = {
 141                .pm     = &dw_pci_dev_pm_ops,
 142        },
 143};
 144
 145module_pci_driver(dw_pci_driver);
 146
 147MODULE_LICENSE("GPL v2");
 148MODULE_DESCRIPTION("Synopsys DesignWare DMA Controller PCI driver");
 149MODULE_AUTHOR("Andy Shevchenko <andriy.shevchenko@linux.intel.com>");
 150