linux/drivers/dma/dw/platform.c
<<
>>
Prefs
   1/*
   2 * Platform driver for the Synopsys DesignWare DMA Controller
   3 *
   4 * Copyright (C) 2007-2008 Atmel Corporation
   5 * Copyright (C) 2010-2011 ST Microelectronics
   6 * Copyright (C) 2013 Intel Corporation
   7 *
   8 * Some parts of this driver are derived from the original dw_dmac.
   9 *
  10 * This program is free software; you can redistribute it and/or modify
  11 * it under the terms of the GNU General Public License version 2 as
  12 * published by the Free Software Foundation.
  13 */
  14
  15#include <linux/module.h>
  16#include <linux/device.h>
  17#include <linux/clk.h>
  18#include <linux/platform_device.h>
  19#include <linux/dmaengine.h>
  20#include <linux/dma-mapping.h>
  21#include <linux/of.h>
  22#include <linux/of_dma.h>
  23#include <linux/acpi.h>
  24#include <linux/acpi_dma.h>
  25
  26#include "internal.h"
  27
  28struct dw_dma_of_filter_args {
  29        struct dw_dma *dw;
  30        unsigned int req;
  31        unsigned int src;
  32        unsigned int dst;
  33};
  34
  35static bool dw_dma_of_filter(struct dma_chan *chan, void *param)
  36{
  37        struct dw_dma_chan *dwc = to_dw_dma_chan(chan);
  38        struct dw_dma_of_filter_args *fargs = param;
  39
  40        /* Ensure the device matches our channel */
  41        if (chan->device != &fargs->dw->dma)
  42                return false;
  43
  44        dwc->request_line = fargs->req;
  45        dwc->src_master = fargs->src;
  46        dwc->dst_master = fargs->dst;
  47
  48        return true;
  49}
  50
  51static struct dma_chan *dw_dma_of_xlate(struct of_phandle_args *dma_spec,
  52                                        struct of_dma *ofdma)
  53{
  54        struct dw_dma *dw = ofdma->of_dma_data;
  55        struct dw_dma_of_filter_args fargs = {
  56                .dw = dw,
  57        };
  58        dma_cap_mask_t cap;
  59
  60        if (dma_spec->args_count != 3)
  61                return NULL;
  62
  63        fargs.req = dma_spec->args[0];
  64        fargs.src = dma_spec->args[1];
  65        fargs.dst = dma_spec->args[2];
  66
  67        if (WARN_ON(fargs.req >= DW_DMA_MAX_NR_REQUESTS ||
  68                    fargs.src >= dw->nr_masters ||
  69                    fargs.dst >= dw->nr_masters))
  70                return NULL;
  71
  72        dma_cap_zero(cap);
  73        dma_cap_set(DMA_SLAVE, cap);
  74
  75        /* TODO: there should be a simpler way to do this */
  76        return dma_request_channel(cap, dw_dma_of_filter, &fargs);
  77}
  78
  79#ifdef CONFIG_ACPI
  80static bool dw_dma_acpi_filter(struct dma_chan *chan, void *param)
  81{
  82        struct dw_dma_chan *dwc = to_dw_dma_chan(chan);
  83        struct acpi_dma_spec *dma_spec = param;
  84
  85        if (chan->device->dev != dma_spec->dev ||
  86            chan->chan_id != dma_spec->chan_id)
  87                return false;
  88
  89        dwc->request_line = dma_spec->slave_id;
  90        dwc->src_master = dwc_get_sms(NULL);
  91        dwc->dst_master = dwc_get_dms(NULL);
  92
  93        return true;
  94}
  95
  96static void dw_dma_acpi_controller_register(struct dw_dma *dw)
  97{
  98        struct device *dev = dw->dma.dev;
  99        struct acpi_dma_filter_info *info;
 100        int ret;
 101
 102        info = devm_kzalloc(dev, sizeof(*info), GFP_KERNEL);
 103        if (!info)
 104                return;
 105
 106        dma_cap_zero(info->dma_cap);
 107        dma_cap_set(DMA_SLAVE, info->dma_cap);
 108        info->filter_fn = dw_dma_acpi_filter;
 109
 110        ret = devm_acpi_dma_controller_register(dev, acpi_dma_simple_xlate,
 111                                                info);
 112        if (ret)
 113                dev_err(dev, "could not register acpi_dma_controller\n");
 114}
 115#else /* !CONFIG_ACPI */
 116static inline void dw_dma_acpi_controller_register(struct dw_dma *dw) {}
 117#endif /* !CONFIG_ACPI */
 118
 119#ifdef CONFIG_OF
 120static struct dw_dma_platform_data *
 121dw_dma_parse_dt(struct platform_device *pdev)
 122{
 123        struct device_node *np = pdev->dev.of_node;
 124        struct dw_dma_platform_data *pdata;
 125        u32 tmp, arr[4];
 126
 127        if (!np) {
 128                dev_err(&pdev->dev, "Missing DT data\n");
 129                return NULL;
 130        }
 131
 132        pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL);
 133        if (!pdata)
 134                return NULL;
 135
 136        if (of_property_read_u32(np, "dma-channels", &pdata->nr_channels))
 137                return NULL;
 138
 139        if (of_property_read_bool(np, "is_private"))
 140                pdata->is_private = true;
 141
 142        if (!of_property_read_u32(np, "chan_allocation_order", &tmp))
 143                pdata->chan_allocation_order = (unsigned char)tmp;
 144
 145        if (!of_property_read_u32(np, "chan_priority", &tmp))
 146                pdata->chan_priority = tmp;
 147
 148        if (!of_property_read_u32(np, "block_size", &tmp))
 149                pdata->block_size = tmp;
 150
 151        if (!of_property_read_u32(np, "dma-masters", &tmp)) {
 152                if (tmp > 4)
 153                        return NULL;
 154
 155                pdata->nr_masters = tmp;
 156        }
 157
 158        if (!of_property_read_u32_array(np, "data_width", arr,
 159                                pdata->nr_masters))
 160                for (tmp = 0; tmp < pdata->nr_masters; tmp++)
 161                        pdata->data_width[tmp] = arr[tmp];
 162
 163        return pdata;
 164}
 165#else
 166static inline struct dw_dma_platform_data *
 167dw_dma_parse_dt(struct platform_device *pdev)
 168{
 169        return NULL;
 170}
 171#endif
 172
 173static int dw_probe(struct platform_device *pdev)
 174{
 175        struct dw_dma_chip *chip;
 176        struct device *dev = &pdev->dev;
 177        struct resource *mem;
 178        struct dw_dma_platform_data *pdata;
 179        int err;
 180
 181        chip = devm_kzalloc(dev, sizeof(*chip), GFP_KERNEL);
 182        if (!chip)
 183                return -ENOMEM;
 184
 185        chip->irq = platform_get_irq(pdev, 0);
 186        if (chip->irq < 0)
 187                return chip->irq;
 188
 189        mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 190        chip->regs = devm_ioremap_resource(dev, mem);
 191        if (IS_ERR(chip->regs))
 192                return PTR_ERR(chip->regs);
 193
 194        /* Apply default dma_mask if needed */
 195        if (!dev->dma_mask) {
 196                dev->dma_mask = &dev->coherent_dma_mask;
 197                dev->coherent_dma_mask = DMA_BIT_MASK(32);
 198        }
 199
 200        pdata = dev_get_platdata(dev);
 201        if (!pdata)
 202                pdata = dw_dma_parse_dt(pdev);
 203
 204        chip->dev = dev;
 205
 206        err = dw_dma_probe(chip, pdata);
 207        if (err)
 208                return err;
 209
 210        platform_set_drvdata(pdev, chip);
 211
 212        if (pdev->dev.of_node) {
 213                err = of_dma_controller_register(pdev->dev.of_node,
 214                                                 dw_dma_of_xlate, chip->dw);
 215                if (err)
 216                        dev_err(&pdev->dev,
 217                                "could not register of_dma_controller\n");
 218        }
 219
 220        if (ACPI_HANDLE(&pdev->dev))
 221                dw_dma_acpi_controller_register(chip->dw);
 222
 223        return 0;
 224}
 225
 226static int dw_remove(struct platform_device *pdev)
 227{
 228        struct dw_dma_chip *chip = platform_get_drvdata(pdev);
 229
 230        if (pdev->dev.of_node)
 231                of_dma_controller_free(pdev->dev.of_node);
 232
 233        return dw_dma_remove(chip);
 234}
 235
 236static void dw_shutdown(struct platform_device *pdev)
 237{
 238        struct dw_dma_chip *chip = platform_get_drvdata(pdev);
 239
 240        dw_dma_shutdown(chip);
 241}
 242
 243#ifdef CONFIG_OF
 244static const struct of_device_id dw_dma_of_id_table[] = {
 245        { .compatible = "snps,dma-spear1340" },
 246        {}
 247};
 248MODULE_DEVICE_TABLE(of, dw_dma_of_id_table);
 249#endif
 250
 251#ifdef CONFIG_ACPI
 252static const struct acpi_device_id dw_dma_acpi_id_table[] = {
 253        { "INTL9C60", 0 },
 254        { }
 255};
 256#endif
 257
 258#ifdef CONFIG_PM_SLEEP
 259
 260static int dw_suspend_noirq(struct device *dev)
 261{
 262        struct platform_device *pdev = to_platform_device(dev);
 263        struct dw_dma_chip *chip = platform_get_drvdata(pdev);
 264
 265        return dw_dma_suspend(chip);
 266}
 267
 268static int dw_resume_noirq(struct device *dev)
 269{
 270        struct platform_device *pdev = to_platform_device(dev);
 271        struct dw_dma_chip *chip = platform_get_drvdata(pdev);
 272
 273        return dw_dma_resume(chip);
 274}
 275
 276#else /* !CONFIG_PM_SLEEP */
 277
 278#define dw_suspend_noirq        NULL
 279#define dw_resume_noirq         NULL
 280
 281#endif /* !CONFIG_PM_SLEEP */
 282
 283static const struct dev_pm_ops dw_dev_pm_ops = {
 284        .suspend_noirq = dw_suspend_noirq,
 285        .resume_noirq = dw_resume_noirq,
 286        .freeze_noirq = dw_suspend_noirq,
 287        .thaw_noirq = dw_resume_noirq,
 288        .restore_noirq = dw_resume_noirq,
 289        .poweroff_noirq = dw_suspend_noirq,
 290};
 291
 292static struct platform_driver dw_driver = {
 293        .probe          = dw_probe,
 294        .remove         = dw_remove,
 295        .shutdown       = dw_shutdown,
 296        .driver = {
 297                .name   = "dw_dmac",
 298                .pm     = &dw_dev_pm_ops,
 299                .of_match_table = of_match_ptr(dw_dma_of_id_table),
 300                .acpi_match_table = ACPI_PTR(dw_dma_acpi_id_table),
 301        },
 302};
 303
 304static int __init dw_init(void)
 305{
 306        return platform_driver_register(&dw_driver);
 307}
 308subsys_initcall(dw_init);
 309
 310static void __exit dw_exit(void)
 311{
 312        platform_driver_unregister(&dw_driver);
 313}
 314module_exit(dw_exit);
 315
 316MODULE_LICENSE("GPL v2");
 317MODULE_DESCRIPTION("Synopsys DesignWare DMA Controller platform driver");
 318