linux/drivers/dma/fsl-edma.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0-or-later
   2/*
   3 * drivers/dma/fsl-edma.c
   4 *
   5 * Copyright 2013-2014 Freescale Semiconductor, Inc.
   6 *
   7 * Driver for the Freescale eDMA engine with flexible channel multiplexing
   8 * capability for DMA request sources. The eDMA block can be found on some
   9 * Vybrid and Layerscape SoCs.
  10 */
  11
  12#include <linux/module.h>
  13#include <linux/interrupt.h>
  14#include <linux/clk.h>
  15#include <linux/of.h>
  16#include <linux/of_device.h>
  17#include <linux/of_address.h>
  18#include <linux/of_irq.h>
  19#include <linux/of_dma.h>
  20
  21#include "fsl-edma-common.h"
  22
  23static void fsl_edma_synchronize(struct dma_chan *chan)
  24{
  25        struct fsl_edma_chan *fsl_chan = to_fsl_edma_chan(chan);
  26
  27        vchan_synchronize(&fsl_chan->vchan);
  28}
  29
  30static irqreturn_t fsl_edma_tx_handler(int irq, void *dev_id)
  31{
  32        struct fsl_edma_engine *fsl_edma = dev_id;
  33        unsigned int intr, ch;
  34        struct edma_regs *regs = &fsl_edma->regs;
  35        struct fsl_edma_chan *fsl_chan;
  36
  37        intr = edma_readl(fsl_edma, regs->intl);
  38        if (!intr)
  39                return IRQ_NONE;
  40
  41        for (ch = 0; ch < fsl_edma->n_chans; ch++) {
  42                if (intr & (0x1 << ch)) {
  43                        edma_writeb(fsl_edma, EDMA_CINT_CINT(ch), regs->cint);
  44
  45                        fsl_chan = &fsl_edma->chans[ch];
  46
  47                        spin_lock(&fsl_chan->vchan.lock);
  48
  49                        if (!fsl_chan->edesc) {
  50                                /* terminate_all called before */
  51                                spin_unlock(&fsl_chan->vchan.lock);
  52                                continue;
  53                        }
  54
  55                        if (!fsl_chan->edesc->iscyclic) {
  56                                list_del(&fsl_chan->edesc->vdesc.node);
  57                                vchan_cookie_complete(&fsl_chan->edesc->vdesc);
  58                                fsl_chan->edesc = NULL;
  59                                fsl_chan->status = DMA_COMPLETE;
  60                                fsl_chan->idle = true;
  61                        } else {
  62                                vchan_cyclic_callback(&fsl_chan->edesc->vdesc);
  63                        }
  64
  65                        if (!fsl_chan->edesc)
  66                                fsl_edma_xfer_desc(fsl_chan);
  67
  68                        spin_unlock(&fsl_chan->vchan.lock);
  69                }
  70        }
  71        return IRQ_HANDLED;
  72}
  73
  74static irqreturn_t fsl_edma_err_handler(int irq, void *dev_id)
  75{
  76        struct fsl_edma_engine *fsl_edma = dev_id;
  77        unsigned int err, ch;
  78        struct edma_regs *regs = &fsl_edma->regs;
  79
  80        err = edma_readl(fsl_edma, regs->errl);
  81        if (!err)
  82                return IRQ_NONE;
  83
  84        for (ch = 0; ch < fsl_edma->n_chans; ch++) {
  85                if (err & (0x1 << ch)) {
  86                        fsl_edma_disable_request(&fsl_edma->chans[ch]);
  87                        edma_writeb(fsl_edma, EDMA_CERR_CERR(ch), regs->cerr);
  88                        fsl_edma->chans[ch].status = DMA_ERROR;
  89                        fsl_edma->chans[ch].idle = true;
  90                }
  91        }
  92        return IRQ_HANDLED;
  93}
  94
  95static irqreturn_t fsl_edma_irq_handler(int irq, void *dev_id)
  96{
  97        if (fsl_edma_tx_handler(irq, dev_id) == IRQ_HANDLED)
  98                return IRQ_HANDLED;
  99
 100        return fsl_edma_err_handler(irq, dev_id);
 101}
 102
 103static struct dma_chan *fsl_edma_xlate(struct of_phandle_args *dma_spec,
 104                struct of_dma *ofdma)
 105{
 106        struct fsl_edma_engine *fsl_edma = ofdma->of_dma_data;
 107        struct dma_chan *chan, *_chan;
 108        struct fsl_edma_chan *fsl_chan;
 109        u32 dmamux_nr = fsl_edma->drvdata->dmamuxs;
 110        unsigned long chans_per_mux = fsl_edma->n_chans / dmamux_nr;
 111
 112        if (dma_spec->args_count != 2)
 113                return NULL;
 114
 115        mutex_lock(&fsl_edma->fsl_edma_mutex);
 116        list_for_each_entry_safe(chan, _chan, &fsl_edma->dma_dev.channels, device_node) {
 117                if (chan->client_count)
 118                        continue;
 119                if ((chan->chan_id / chans_per_mux) == dma_spec->args[0]) {
 120                        chan = dma_get_slave_channel(chan);
 121                        if (chan) {
 122                                chan->device->privatecnt++;
 123                                fsl_chan = to_fsl_edma_chan(chan);
 124                                fsl_chan->slave_id = dma_spec->args[1];
 125                                fsl_edma_chan_mux(fsl_chan, fsl_chan->slave_id,
 126                                                true);
 127                                mutex_unlock(&fsl_edma->fsl_edma_mutex);
 128                                return chan;
 129                        }
 130                }
 131        }
 132        mutex_unlock(&fsl_edma->fsl_edma_mutex);
 133        return NULL;
 134}
 135
 136static int
 137fsl_edma_irq_init(struct platform_device *pdev, struct fsl_edma_engine *fsl_edma)
 138{
 139        int ret;
 140
 141        fsl_edma->txirq = platform_get_irq_byname(pdev, "edma-tx");
 142        if (fsl_edma->txirq < 0)
 143                return fsl_edma->txirq;
 144
 145        fsl_edma->errirq = platform_get_irq_byname(pdev, "edma-err");
 146        if (fsl_edma->errirq < 0)
 147                return fsl_edma->errirq;
 148
 149        if (fsl_edma->txirq == fsl_edma->errirq) {
 150                ret = devm_request_irq(&pdev->dev, fsl_edma->txirq,
 151                                fsl_edma_irq_handler, 0, "eDMA", fsl_edma);
 152                if (ret) {
 153                        dev_err(&pdev->dev, "Can't register eDMA IRQ.\n");
 154                        return ret;
 155                }
 156        } else {
 157                ret = devm_request_irq(&pdev->dev, fsl_edma->txirq,
 158                                fsl_edma_tx_handler, 0, "eDMA tx", fsl_edma);
 159                if (ret) {
 160                        dev_err(&pdev->dev, "Can't register eDMA tx IRQ.\n");
 161                        return ret;
 162                }
 163
 164                ret = devm_request_irq(&pdev->dev, fsl_edma->errirq,
 165                                fsl_edma_err_handler, 0, "eDMA err", fsl_edma);
 166                if (ret) {
 167                        dev_err(&pdev->dev, "Can't register eDMA err IRQ.\n");
 168                        return ret;
 169                }
 170        }
 171
 172        return 0;
 173}
 174
 175static int
 176fsl_edma2_irq_init(struct platform_device *pdev,
 177                   struct fsl_edma_engine *fsl_edma)
 178{
 179        int i, ret, irq;
 180        int count;
 181
 182        count = platform_irq_count(pdev);
 183        dev_dbg(&pdev->dev, "%s Found %d interrupts\r\n", __func__, count);
 184        if (count <= 2) {
 185                dev_err(&pdev->dev, "Interrupts in DTS not correct.\n");
 186                return -EINVAL;
 187        }
 188        /*
 189         * 16 channel independent interrupts + 1 error interrupt on i.mx7ulp.
 190         * 2 channel share one interrupt, for example, ch0/ch16, ch1/ch17...
 191         * For now, just simply request irq without IRQF_SHARED flag, since 16
 192         * channels are enough on i.mx7ulp whose M4 domain own some peripherals.
 193         */
 194        for (i = 0; i < count; i++) {
 195                irq = platform_get_irq(pdev, i);
 196                if (irq < 0)
 197                        return -ENXIO;
 198
 199                sprintf(fsl_edma->chans[i].chan_name, "eDMA2-CH%02d", i);
 200
 201                /* The last IRQ is for eDMA err */
 202                if (i == count - 1)
 203                        ret = devm_request_irq(&pdev->dev, irq,
 204                                                fsl_edma_err_handler,
 205                                                0, "eDMA2-ERR", fsl_edma);
 206                else
 207                        ret = devm_request_irq(&pdev->dev, irq,
 208                                                fsl_edma_tx_handler, 0,
 209                                                fsl_edma->chans[i].chan_name,
 210                                                fsl_edma);
 211                if (ret)
 212                        return ret;
 213        }
 214
 215        return 0;
 216}
 217
 218static void fsl_edma_irq_exit(
 219                struct platform_device *pdev, struct fsl_edma_engine *fsl_edma)
 220{
 221        if (fsl_edma->txirq == fsl_edma->errirq) {
 222                devm_free_irq(&pdev->dev, fsl_edma->txirq, fsl_edma);
 223        } else {
 224                devm_free_irq(&pdev->dev, fsl_edma->txirq, fsl_edma);
 225                devm_free_irq(&pdev->dev, fsl_edma->errirq, fsl_edma);
 226        }
 227}
 228
 229static void fsl_disable_clocks(struct fsl_edma_engine *fsl_edma, int nr_clocks)
 230{
 231        int i;
 232
 233        for (i = 0; i < nr_clocks; i++)
 234                clk_disable_unprepare(fsl_edma->muxclk[i]);
 235}
 236
 237static struct fsl_edma_drvdata vf610_data = {
 238        .version = v1,
 239        .dmamuxs = DMAMUX_NR,
 240        .setup_irq = fsl_edma_irq_init,
 241};
 242
 243static struct fsl_edma_drvdata ls1028a_data = {
 244        .version = v1,
 245        .dmamuxs = DMAMUX_NR,
 246        .mux_swap = true,
 247        .setup_irq = fsl_edma_irq_init,
 248};
 249
 250static struct fsl_edma_drvdata imx7ulp_data = {
 251        .version = v3,
 252        .dmamuxs = 1,
 253        .has_dmaclk = true,
 254        .setup_irq = fsl_edma2_irq_init,
 255};
 256
 257static const struct of_device_id fsl_edma_dt_ids[] = {
 258        { .compatible = "fsl,vf610-edma", .data = &vf610_data},
 259        { .compatible = "fsl,ls1028a-edma", .data = &ls1028a_data},
 260        { .compatible = "fsl,imx7ulp-edma", .data = &imx7ulp_data},
 261        { /* sentinel */ }
 262};
 263MODULE_DEVICE_TABLE(of, fsl_edma_dt_ids);
 264
 265static int fsl_edma_probe(struct platform_device *pdev)
 266{
 267        const struct of_device_id *of_id =
 268                        of_match_device(fsl_edma_dt_ids, &pdev->dev);
 269        struct device_node *np = pdev->dev.of_node;
 270        struct fsl_edma_engine *fsl_edma;
 271        const struct fsl_edma_drvdata *drvdata = NULL;
 272        struct fsl_edma_chan *fsl_chan;
 273        struct edma_regs *regs;
 274        struct resource *res;
 275        int len, chans;
 276        int ret, i;
 277
 278        if (of_id)
 279                drvdata = of_id->data;
 280        if (!drvdata) {
 281                dev_err(&pdev->dev, "unable to find driver data\n");
 282                return -EINVAL;
 283        }
 284
 285        ret = of_property_read_u32(np, "dma-channels", &chans);
 286        if (ret) {
 287                dev_err(&pdev->dev, "Can't get dma-channels.\n");
 288                return ret;
 289        }
 290
 291        len = sizeof(*fsl_edma) + sizeof(*fsl_chan) * chans;
 292        fsl_edma = devm_kzalloc(&pdev->dev, len, GFP_KERNEL);
 293        if (!fsl_edma)
 294                return -ENOMEM;
 295
 296        fsl_edma->drvdata = drvdata;
 297        fsl_edma->n_chans = chans;
 298        mutex_init(&fsl_edma->fsl_edma_mutex);
 299
 300        res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 301        fsl_edma->membase = devm_ioremap_resource(&pdev->dev, res);
 302        if (IS_ERR(fsl_edma->membase))
 303                return PTR_ERR(fsl_edma->membase);
 304
 305        fsl_edma_setup_regs(fsl_edma);
 306        regs = &fsl_edma->regs;
 307
 308        if (drvdata->has_dmaclk) {
 309                fsl_edma->dmaclk = devm_clk_get(&pdev->dev, "dma");
 310                if (IS_ERR(fsl_edma->dmaclk)) {
 311                        dev_err(&pdev->dev, "Missing DMA block clock.\n");
 312                        return PTR_ERR(fsl_edma->dmaclk);
 313                }
 314
 315                ret = clk_prepare_enable(fsl_edma->dmaclk);
 316                if (ret) {
 317                        dev_err(&pdev->dev, "DMA clk block failed.\n");
 318                        return ret;
 319                }
 320        }
 321
 322        for (i = 0; i < fsl_edma->drvdata->dmamuxs; i++) {
 323                char clkname[32];
 324
 325                res = platform_get_resource(pdev, IORESOURCE_MEM, 1 + i);
 326                fsl_edma->muxbase[i] = devm_ioremap_resource(&pdev->dev, res);
 327                if (IS_ERR(fsl_edma->muxbase[i])) {
 328                        /* on error: disable all previously enabled clks */
 329                        fsl_disable_clocks(fsl_edma, i);
 330                        return PTR_ERR(fsl_edma->muxbase[i]);
 331                }
 332
 333                sprintf(clkname, "dmamux%d", i);
 334                fsl_edma->muxclk[i] = devm_clk_get(&pdev->dev, clkname);
 335                if (IS_ERR(fsl_edma->muxclk[i])) {
 336                        dev_err(&pdev->dev, "Missing DMAMUX block clock.\n");
 337                        /* on error: disable all previously enabled clks */
 338                        fsl_disable_clocks(fsl_edma, i);
 339                        return PTR_ERR(fsl_edma->muxclk[i]);
 340                }
 341
 342                ret = clk_prepare_enable(fsl_edma->muxclk[i]);
 343                if (ret)
 344                        /* on error: disable all previously enabled clks */
 345                        fsl_disable_clocks(fsl_edma, i);
 346
 347        }
 348
 349        fsl_edma->big_endian = of_property_read_bool(np, "big-endian");
 350
 351        INIT_LIST_HEAD(&fsl_edma->dma_dev.channels);
 352        for (i = 0; i < fsl_edma->n_chans; i++) {
 353                struct fsl_edma_chan *fsl_chan = &fsl_edma->chans[i];
 354
 355                fsl_chan->edma = fsl_edma;
 356                fsl_chan->pm_state = RUNNING;
 357                fsl_chan->slave_id = 0;
 358                fsl_chan->idle = true;
 359                fsl_chan->dma_dir = DMA_NONE;
 360                fsl_chan->vchan.desc_free = fsl_edma_free_desc;
 361                vchan_init(&fsl_chan->vchan, &fsl_edma->dma_dev);
 362
 363                edma_writew(fsl_edma, 0x0, &regs->tcd[i].csr);
 364                fsl_edma_chan_mux(fsl_chan, 0, false);
 365        }
 366
 367        edma_writel(fsl_edma, ~0, regs->intl);
 368        ret = fsl_edma->drvdata->setup_irq(pdev, fsl_edma);
 369        if (ret)
 370                return ret;
 371
 372        dma_cap_set(DMA_PRIVATE, fsl_edma->dma_dev.cap_mask);
 373        dma_cap_set(DMA_SLAVE, fsl_edma->dma_dev.cap_mask);
 374        dma_cap_set(DMA_CYCLIC, fsl_edma->dma_dev.cap_mask);
 375
 376        fsl_edma->dma_dev.dev = &pdev->dev;
 377        fsl_edma->dma_dev.device_alloc_chan_resources
 378                = fsl_edma_alloc_chan_resources;
 379        fsl_edma->dma_dev.device_free_chan_resources
 380                = fsl_edma_free_chan_resources;
 381        fsl_edma->dma_dev.device_tx_status = fsl_edma_tx_status;
 382        fsl_edma->dma_dev.device_prep_slave_sg = fsl_edma_prep_slave_sg;
 383        fsl_edma->dma_dev.device_prep_dma_cyclic = fsl_edma_prep_dma_cyclic;
 384        fsl_edma->dma_dev.device_config = fsl_edma_slave_config;
 385        fsl_edma->dma_dev.device_pause = fsl_edma_pause;
 386        fsl_edma->dma_dev.device_resume = fsl_edma_resume;
 387        fsl_edma->dma_dev.device_terminate_all = fsl_edma_terminate_all;
 388        fsl_edma->dma_dev.device_synchronize = fsl_edma_synchronize;
 389        fsl_edma->dma_dev.device_issue_pending = fsl_edma_issue_pending;
 390
 391        fsl_edma->dma_dev.src_addr_widths = FSL_EDMA_BUSWIDTHS;
 392        fsl_edma->dma_dev.dst_addr_widths = FSL_EDMA_BUSWIDTHS;
 393        fsl_edma->dma_dev.directions = BIT(DMA_DEV_TO_MEM) | BIT(DMA_MEM_TO_DEV);
 394
 395        platform_set_drvdata(pdev, fsl_edma);
 396
 397        ret = dma_async_device_register(&fsl_edma->dma_dev);
 398        if (ret) {
 399                dev_err(&pdev->dev,
 400                        "Can't register Freescale eDMA engine. (%d)\n", ret);
 401                fsl_disable_clocks(fsl_edma, fsl_edma->drvdata->dmamuxs);
 402                return ret;
 403        }
 404
 405        ret = of_dma_controller_register(np, fsl_edma_xlate, fsl_edma);
 406        if (ret) {
 407                dev_err(&pdev->dev,
 408                        "Can't register Freescale eDMA of_dma. (%d)\n", ret);
 409                dma_async_device_unregister(&fsl_edma->dma_dev);
 410                fsl_disable_clocks(fsl_edma, fsl_edma->drvdata->dmamuxs);
 411                return ret;
 412        }
 413
 414        /* enable round robin arbitration */
 415        edma_writel(fsl_edma, EDMA_CR_ERGA | EDMA_CR_ERCA, regs->cr);
 416
 417        return 0;
 418}
 419
 420static int fsl_edma_remove(struct platform_device *pdev)
 421{
 422        struct device_node *np = pdev->dev.of_node;
 423        struct fsl_edma_engine *fsl_edma = platform_get_drvdata(pdev);
 424
 425        fsl_edma_irq_exit(pdev, fsl_edma);
 426        fsl_edma_cleanup_vchan(&fsl_edma->dma_dev);
 427        of_dma_controller_free(np);
 428        dma_async_device_unregister(&fsl_edma->dma_dev);
 429        fsl_disable_clocks(fsl_edma, fsl_edma->drvdata->dmamuxs);
 430
 431        return 0;
 432}
 433
 434static int fsl_edma_suspend_late(struct device *dev)
 435{
 436        struct fsl_edma_engine *fsl_edma = dev_get_drvdata(dev);
 437        struct fsl_edma_chan *fsl_chan;
 438        unsigned long flags;
 439        int i;
 440
 441        for (i = 0; i < fsl_edma->n_chans; i++) {
 442                fsl_chan = &fsl_edma->chans[i];
 443                spin_lock_irqsave(&fsl_chan->vchan.lock, flags);
 444                /* Make sure chan is idle or will force disable. */
 445                if (unlikely(!fsl_chan->idle)) {
 446                        dev_warn(dev, "WARN: There is non-idle channel.");
 447                        fsl_edma_disable_request(fsl_chan);
 448                        fsl_edma_chan_mux(fsl_chan, 0, false);
 449                }
 450
 451                fsl_chan->pm_state = SUSPENDED;
 452                spin_unlock_irqrestore(&fsl_chan->vchan.lock, flags);
 453        }
 454
 455        return 0;
 456}
 457
 458static int fsl_edma_resume_early(struct device *dev)
 459{
 460        struct fsl_edma_engine *fsl_edma = dev_get_drvdata(dev);
 461        struct fsl_edma_chan *fsl_chan;
 462        struct edma_regs *regs = &fsl_edma->regs;
 463        int i;
 464
 465        for (i = 0; i < fsl_edma->n_chans; i++) {
 466                fsl_chan = &fsl_edma->chans[i];
 467                fsl_chan->pm_state = RUNNING;
 468                edma_writew(fsl_edma, 0x0, &regs->tcd[i].csr);
 469                if (fsl_chan->slave_id != 0)
 470                        fsl_edma_chan_mux(fsl_chan, fsl_chan->slave_id, true);
 471        }
 472
 473        edma_writel(fsl_edma, EDMA_CR_ERGA | EDMA_CR_ERCA, regs->cr);
 474
 475        return 0;
 476}
 477
 478/*
 479 * eDMA provides the service to others, so it should be suspend late
 480 * and resume early. When eDMA suspend, all of the clients should stop
 481 * the DMA data transmission and let the channel idle.
 482 */
 483static const struct dev_pm_ops fsl_edma_pm_ops = {
 484        .suspend_late   = fsl_edma_suspend_late,
 485        .resume_early   = fsl_edma_resume_early,
 486};
 487
 488static struct platform_driver fsl_edma_driver = {
 489        .driver         = {
 490                .name   = "fsl-edma",
 491                .of_match_table = fsl_edma_dt_ids,
 492                .pm     = &fsl_edma_pm_ops,
 493        },
 494        .probe          = fsl_edma_probe,
 495        .remove         = fsl_edma_remove,
 496};
 497
 498static int __init fsl_edma_init(void)
 499{
 500        return platform_driver_register(&fsl_edma_driver);
 501}
 502subsys_initcall(fsl_edma_init);
 503
 504static void __exit fsl_edma_exit(void)
 505{
 506        platform_driver_unregister(&fsl_edma_driver);
 507}
 508module_exit(fsl_edma_exit);
 509
 510MODULE_ALIAS("platform:fsl-edma");
 511MODULE_DESCRIPTION("Freescale eDMA engine driver");
 512MODULE_LICENSE("GPL v2");
 513