Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
0002 /*
0003  * Platform driver for the Synopsys DesignWare DMA Controller
0004  *
0005  * Copyright (C) 2007-2008 Atmel Corporation
0006  * Copyright (C) 2010-2011 ST Microelectronics
0007  * Copyright (C) 2013 Intel Corporation
0008  *
0009  * Some parts of this driver are derived from the original dw_dmac.
0010  */
0011 
0012 #include <linux/module.h>
0013 #include <linux/device.h>
0014 #include <linux/clk.h>
0015 #include <linux/pm_runtime.h>
0016 #include <linux/platform_device.h>
0017 #include <linux/dmaengine.h>
0018 #include <linux/dma-mapping.h>
0019 #include <linux/of.h>
0020 #include <linux/acpi.h>
0021 
0022 #include "internal.h"
0023 
0024 #define DRV_NAME    "dw_dmac"
0025 
0026 static int dw_probe(struct platform_device *pdev)
0027 {
0028     const struct dw_dma_chip_pdata *match;
0029     struct dw_dma_chip_pdata *data;
0030     struct dw_dma_chip *chip;
0031     struct device *dev = &pdev->dev;
0032     int err;
0033 
0034     match = device_get_match_data(dev);
0035     if (!match)
0036         return -ENODEV;
0037 
0038     data = devm_kmemdup(&pdev->dev, match, sizeof(*match), GFP_KERNEL);
0039     if (!data)
0040         return -ENOMEM;
0041 
0042     chip = devm_kzalloc(dev, sizeof(*chip), GFP_KERNEL);
0043     if (!chip)
0044         return -ENOMEM;
0045 
0046     chip->irq = platform_get_irq(pdev, 0);
0047     if (chip->irq < 0)
0048         return chip->irq;
0049 
0050     chip->regs = devm_platform_ioremap_resource(pdev, 0);
0051     if (IS_ERR(chip->regs))
0052         return PTR_ERR(chip->regs);
0053 
0054     err = dma_coerce_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(32));
0055     if (err)
0056         return err;
0057 
0058     if (!data->pdata)
0059         data->pdata = dev_get_platdata(dev);
0060     if (!data->pdata)
0061         data->pdata = dw_dma_parse_dt(pdev);
0062 
0063     chip->dev = dev;
0064     chip->id = pdev->id;
0065     chip->pdata = data->pdata;
0066 
0067     data->chip = chip;
0068 
0069     chip->clk = devm_clk_get_optional(chip->dev, "hclk");
0070     if (IS_ERR(chip->clk))
0071         return PTR_ERR(chip->clk);
0072     err = clk_prepare_enable(chip->clk);
0073     if (err)
0074         return err;
0075 
0076     pm_runtime_enable(&pdev->dev);
0077 
0078     err = data->probe(chip);
0079     if (err)
0080         goto err_dw_dma_probe;
0081 
0082     platform_set_drvdata(pdev, data);
0083 
0084     dw_dma_of_controller_register(chip->dw);
0085 
0086     dw_dma_acpi_controller_register(chip->dw);
0087 
0088     return 0;
0089 
0090 err_dw_dma_probe:
0091     pm_runtime_disable(&pdev->dev);
0092     clk_disable_unprepare(chip->clk);
0093     return err;
0094 }
0095 
0096 static int dw_remove(struct platform_device *pdev)
0097 {
0098     struct dw_dma_chip_pdata *data = platform_get_drvdata(pdev);
0099     struct dw_dma_chip *chip = data->chip;
0100     int ret;
0101 
0102     dw_dma_acpi_controller_free(chip->dw);
0103 
0104     dw_dma_of_controller_free(chip->dw);
0105 
0106     ret = data->remove(chip);
0107     if (ret)
0108         dev_warn(chip->dev, "can't remove device properly: %d\n", ret);
0109 
0110     pm_runtime_disable(&pdev->dev);
0111     clk_disable_unprepare(chip->clk);
0112 
0113     return 0;
0114 }
0115 
0116 static void dw_shutdown(struct platform_device *pdev)
0117 {
0118     struct dw_dma_chip_pdata *data = platform_get_drvdata(pdev);
0119     struct dw_dma_chip *chip = data->chip;
0120 
0121     /*
0122      * We have to call do_dw_dma_disable() to stop any ongoing transfer. On
0123      * some platforms we can't do that since DMA device is powered off.
0124      * Moreover we have no possibility to check if the platform is affected
0125      * or not. That's why we call pm_runtime_get_sync() / pm_runtime_put()
0126      * unconditionally. On the other hand we can't use
0127      * pm_runtime_suspended() because runtime PM framework is not fully
0128      * used by the driver.
0129      */
0130     pm_runtime_get_sync(chip->dev);
0131     do_dw_dma_disable(chip);
0132     pm_runtime_put_sync_suspend(chip->dev);
0133 
0134     clk_disable_unprepare(chip->clk);
0135 }
0136 
0137 #ifdef CONFIG_OF
0138 static const struct of_device_id dw_dma_of_id_table[] = {
0139     { .compatible = "snps,dma-spear1340", .data = &dw_dma_chip_pdata },
0140     { .compatible = "renesas,rzn1-dma", .data = &dw_dma_chip_pdata },
0141     {}
0142 };
0143 MODULE_DEVICE_TABLE(of, dw_dma_of_id_table);
0144 #endif
0145 
0146 #ifdef CONFIG_ACPI
0147 static const struct acpi_device_id dw_dma_acpi_id_table[] = {
0148     { "INTL9C60", (kernel_ulong_t)&dw_dma_chip_pdata },
0149     { "80862286", (kernel_ulong_t)&dw_dma_chip_pdata },
0150     { "808622C0", (kernel_ulong_t)&dw_dma_chip_pdata },
0151 
0152     /* Elkhart Lake iDMA 32-bit (PSE DMA) */
0153     { "80864BB4", (kernel_ulong_t)&xbar_chip_pdata },
0154     { "80864BB5", (kernel_ulong_t)&xbar_chip_pdata },
0155     { "80864BB6", (kernel_ulong_t)&xbar_chip_pdata },
0156 
0157     { }
0158 };
0159 MODULE_DEVICE_TABLE(acpi, dw_dma_acpi_id_table);
0160 #endif
0161 
0162 #ifdef CONFIG_PM_SLEEP
0163 
0164 static int dw_suspend_late(struct device *dev)
0165 {
0166     struct dw_dma_chip_pdata *data = dev_get_drvdata(dev);
0167     struct dw_dma_chip *chip = data->chip;
0168 
0169     do_dw_dma_disable(chip);
0170     clk_disable_unprepare(chip->clk);
0171 
0172     return 0;
0173 }
0174 
0175 static int dw_resume_early(struct device *dev)
0176 {
0177     struct dw_dma_chip_pdata *data = dev_get_drvdata(dev);
0178     struct dw_dma_chip *chip = data->chip;
0179     int ret;
0180 
0181     ret = clk_prepare_enable(chip->clk);
0182     if (ret)
0183         return ret;
0184 
0185     return do_dw_dma_enable(chip);
0186 }
0187 
0188 #endif /* CONFIG_PM_SLEEP */
0189 
0190 static const struct dev_pm_ops dw_dev_pm_ops = {
0191     SET_LATE_SYSTEM_SLEEP_PM_OPS(dw_suspend_late, dw_resume_early)
0192 };
0193 
0194 static struct platform_driver dw_driver = {
0195     .probe      = dw_probe,
0196     .remove     = dw_remove,
0197     .shutdown       = dw_shutdown,
0198     .driver = {
0199         .name   = DRV_NAME,
0200         .pm = &dw_dev_pm_ops,
0201         .of_match_table = of_match_ptr(dw_dma_of_id_table),
0202         .acpi_match_table = ACPI_PTR(dw_dma_acpi_id_table),
0203     },
0204 };
0205 
0206 static int __init dw_init(void)
0207 {
0208     return platform_driver_register(&dw_driver);
0209 }
0210 subsys_initcall(dw_init);
0211 
0212 static void __exit dw_exit(void)
0213 {
0214     platform_driver_unregister(&dw_driver);
0215 }
0216 module_exit(dw_exit);
0217 
0218 MODULE_LICENSE("GPL v2");
0219 MODULE_DESCRIPTION("Synopsys DesignWare DMA Controller platform driver");
0220 MODULE_ALIAS("platform:" DRV_NAME);