| .. | .. |
|---|
| 1 | +// SPDX-License-Identifier: GPL-2.0 |
|---|
| 1 | 2 | /* |
|---|
| 2 | 3 | * arch/sh/drivers/dma/dma-sh.c |
|---|
| 3 | 4 | * |
|---|
| .. | .. |
|---|
| 6 | 7 | * Copyright (C) 2000 Takashi YOSHII |
|---|
| 7 | 8 | * Copyright (C) 2003, 2004 Paul Mundt |
|---|
| 8 | 9 | * Copyright (C) 2005 Andriy Skulysh |
|---|
| 9 | | - * |
|---|
| 10 | | - * This file is subject to the terms and conditions of the GNU General Public |
|---|
| 11 | | - * License. See the file "COPYING" in the main directory of this archive |
|---|
| 12 | | - * for more details. |
|---|
| 13 | 10 | */ |
|---|
| 14 | 11 | #include <linux/init.h> |
|---|
| 15 | 12 | #include <linux/interrupt.h> |
|---|
| .. | .. |
|---|
| 22 | 19 | #include <cpu/dma.h> |
|---|
| 23 | 20 | |
|---|
| 24 | 21 | /* |
|---|
| 22 | + * Some of the SoCs feature two DMAC modules. In such a case, the channels are |
|---|
| 23 | + * distributed equally among them. |
|---|
| 24 | + */ |
|---|
| 25 | +#ifdef SH_DMAC_BASE1 |
|---|
| 26 | +#define SH_DMAC_NR_MD_CH (CONFIG_NR_ONCHIP_DMA_CHANNELS / 2) |
|---|
| 27 | +#else |
|---|
| 28 | +#define SH_DMAC_NR_MD_CH CONFIG_NR_ONCHIP_DMA_CHANNELS |
|---|
| 29 | +#endif |
|---|
| 30 | + |
|---|
| 31 | +#define SH_DMAC_CH_SZ 0x10 |
|---|
| 32 | + |
|---|
| 33 | +/* |
|---|
| 25 | 34 | * Define the default configuration for dual address memory-memory transfer. |
|---|
| 26 | 35 | * The 0x400 value represents auto-request, external->external. |
|---|
| 27 | 36 | */ |
|---|
| .. | .. |
|---|
| 32 | 41 | unsigned long base = SH_DMAC_BASE0; |
|---|
| 33 | 42 | |
|---|
| 34 | 43 | #ifdef SH_DMAC_BASE1 |
|---|
| 35 | | - if (chan >= 6) |
|---|
| 44 | + if (chan >= SH_DMAC_NR_MD_CH) |
|---|
| 36 | 45 | base = SH_DMAC_BASE1; |
|---|
| 37 | 46 | #endif |
|---|
| 38 | 47 | |
|---|
| .. | .. |
|---|
| 43 | 52 | { |
|---|
| 44 | 53 | unsigned long base = dma_find_base(chan); |
|---|
| 45 | 54 | |
|---|
| 46 | | - /* Normalize offset calculation */ |
|---|
| 47 | | - if (chan >= 9) |
|---|
| 48 | | - chan -= 6; |
|---|
| 49 | | - if (chan >= 4) |
|---|
| 50 | | - base += 0x10; |
|---|
| 55 | + chan = (chan % SH_DMAC_NR_MD_CH) * SH_DMAC_CH_SZ; |
|---|
| 51 | 56 | |
|---|
| 52 | | - return base + (chan * 0x10); |
|---|
| 57 | + /* DMAOR is placed inside the channel register space. Step over it. */ |
|---|
| 58 | + if (chan >= DMAOR) |
|---|
| 59 | + base += SH_DMAC_CH_SZ; |
|---|
| 60 | + |
|---|
| 61 | + return base + chan; |
|---|
| 53 | 62 | } |
|---|
| 54 | 63 | |
|---|
| 55 | 64 | #ifdef CONFIG_SH_DMA_IRQ_MULTI |
|---|
| .. | .. |
|---|
| 253 | 262 | #define NR_DMAOR 1 |
|---|
| 254 | 263 | #endif |
|---|
| 255 | 264 | |
|---|
| 256 | | -/* |
|---|
| 257 | | - * DMAOR bases are broken out amongst channel groups. DMAOR0 manages |
|---|
| 258 | | - * channels 0 - 5, DMAOR1 6 - 11 (optional). |
|---|
| 259 | | - */ |
|---|
| 260 | | -#define dmaor_read_reg(n) __raw_readw(dma_find_base((n)*6)) |
|---|
| 261 | | -#define dmaor_write_reg(n, data) __raw_writew(data, dma_find_base(n)*6) |
|---|
| 265 | +#define dmaor_read_reg(n) __raw_readw(dma_find_base((n) * \ |
|---|
| 266 | + SH_DMAC_NR_MD_CH) + DMAOR) |
|---|
| 267 | +#define dmaor_write_reg(n, data) __raw_writew(data, \ |
|---|
| 268 | + dma_find_base((n) * \ |
|---|
| 269 | + SH_DMAC_NR_MD_CH) + DMAOR) |
|---|
| 262 | 270 | |
|---|
| 263 | 271 | static inline int dmaor_reset(int no) |
|---|
| 264 | 272 | { |
|---|
| .. | .. |
|---|
| 414 | 422 | |
|---|
| 415 | 423 | MODULE_AUTHOR("Takashi YOSHII, Paul Mundt, Andriy Skulysh"); |
|---|
| 416 | 424 | MODULE_DESCRIPTION("SuperH On-Chip DMAC Support"); |
|---|
| 417 | | -MODULE_LICENSE("GPL"); |
|---|
| 425 | +MODULE_LICENSE("GPL v2"); |
|---|