This source file includes following definitions.
- dma_find_base
- dma_base_addr
- get_dmte_irq
- get_dmte_irq
- calc_xmit_shift
- dma_tei
- sh_dmac_request_dma
- sh_dmac_free_dma
- sh_dmac_configure_channel
- sh_dmac_enable_dma
- sh_dmac_disable_dma
- sh_dmac_xfer_dma
- sh_dmac_get_dma_residue
- dmaor_reset
- get_dma_error_irq
- get_dma_error_irq
- dma_err
- dmae_irq_init
- dmae_irq_free
- dmae_irq_init
- dmae_irq_free
- sh_dmac_init
- sh_dmac_exit
   1 
   2 
   3 
   4 
   5 
   6 
   7 
   8 
   9 
  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 
  23 
  24 
  25 #define RS_DUAL (DM_INC | SM_INC | RS_AUTO | TS_INDEX2VAL(XMIT_SZ_32BIT))
  26 
  27 static 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 
  39 static unsigned long dma_base_addr(unsigned int chan)
  40 {
  41         unsigned long base = dma_find_base(chan);
  42 
  43         
  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
  53 static inline unsigned int get_dmte_irq(unsigned int chan)
  54 {
  55         return chan >= 6 ? DMTE6_IRQ : DMTE0_IRQ;
  56 }
  57 #else
  58 
  59 static 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 
  75 static inline unsigned int get_dmte_irq(unsigned int chan)
  76 {
  77         return dmte_irq_map[chan];
  78 }
  79 #endif
  80 
  81 
  82 
  83 
  84 
  85 
  86 
  87 
  88 
  89 static unsigned int ts_shift[] = TS_SHIFT;
  90 
  91 static 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 
 102 
 103 
 104 
 105 
 106 static 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 
 124 static 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 
 133 static void sh_dmac_free_dma(struct dma_channel *chan)
 134 {
 135         free_irq(get_dmte_irq(chan->chan), chan);
 136 }
 137 
 138 static int
 139 sh_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 
 157 static 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 
 176 static 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 
 191 static int sh_dmac_xfer_dma(struct dma_channel *chan)
 192 {
 193         
 194 
 195 
 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 
 204 
 205 
 206 
 207 
 208 
 209 
 210 
 211 
 212 
 213 
 214 
 215 
 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 
 232 static 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 
 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 
 255 
 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 
 260 static inline int dmaor_reset(int no)
 261 {
 262         unsigned long dmaor = dmaor_read_reg(no);
 263 
 264         
 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         
 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 
 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 
 291 static const char *dmae_name[] = {
 292         "DMAC Address Error0",
 293         "DMAC Address Error1"
 294 };
 295 
 296 #ifdef CONFIG_SH_DMA_IRQ_MULTI
 297 static inline unsigned int get_dma_error_irq(int n)
 298 {
 299         return get_dmte_irq(n * 6);
 300 }
 301 #else
 302 
 303 static unsigned int dmae_irq_map[] = {
 304         DMAE0_IRQ,
 305 
 306 #ifdef DMAE1_IRQ
 307         DMAE1_IRQ,
 308 #endif
 309 };
 310 
 311 static inline unsigned int get_dma_error_irq(int n)
 312 {
 313         return dmae_irq_map[n];
 314 }
 315 #endif
 316 
 317 static 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 
 329 static 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 
 345 static 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
 353 static inline int dmae_irq_init(void)
 354 {
 355         return 0;
 356 }
 357 
 358 static void dmae_irq_free(void)
 359 {
 360 }
 361 #endif
 362 
 363 static 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 
 371 static 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 
 378 static int __init sh_dmac_init(void)
 379 {
 380         struct dma_info *info = &sh_dmac_info;
 381         int i, rc;
 382 
 383         
 384 
 385 
 386         rc = dmae_irq_init();
 387         if (unlikely(rc != 0))
 388                 return rc;
 389 
 390         
 391 
 392 
 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 
 403 static void __exit sh_dmac_exit(void)
 404 {
 405         dmae_irq_free();
 406         unregister_dmac(&sh_dmac_info);
 407 }
 408 
 409 subsys_initcall(sh_dmac_init);
 410 module_exit(sh_dmac_exit);
 411 
 412 MODULE_AUTHOR("Takashi YOSHII, Paul Mundt, Andriy Skulysh");
 413 MODULE_DESCRIPTION("SuperH On-Chip DMAC Support");
 414 MODULE_LICENSE("GPL v2");