linux/arch/sh/drivers/dma/dma-sh.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0
   2/*
   3 * arch/sh/drivers/dma/dma-sh.c
   4 *
   5 * SuperH On-chip DMAC Support
   6 *
   7 * Copyright (C) 2000 Takashi YOSHII
   8 * Copyright (C) 2003, 2004 Paul Mundt
   9 * Copyright (C) 2005 Andriy Skulysh
  10 */
  11#include <linux/init.h>
  12#include <linux/interrupt.h>
  13#include <linux/module.h>
  14#include <linux/io.h>
  15#include <mach-dreamcast/mach/dma.h>
  16#include <asm/dma.h>
  17#include <asm/dma-register.h>
  18#include <cpu/dma-register.h>
  19#include <cpu/dma.h>
  20
  21/*
  22 * Define the default configuration for dual address memory-memory transfer.
  23 * The 0x400 value represents auto-request, external->external.
  24 */
  25#define RS_DUAL (DM_INC | SM_INC | RS_AUTO | TS_INDEX2VAL(XMIT_SZ_32BIT))
  26
  27static unsigned long dma_find_base(unsigned int chan)
  28{
  29        unsigned long base = SH_DMAC_BASE0;
  30
  31#ifdef SH_DMAC_BASE1
  32        if (chan >= 6)
  33                base = SH_DMAC_BASE1;
  34#endif
  35
  36        return base;
  37}
  38
  39static unsigned long dma_base_addr(unsigned int chan)
  40{
  41        unsigned long base = dma_find_base(chan);
  42
  43        /* Normalize offset calculation */
  44        if (chan >= 9)
  45                chan -= 6;
  46        if (chan >= 4)
  47                base += 0x10;
  48
  49        return base + (chan * 0x10);
  50}
  51
  52#ifdef CONFIG_SH_DMA_IRQ_MULTI
  53static inline unsigned int get_dmte_irq(unsigned int chan)
  54{
  55        return chan >= 6 ? DMTE6_IRQ : DMTE0_IRQ;
  56}
  57#else
  58
  59static unsigned int dmte_irq_map[] = {
  60        DMTE0_IRQ, DMTE0_IRQ + 1, DMTE0_IRQ + 2, DMTE0_IRQ + 3,
  61
  62#ifdef DMTE4_IRQ
  63        DMTE4_IRQ, DMTE4_IRQ + 1,
  64#endif
  65
  66#ifdef DMTE6_IRQ
  67        DMTE6_IRQ, DMTE6_IRQ + 1,
  68#endif
  69
  70#ifdef DMTE8_IRQ
  71        DMTE8_IRQ, DMTE9_IRQ, DMTE10_IRQ, DMTE11_IRQ,
  72#endif
  73};
  74
  75static inline unsigned int get_dmte_irq(unsigned int chan)
  76{
  77        return dmte_irq_map[chan];
  78}
  79#endif
  80
  81/*
  82 * We determine the correct shift size based off of the CHCR transmit size
  83 * for the given channel. Since we know that it will take:
  84 *
  85 *      info->count >> ts_shift[transmit_size]
  86 *
  87 * iterations to complete the transfer.
  88 */
  89static unsigned int ts_shift[] = TS_SHIFT;
  90
  91static inline unsigned int calc_xmit_shift(struct dma_channel *chan)
  92{
  93        u32 chcr = __raw_readl(dma_base_addr(chan->chan) + CHCR);
  94        int cnt = ((chcr & CHCR_TS_LOW_MASK) >> CHCR_TS_LOW_SHIFT) |
  95                ((chcr & CHCR_TS_HIGH_MASK) >> CHCR_TS_HIGH_SHIFT);
  96
  97        return ts_shift[cnt];
  98}
  99
 100/*
 101 * The transfer end interrupt must read the chcr register to end the
 102 * hardware interrupt active condition.
 103 * Besides that it needs to waken any waiting process, which should handle
 104 * setting up the next transfer.
 105 */
 106static irqreturn_t dma_tei(int irq, void *dev_id)
 107{
 108        struct dma_channel *chan = dev_id;
 109        u32 chcr;
 110
 111        chcr = __raw_readl(dma_base_addr(chan->chan) + CHCR);
 112
 113        if (!(chcr & CHCR_TE))
 114                return IRQ_NONE;
 115
 116        chcr &= ~(CHCR_IE | CHCR_DE);
 117        __raw_writel(chcr, (dma_base_addr(chan->chan) + CHCR));
 118
 119        wake_up(&chan->wait_queue);
 120
 121        return IRQ_HANDLED;
 122}
 123
 124static int sh_dmac_request_dma(struct dma_channel *chan)
 125{
 126        if (unlikely(!(chan->flags & DMA_TEI_CAPABLE)))
 127                return 0;
 128
 129        return request_irq(get_dmte_irq(chan->chan), dma_tei, IRQF_SHARED,
 130                           chan->dev_id, chan);
 131}
 132
 133static void sh_dmac_free_dma(struct dma_channel *chan)
 134{
 135        free_irq(get_dmte_irq(chan->chan), chan);
 136}
 137
 138static int
 139sh_dmac_configure_channel(struct dma_channel *chan, unsigned long chcr)
 140{
 141        if (!chcr)
 142                chcr = RS_DUAL | CHCR_IE;
 143
 144        if (chcr & CHCR_IE) {
 145                chcr &= ~CHCR_IE;
 146                chan->flags |= DMA_TEI_CAPABLE;
 147        } else {
 148                chan->flags &= ~DMA_TEI_CAPABLE;
 149        }
 150
 151        __raw_writel(chcr, (dma_base_addr(chan->chan) + CHCR));
 152
 153        chan->flags |= DMA_CONFIGURED;
 154        return 0;
 155}
 156
 157static void sh_dmac_enable_dma(struct dma_channel *chan)
 158{
 159        int irq;
 160        u32 chcr;
 161
 162        chcr = __raw_readl(dma_base_addr(chan->chan) + CHCR);
 163        chcr |= CHCR_DE;
 164
 165        if (chan->flags & DMA_TEI_CAPABLE)
 166                chcr |= CHCR_IE;
 167
 168        __raw_writel(chcr, (dma_base_addr(chan->chan) + CHCR));
 169
 170        if (chan->flags & DMA_TEI_CAPABLE) {
 171                irq = get_dmte_irq(chan->chan);
 172                enable_irq(irq);
 173        }
 174}
 175
 176static void sh_dmac_disable_dma(struct dma_channel *chan)
 177{
 178        int irq;
 179        u32 chcr;
 180
 181        if (chan->flags & DMA_TEI_CAPABLE) {
 182                irq = get_dmte_irq(chan->chan);
 183                disable_irq(irq);
 184        }
 185
 186        chcr = __raw_readl(dma_base_addr(chan->chan) + CHCR);
 187        chcr &= ~(CHCR_DE | CHCR_TE | CHCR_IE);
 188        __raw_writel(chcr, (dma_base_addr(chan->chan) + CHCR));
 189}
 190
 191static int sh_dmac_xfer_dma(struct dma_channel *chan)
 192{
 193        /*
 194         * If we haven't pre-configured the channel with special flags, use
 195         * the defaults.
 196         */
 197        if (unlikely(!(chan->flags & DMA_CONFIGURED)))
 198                sh_dmac_configure_channel(chan, 0);
 199
 200        sh_dmac_disable_dma(chan);
 201
 202        /*
 203         * Single-address mode usage note!
 204         *
 205         * It's important that we don't accidentally write any value to SAR/DAR
 206         * (this includes 0) that hasn't been directly specified by the user if
 207         * we're in single-address mode.
 208         *
 209         * In this case, only one address can be defined, anything else will
 210         * result in a DMA address error interrupt (at least on the SH-4),
 211         * which will subsequently halt the transfer.
 212         *
 213         * Channel 2 on the Dreamcast is a special case, as this is used for
 214         * cascading to the PVR2 DMAC. In this case, we still need to write
 215         * SAR and DAR, regardless of value, in order for cascading to work.
 216         */
 217        if (chan->sar || (mach_is_dreamcast() &&
 218                          chan->chan == PVR2_CASCADE_CHAN))
 219                __raw_writel(chan->sar, (dma_base_addr(chan->chan) + SAR));
 220        if (chan->dar || (mach_is_dreamcast() &&
 221                          chan->chan == PVR2_CASCADE_CHAN))
 222                __raw_writel(chan->dar, (dma_base_addr(chan->chan) + DAR));
 223
 224        __raw_writel(chan->count >> calc_xmit_shift(chan),
 225                (dma_base_addr(chan->chan) + TCR));
 226
 227        sh_dmac_enable_dma(chan);
 228
 229        return 0;
 230}
 231
 232static int sh_dmac_get_dma_residue(struct dma_channel *chan)
 233{
 234        if (!(__raw_readl(dma_base_addr(chan->chan) + CHCR) & CHCR_DE))
 235                return 0;
 236
 237        return __raw_readl(dma_base_addr(chan->chan) + TCR)
 238                 << calc_xmit_shift(chan);
 239}
 240
 241/*
 242 * DMAOR handling
 243 */
 244#if defined(CONFIG_CPU_SUBTYPE_SH7723)  || \
 245    defined(CONFIG_CPU_SUBTYPE_SH7724)  || \
 246    defined(CONFIG_CPU_SUBTYPE_SH7780)  || \
 247    defined(CONFIG_CPU_SUBTYPE_SH7785)
 248#define NR_DMAOR        2
 249#else
 250#define NR_DMAOR        1
 251#endif
 252
 253/*
 254 * DMAOR bases are broken out amongst channel groups. DMAOR0 manages
 255 * channels 0 - 5, DMAOR1 6 - 11 (optional).
 256 */
 257#define dmaor_read_reg(n)               __raw_readw(dma_find_base((n)*6))
 258#define dmaor_write_reg(n, data)        __raw_writew(data, dma_find_base(n)*6)
 259
 260static inline int dmaor_reset(int no)
 261{
 262        unsigned long dmaor = dmaor_read_reg(no);
 263
 264        /* Try to clear the error flags first, incase they are set */
 265        dmaor &= ~(DMAOR_NMIF | DMAOR_AE);
 266        dmaor_write_reg(no, dmaor);
 267
 268        dmaor |= DMAOR_INIT;
 269        dmaor_write_reg(no, dmaor);
 270
 271        /* See if we got an error again */
 272        if ((dmaor_read_reg(no) & (DMAOR_AE | DMAOR_NMIF))) {
 273                printk(KERN_ERR "dma-sh: Can't initialize DMAOR.\n");
 274                return -EINVAL;
 275        }
 276
 277        return 0;
 278}
 279
 280/*
 281 * DMAE handling
 282 */
 283#ifdef CONFIG_CPU_SH4
 284
 285#if defined(DMAE1_IRQ)
 286#define NR_DMAE         2
 287#else
 288#define NR_DMAE         1
 289#endif
 290
 291static const char *dmae_name[] = {
 292        "DMAC Address Error0",
 293        "DMAC Address Error1"
 294};
 295
 296#ifdef CONFIG_SH_DMA_IRQ_MULTI
 297static inline unsigned int get_dma_error_irq(int n)
 298{
 299        return get_dmte_irq(n * 6);
 300}
 301#else
 302
 303static unsigned int dmae_irq_map[] = {
 304        DMAE0_IRQ,
 305
 306#ifdef DMAE1_IRQ
 307        DMAE1_IRQ,
 308#endif
 309};
 310
 311static inline unsigned int get_dma_error_irq(int n)
 312{
 313        return dmae_irq_map[n];
 314}
 315#endif
 316
 317static irqreturn_t dma_err(int irq, void *dummy)
 318{
 319        int i;
 320
 321        for (i = 0; i < NR_DMAOR; i++)
 322                dmaor_reset(i);
 323
 324        disable_irq(irq);
 325
 326        return IRQ_HANDLED;
 327}
 328
 329static int dmae_irq_init(void)
 330{
 331        int n;
 332
 333        for (n = 0; n < NR_DMAE; n++) {
 334                int i = request_irq(get_dma_error_irq(n), dma_err,
 335                                    IRQF_SHARED, dmae_name[n], (void *)dmae_name[n]);
 336                if (unlikely(i < 0)) {
 337                        printk(KERN_ERR "%s request_irq fail\n", dmae_name[n]);
 338                        return i;
 339                }
 340        }
 341
 342        return 0;
 343}
 344
 345static void dmae_irq_free(void)
 346{
 347        int n;
 348
 349        for (n = 0; n < NR_DMAE; n++)
 350                free_irq(get_dma_error_irq(n), NULL);
 351}
 352#else
 353static inline int dmae_irq_init(void)
 354{
 355        return 0;
 356}
 357
 358static void dmae_irq_free(void)
 359{
 360}
 361#endif
 362
 363static struct dma_ops sh_dmac_ops = {
 364        .request        = sh_dmac_request_dma,
 365        .free           = sh_dmac_free_dma,
 366        .get_residue    = sh_dmac_get_dma_residue,
 367        .xfer           = sh_dmac_xfer_dma,
 368        .configure      = sh_dmac_configure_channel,
 369};
 370
 371static struct dma_info sh_dmac_info = {
 372        .name           = "sh_dmac",
 373        .nr_channels    = CONFIG_NR_ONCHIP_DMA_CHANNELS,
 374        .ops            = &sh_dmac_ops,
 375        .flags          = DMAC_CHANNELS_TEI_CAPABLE,
 376};
 377
 378static int __init sh_dmac_init(void)
 379{
 380        struct dma_info *info = &sh_dmac_info;
 381        int i, rc;
 382
 383        /*
 384         * Initialize DMAE, for parts that support it.
 385         */
 386        rc = dmae_irq_init();
 387        if (unlikely(rc != 0))
 388                return rc;
 389
 390        /*
 391         * Initialize DMAOR, and clean up any error flags that may have
 392         * been set.
 393         */
 394        for (i = 0; i < NR_DMAOR; i++) {
 395                rc = dmaor_reset(i);
 396                if (unlikely(rc != 0))
 397                        return rc;
 398        }
 399
 400        return register_dmac(info);
 401}
 402
 403static void __exit sh_dmac_exit(void)
 404{
 405        dmae_irq_free();
 406        unregister_dmac(&sh_dmac_info);
 407}
 408
 409subsys_initcall(sh_dmac_init);
 410module_exit(sh_dmac_exit);
 411
 412MODULE_AUTHOR("Takashi YOSHII, Paul Mundt, Andriy Skulysh");
 413MODULE_DESCRIPTION("SuperH On-Chip DMAC Support");
 414MODULE_LICENSE("GPL v2");
 415