dma-sh.c (8905B)
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");