1 // SPDX-License-Identifier: GPL-2.0 1 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 * Some of the SoCs feature two DMAC modules. 23 * distributed equally among them. 24 */ 25 #ifdef SH_DMAC_BASE1 26 #define SH_DMAC_NR_MD_CH (CONFIG_NR_ONC 27 #else 28 #define SH_DMAC_NR_MD_CH CONFIG_NR_ONCH 29 #endif 30 31 #define SH_DMAC_CH_SZ 0x10 32 33 /* 34 * Define the default configuration for dual a 35 * The 0x400 value represents auto-request, ex 36 */ 37 #define RS_DUAL (DM_INC | SM_INC | RS_AUTO | T 38 39 static unsigned long dma_find_base(unsigned in 40 { 41 unsigned long base = SH_DMAC_BASE0; 42 43 #ifdef SH_DMAC_BASE1 44 if (chan >= SH_DMAC_NR_MD_CH) 45 base = SH_DMAC_BASE1; 46 #endif 47 48 return base; 49 } 50 51 static unsigned long dma_base_addr(unsigned in 52 { 53 unsigned long base = dma_find_base(cha 54 55 chan = (chan % SH_DMAC_NR_MD_CH) * SH_ 56 57 /* DMAOR is placed inside the channel 58 if (chan >= DMAOR) 59 base += SH_DMAC_CH_SZ; 60 61 return base + chan; 62 } 63 64 #ifdef CONFIG_SH_DMA_IRQ_MULTI 65 static inline unsigned int get_dmte_irq(unsign 66 { 67 return chan >= 6 ? DMTE6_IRQ : DMTE0_I 68 } 69 #else 70 71 static unsigned int dmte_irq_map[] = { 72 DMTE0_IRQ, DMTE0_IRQ + 1, DMTE0_IRQ + 73 74 #ifdef DMTE4_IRQ 75 DMTE4_IRQ, DMTE4_IRQ + 1, 76 #endif 77 78 #ifdef DMTE6_IRQ 79 DMTE6_IRQ, DMTE6_IRQ + 1, 80 #endif 81 82 #ifdef DMTE8_IRQ 83 DMTE8_IRQ, DMTE9_IRQ, DMTE10_IRQ, DMTE 84 #endif 85 }; 86 87 static inline unsigned int get_dmte_irq(unsign 88 { 89 return dmte_irq_map[chan]; 90 } 91 #endif 92 93 /* 94 * We determine the correct shift size based o 95 * for the given channel. Since we know that i 96 * 97 * info->count >> ts_shift[transmit_size] 98 * 99 * iterations to complete the transfer. 100 */ 101 static unsigned int ts_shift[] = TS_SHIFT; 102 103 static inline unsigned int calc_xmit_shift(str 104 { 105 u32 chcr = __raw_readl(dma_base_addr(c 106 int cnt = ((chcr & CHCR_TS_LOW_MASK) > 107 ((chcr & CHCR_TS_HIGH_MASK) >> 108 109 return ts_shift[cnt]; 110 } 111 112 /* 113 * The transfer end interrupt must read the ch 114 * hardware interrupt active condition. 115 * Besides that it needs to waken any waiting 116 * setting up the next transfer. 117 */ 118 static irqreturn_t dma_tei(int irq, void *dev_ 119 { 120 struct dma_channel *chan = dev_id; 121 u32 chcr; 122 123 chcr = __raw_readl(dma_base_addr(chan- 124 125 if (!(chcr & CHCR_TE)) 126 return IRQ_NONE; 127 128 chcr &= ~(CHCR_IE | CHCR_DE); 129 __raw_writel(chcr, (dma_base_addr(chan 130 131 wake_up(&chan->wait_queue); 132 133 return IRQ_HANDLED; 134 } 135 136 static int sh_dmac_request_dma(struct dma_chan 137 { 138 if (unlikely(!(chan->flags & DMA_TEI_C 139 return 0; 140 141 return request_irq(get_dmte_irq(chan-> 142 chan->dev_id, chan) 143 } 144 145 static void sh_dmac_free_dma(struct dma_channe 146 { 147 free_irq(get_dmte_irq(chan->chan), cha 148 } 149 150 static int 151 sh_dmac_configure_channel(struct dma_channel * 152 { 153 if (!chcr) 154 chcr = RS_DUAL | CHCR_IE; 155 156 if (chcr & CHCR_IE) { 157 chcr &= ~CHCR_IE; 158 chan->flags |= DMA_TEI_CAPABLE 159 } else { 160 chan->flags &= ~DMA_TEI_CAPABL 161 } 162 163 __raw_writel(chcr, (dma_base_addr(chan 164 165 chan->flags |= DMA_CONFIGURED; 166 return 0; 167 } 168 169 static void sh_dmac_enable_dma(struct dma_chan 170 { 171 int irq; 172 u32 chcr; 173 174 chcr = __raw_readl(dma_base_addr(chan- 175 chcr |= CHCR_DE; 176 177 if (chan->flags & DMA_TEI_CAPABLE) 178 chcr |= CHCR_IE; 179 180 __raw_writel(chcr, (dma_base_addr(chan 181 182 if (chan->flags & DMA_TEI_CAPABLE) { 183 irq = get_dmte_irq(chan->chan) 184 enable_irq(irq); 185 } 186 } 187 188 static void sh_dmac_disable_dma(struct dma_cha 189 { 190 int irq; 191 u32 chcr; 192 193 if (chan->flags & DMA_TEI_CAPABLE) { 194 irq = get_dmte_irq(chan->chan) 195 disable_irq(irq); 196 } 197 198 chcr = __raw_readl(dma_base_addr(chan- 199 chcr &= ~(CHCR_DE | CHCR_TE | CHCR_IE) 200 __raw_writel(chcr, (dma_base_addr(chan 201 } 202 203 static int sh_dmac_xfer_dma(struct dma_channel 204 { 205 /* 206 * If we haven't pre-configured the ch 207 * the defaults. 208 */ 209 if (unlikely(!(chan->flags & DMA_CONFI 210 sh_dmac_configure_channel(chan 211 212 sh_dmac_disable_dma(chan); 213 214 /* 215 * Single-address mode usage note! 216 * 217 * It's important that we don't accide 218 * (this includes 0) that hasn't been 219 * we're in single-address mode. 220 * 221 * In this case, only one address can 222 * result in a DMA address error inter 223 * which will subsequently halt the tr 224 * 225 * Channel 2 on the Dreamcast is a spe 226 * cascading to the PVR2 DMAC. In this 227 * SAR and DAR, regardless of value, i 228 */ 229 if (chan->sar || (mach_is_dreamcast() 230 chan->chan == PVR2_C 231 __raw_writel(chan->sar, (dma_b 232 if (chan->dar || (mach_is_dreamcast() 233 chan->chan == PVR2_C 234 __raw_writel(chan->dar, (dma_b 235 236 __raw_writel(chan->count >> calc_xmit_ 237 (dma_base_addr(chan->chan) + T 238 239 sh_dmac_enable_dma(chan); 240 241 return 0; 242 } 243 244 static int sh_dmac_get_dma_residue(struct dma_ 245 { 246 if (!(__raw_readl(dma_base_addr(chan-> 247 return 0; 248 249 return __raw_readl(dma_base_addr(chan- 250 << calc_xmit_shift(chan); 251 } 252 253 /* 254 * DMAOR handling 255 */ 256 #if defined(CONFIG_CPU_SUBTYPE_SH7723) || \ 257 defined(CONFIG_CPU_SUBTYPE_SH7724) || \ 258 defined(CONFIG_CPU_SUBTYPE_SH7780) || \ 259 defined(CONFIG_CPU_SUBTYPE_SH7785) 260 #define NR_DMAOR 2 261 #else 262 #define NR_DMAOR 1 263 #endif 264 265 #define dmaor_read_reg(n) __raw_ 266 267 #define dmaor_write_reg(n, data) __raw_ 268 269 270 271 static inline int dmaor_reset(int no) 272 { 273 unsigned long dmaor = dmaor_read_reg(n 274 275 /* Try to clear the error flags first, 276 dmaor &= ~(DMAOR_NMIF | DMAOR_AE); 277 dmaor_write_reg(no, dmaor); 278 279 dmaor |= DMAOR_INIT; 280 dmaor_write_reg(no, dmaor); 281 282 /* See if we got an error again */ 283 if ((dmaor_read_reg(no) & (DMAOR_AE | 284 printk(KERN_ERR "dma-sh: Can't 285 return -EINVAL; 286 } 287 288 return 0; 289 } 290 291 /* 292 * DMAE handling 293 */ 294 #ifdef CONFIG_CPU_SH4 295 296 #if defined(DMAE1_IRQ) 297 #define NR_DMAE 2 298 #else 299 #define NR_DMAE 1 300 #endif 301 302 static const char *dmae_name[] = { 303 "DMAC Address Error0", 304 "DMAC Address Error1" 305 }; 306 307 #ifdef CONFIG_SH_DMA_IRQ_MULTI 308 static inline unsigned int get_dma_error_irq(i 309 { 310 return get_dmte_irq(n * 6); 311 } 312 #else 313 314 static unsigned int dmae_irq_map[] = { 315 DMAE0_IRQ, 316 317 #ifdef DMAE1_IRQ 318 DMAE1_IRQ, 319 #endif 320 }; 321 322 static inline unsigned int get_dma_error_irq(i 323 { 324 return dmae_irq_map[n]; 325 } 326 #endif 327 328 static irqreturn_t dma_err(int irq, void *dumm 329 { 330 int i; 331 332 for (i = 0; i < NR_DMAOR; i++) 333 dmaor_reset(i); 334 335 disable_irq(irq); 336 337 return IRQ_HANDLED; 338 } 339 340 static int dmae_irq_init(void) 341 { 342 int n; 343 344 for (n = 0; n < NR_DMAE; n++) { 345 int i = request_irq(get_dma_er 346 IRQF_SHARE 347 if (unlikely(i < 0)) { 348 printk(KERN_ERR "%s re 349 return i; 350 } 351 } 352 353 return 0; 354 } 355 356 static void dmae_irq_free(void) 357 { 358 int n; 359 360 for (n = 0; n < NR_DMAE; n++) 361 free_irq(get_dma_error_irq(n), 362 } 363 #else 364 static inline int dmae_irq_init(void) 365 { 366 return 0; 367 } 368 369 static void dmae_irq_free(void) 370 { 371 } 372 #endif 373 374 static struct dma_ops sh_dmac_ops = { 375 .request = sh_dmac_request_dma, 376 .free = sh_dmac_free_dma, 377 .get_residue = sh_dmac_get_dma_resi 378 .xfer = sh_dmac_xfer_dma, 379 .configure = sh_dmac_configure_ch 380 }; 381 382 static struct dma_info sh_dmac_info = { 383 .name = "sh_dmac", 384 .nr_channels = CONFIG_NR_ONCHIP_DMA 385 .ops = &sh_dmac_ops, 386 .flags = DMAC_CHANNELS_TEI_CA 387 }; 388 389 static int __init sh_dmac_init(void) 390 { 391 struct dma_info *info = &sh_dmac_info; 392 int i, rc; 393 394 /* 395 * Initialize DMAE, for parts that sup 396 */ 397 rc = dmae_irq_init(); 398 if (unlikely(rc != 0)) 399 return rc; 400 401 /* 402 * Initialize DMAOR, and clean up any 403 * been set. 404 */ 405 for (i = 0; i < NR_DMAOR; i++) { 406 rc = dmaor_reset(i); 407 if (unlikely(rc != 0)) 408 return rc; 409 } 410 411 return register_dmac(info); 412 } 413 414 static void __exit sh_dmac_exit(void) 415 { 416 dmae_irq_free(); 417 unregister_dmac(&sh_dmac_info); 418 } 419 420 subsys_initcall(sh_dmac_init); 421 module_exit(sh_dmac_exit); 422 423 MODULE_AUTHOR("Takashi YOSHII, Paul Mundt, And 424 MODULE_DESCRIPTION("SuperH On-Chip DMAC Suppor 425 MODULE_LICENSE("GPL v2"); 426
Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.