root/drivers/dma/dw/platform.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. dw_probe
  2. dw_remove
  3. dw_shutdown
  4. dw_suspend_late
  5. dw_resume_early
  6. dw_init
  7. dw_exit

   1 // SPDX-License-Identifier: GPL-2.0
   2 /*
   3  * Platform driver for the Synopsys DesignWare DMA Controller
   4  *
   5  * Copyright (C) 2007-2008 Atmel Corporation
   6  * Copyright (C) 2010-2011 ST Microelectronics
   7  * Copyright (C) 2013 Intel Corporation
   8  *
   9  * Some parts of this driver are derived from the original dw_dmac.
  10  */
  11 
  12 #include <linux/module.h>
  13 #include <linux/device.h>
  14 #include <linux/clk.h>
  15 #include <linux/pm_runtime.h>
  16 #include <linux/platform_device.h>
  17 #include <linux/dmaengine.h>
  18 #include <linux/dma-mapping.h>
  19 #include <linux/of.h>
  20 #include <linux/acpi.h>
  21 
  22 #include "internal.h"
  23 
  24 #define DRV_NAME        "dw_dmac"
  25 
  26 static int dw_probe(struct platform_device *pdev)
  27 {
  28         const struct dw_dma_chip_pdata *match;
  29         struct dw_dma_chip_pdata *data;
  30         struct dw_dma_chip *chip;
  31         struct device *dev = &pdev->dev;
  32         int err;
  33 
  34         match = device_get_match_data(dev);
  35         if (!match)
  36                 return -ENODEV;
  37 
  38         data = devm_kmemdup(&pdev->dev, match, sizeof(*match), GFP_KERNEL);
  39         if (!data)
  40                 return -ENOMEM;
  41 
  42         chip = devm_kzalloc(dev, sizeof(*chip), GFP_KERNEL);
  43         if (!chip)
  44                 return -ENOMEM;
  45 
  46         chip->irq = platform_get_irq(pdev, 0);
  47         if (chip->irq < 0)
  48                 return chip->irq;
  49 
  50         chip->regs = devm_platform_ioremap_resource(pdev, 0);
  51         if (IS_ERR(chip->regs))
  52                 return PTR_ERR(chip->regs);
  53 
  54         err = dma_coerce_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(32));
  55         if (err)
  56                 return err;
  57 
  58         if (!data->pdata)
  59                 data->pdata = dev_get_platdata(dev);
  60         if (!data->pdata)
  61                 data->pdata = dw_dma_parse_dt(pdev);
  62 
  63         chip->dev = dev;
  64         chip->id = pdev->id;
  65         chip->pdata = data->pdata;
  66 
  67         data->chip = chip;
  68 
  69         chip->clk = devm_clk_get_optional(chip->dev, "hclk");
  70         if (IS_ERR(chip->clk))
  71                 return PTR_ERR(chip->clk);
  72         err = clk_prepare_enable(chip->clk);
  73         if (err)
  74                 return err;
  75 
  76         pm_runtime_enable(&pdev->dev);
  77 
  78         err = data->probe(chip);
  79         if (err)
  80                 goto err_dw_dma_probe;
  81 
  82         platform_set_drvdata(pdev, data);
  83 
  84         dw_dma_of_controller_register(chip->dw);
  85 
  86         dw_dma_acpi_controller_register(chip->dw);
  87 
  88         return 0;
  89 
  90 err_dw_dma_probe:
  91         pm_runtime_disable(&pdev->dev);
  92         clk_disable_unprepare(chip->clk);
  93         return err;
  94 }
  95 
  96 static int dw_remove(struct platform_device *pdev)
  97 {
  98         struct dw_dma_chip_pdata *data = platform_get_drvdata(pdev);
  99         struct dw_dma_chip *chip = data->chip;
 100         int ret;
 101 
 102         dw_dma_acpi_controller_free(chip->dw);
 103 
 104         dw_dma_of_controller_free(chip->dw);
 105 
 106         ret = data->remove(chip);
 107         if (ret)
 108                 dev_warn(chip->dev, "can't remove device properly: %d\n", ret);
 109 
 110         pm_runtime_disable(&pdev->dev);
 111         clk_disable_unprepare(chip->clk);
 112 
 113         return 0;
 114 }
 115 
 116 static void dw_shutdown(struct platform_device *pdev)
 117 {
 118         struct dw_dma_chip_pdata *data = platform_get_drvdata(pdev);
 119         struct dw_dma_chip *chip = data->chip;
 120 
 121         /*
 122          * We have to call do_dw_dma_disable() to stop any ongoing transfer. On
 123          * some platforms we can't do that since DMA device is powered off.
 124          * Moreover we have no possibility to check if the platform is affected
 125          * or not. That's why we call pm_runtime_get_sync() / pm_runtime_put()
 126          * unconditionally. On the other hand we can't use
 127          * pm_runtime_suspended() because runtime PM framework is not fully
 128          * used by the driver.
 129          */
 130         pm_runtime_get_sync(chip->dev);
 131         do_dw_dma_disable(chip);
 132         pm_runtime_put_sync_suspend(chip->dev);
 133 
 134         clk_disable_unprepare(chip->clk);
 135 }
 136 
 137 #ifdef CONFIG_OF
 138 static const struct of_device_id dw_dma_of_id_table[] = {
 139         { .compatible = "snps,dma-spear1340", .data = &dw_dma_chip_pdata },
 140         {}
 141 };
 142 MODULE_DEVICE_TABLE(of, dw_dma_of_id_table);
 143 #endif
 144 
 145 #ifdef CONFIG_ACPI
 146 static const struct acpi_device_id dw_dma_acpi_id_table[] = {
 147         { "INTL9C60", (kernel_ulong_t)&dw_dma_chip_pdata },
 148         { "80862286", (kernel_ulong_t)&dw_dma_chip_pdata },
 149         { "808622C0", (kernel_ulong_t)&dw_dma_chip_pdata },
 150 
 151         /* Elkhart Lake iDMA 32-bit (PSE DMA) */
 152         { "80864BB4", (kernel_ulong_t)&idma32_chip_pdata },
 153         { "80864BB5", (kernel_ulong_t)&idma32_chip_pdata },
 154         { "80864BB6", (kernel_ulong_t)&idma32_chip_pdata },
 155 
 156         { }
 157 };
 158 MODULE_DEVICE_TABLE(acpi, dw_dma_acpi_id_table);
 159 #endif
 160 
 161 #ifdef CONFIG_PM_SLEEP
 162 
 163 static int dw_suspend_late(struct device *dev)
 164 {
 165         struct dw_dma_chip_pdata *data = dev_get_drvdata(dev);
 166         struct dw_dma_chip *chip = data->chip;
 167 
 168         do_dw_dma_disable(chip);
 169         clk_disable_unprepare(chip->clk);
 170 
 171         return 0;
 172 }
 173 
 174 static int dw_resume_early(struct device *dev)
 175 {
 176         struct dw_dma_chip_pdata *data = dev_get_drvdata(dev);
 177         struct dw_dma_chip *chip = data->chip;
 178         int ret;
 179 
 180         ret = clk_prepare_enable(chip->clk);
 181         if (ret)
 182                 return ret;
 183 
 184         return do_dw_dma_enable(chip);
 185 }
 186 
 187 #endif /* CONFIG_PM_SLEEP */
 188 
 189 static const struct dev_pm_ops dw_dev_pm_ops = {
 190         SET_LATE_SYSTEM_SLEEP_PM_OPS(dw_suspend_late, dw_resume_early)
 191 };
 192 
 193 static struct platform_driver dw_driver = {
 194         .probe          = dw_probe,
 195         .remove         = dw_remove,
 196         .shutdown       = dw_shutdown,
 197         .driver = {
 198                 .name   = DRV_NAME,
 199                 .pm     = &dw_dev_pm_ops,
 200                 .of_match_table = of_match_ptr(dw_dma_of_id_table),
 201                 .acpi_match_table = ACPI_PTR(dw_dma_acpi_id_table),
 202         },
 203 };
 204 
 205 static int __init dw_init(void)
 206 {
 207         return platform_driver_register(&dw_driver);
 208 }
 209 subsys_initcall(dw_init);
 210 
 211 static void __exit dw_exit(void)
 212 {
 213         platform_driver_unregister(&dw_driver);
 214 }
 215 module_exit(dw_exit);
 216 
 217 MODULE_LICENSE("GPL v2");
 218 MODULE_DESCRIPTION("Synopsys DesignWare DMA Controller platform driver");
 219 MODULE_ALIAS("platform:" DRV_NAME);

/* [<][>][^][v][top][bottom][index][help] */