OpenCores
URL https://opencores.org/ocsvn/or1k/or1k/trunk

Subversion Repositories or1k

[/] [or1k/] [trunk/] [linux/] [linux-2.4/] [arch/] [sh/] [kernel/] [dma.c] - Blame information for rev 1765

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 1275 phoenix
/*
2
 * arch/sh/kernel/dma.c
3
 *
4
 * Copyright (C) 2000 Takashi YOSHII
5
 *
6
 * PC like DMA API for SuperH's DMAC.
7
 */
8
 
9
#include <linux/config.h>
10
#include <linux/init.h>
11
#include <linux/irq.h>
12
#include <linux/interrupt.h>
13
#include <linux/module.h>
14
 
15
#include <asm/signal.h>
16
#include <asm/dma.h>
17
 
18
static struct dma_info_t *dma_info[MAX_DMA_CHANNELS];
19
static struct dma_info_t *autoinit_info[SH_MAX_DMA_CHANNELS] = {0};
20
static spinlock_t  dma_spin_lock;
21
 
22
static unsigned int calc_chcr(struct dma_info_t *info)
23
{
24
        unsigned int chcr;
25
 
26
        chcr = ( info->mode & DMA_MODE_WRITE )? info->mode_write : info->mode_read;
27
        if( info->mode & DMA_AUTOINIT )
28
                chcr |= CHCR_IE;
29
        return chcr;
30
}
31
 
32
static __inline__ int ts_shift(unsigned long chcr)
33
{
34
        return ((int[]){3,0,1,2,5,0,0,0})[(chcr>>4)&0x000007];
35
}
36
 
37
static void dma_tei(int irq, void *dev_id, struct pt_regs *regs)
38
{
39
        int chan = irq - DMTE_IRQ[0];
40
        struct dma_info_t *info = autoinit_info[chan];
41
 
42
        if( info->mode & DMA_MODE_WRITE )
43
                ctrl_outl(info->mem_addr, SAR[info->chan]);
44
        else
45
                ctrl_outl(info->mem_addr, DAR[info->chan]);
46
 
47
        ctrl_outl(info->count>>ts_shift(calc_chcr(info)), DMATCR[info->chan]);
48
        ctrl_outl(ctrl_inl(CHCR[info->chan])&~CHCR_TE, CHCR[info->chan]);
49
}
50
 
51
static struct irqaction irq_tei = { dma_tei, SA_INTERRUPT, 0, "dma_tei", NULL, NULL};
52
 
53
void setup_dma(unsigned int dmanr, struct dma_info_t *info)
54
{
55
        make_ipr_irq(DMTE_IRQ[info->chan], DMA_IPR_ADDR, DMA_IPR_POS, DMA_PRIORITY);
56
        setup_irq(DMTE_IRQ[info->chan], &irq_tei);
57
        dma_info[dmanr] = info;
58
}
59
 
60
unsigned long claim_dma_lock(void)
61
{
62
        unsigned long flags;
63
        spin_lock_irqsave(&dma_spin_lock, flags);
64
        return flags;
65
}
66
 
67
void release_dma_lock(unsigned long flags)
68
{
69
        spin_unlock_irqrestore(&dma_spin_lock, flags);
70
}
71
 
72
void enable_dma(unsigned int dmanr)
73
{
74
        struct dma_info_t *info = dma_info[dmanr];
75
        ctrl_outl(calc_chcr(info)|CHCR_DE, CHCR[info->chan]);
76
}
77
 
78
void disable_dma(unsigned int dmanr)
79
{
80
        struct dma_info_t *info = dma_info[dmanr];
81
        ctrl_outl(calc_chcr(info)&~CHCR_DE, CHCR[info->chan]);
82
}
83
 
84
void set_dma_mode(unsigned int dmanr, char mode)
85
{
86
        struct dma_info_t *info = dma_info[dmanr];
87
 
88
        info->mode = mode;
89
        set_dma_addr(dmanr, info->mem_addr);
90
        set_dma_count(dmanr, info->count);
91
        autoinit_info[info->chan] = info;
92
}
93
 
94
void set_dma_addr(unsigned int dmanr, unsigned int a)
95
{
96
        struct dma_info_t *info = dma_info[dmanr];
97
        unsigned long sar, dar;
98
 
99
        info->mem_addr = a;
100
        sar = (info->mode & DMA_MODE_WRITE)? info->mem_addr: info->dev_addr;
101
        dar = (info->mode & DMA_MODE_WRITE)? info->dev_addr: info->mem_addr;
102
        ctrl_outl(sar, SAR[info->chan]);
103
        ctrl_outl(dar, DAR[info->chan]);
104
}
105
 
106
void set_dma_count(unsigned int dmanr, unsigned int count)
107
{
108
        struct dma_info_t *info = dma_info[dmanr];
109
        info->count = count;
110
        ctrl_outl(count>>ts_shift(calc_chcr(info)), DMATCR[info->chan]);
111
}
112
 
113
int get_dma_residue(unsigned int dmanr)
114
{
115
        struct dma_info_t *info = dma_info[dmanr];
116
        return ctrl_inl(DMATCR[info->chan])<<ts_shift(calc_chcr(info));
117
}
118
 
119
#if defined(__SH4__)
120
static void dma_err(int irq, void *dev_id, struct pt_regs *regs)
121
{
122
        printk(KERN_WARNING "DMAE: DMAOR=%lx\n",ctrl_inl(DMAOR));
123
        ctrl_outl(ctrl_inl(DMAOR)&~DMAOR_NMIF, DMAOR);
124
        ctrl_outl(ctrl_inl(DMAOR)&~DMAOR_AE, DMAOR);
125
        ctrl_outl(ctrl_inl(DMAOR)|DMAOR_DME, DMAOR);
126
}
127
static struct irqaction irq_err = { dma_err, SA_INTERRUPT, 0, "dma_err", NULL, NULL};
128
#endif
129
 
130
int __init init_dma(void)
131
{
132
#if defined(__SH4__)
133
        make_ipr_irq(DMAE_IRQ, DMA_IPR_ADDR, DMA_IPR_POS, DMA_PRIORITY);
134
        setup_irq(DMAE_IRQ, &irq_err);
135
#endif
136
 
137
        ctrl_outl(DMAOR_DME, DMAOR);
138
        return 0;
139
}
140
 
141
static void __exit exit_dma(void)
142
{
143
#ifdef CONFIG_CPU_SH4
144
        free_irq(DMAE_IRQ);
145
#endif
146
}
147
 
148
module_init(init_dma);
149
module_exit(exit_dma);
150
 
151
MODULE_LICENSE("GPL");
152
 
153
EXPORT_SYMBOL(setup_dma);
154
EXPORT_SYMBOL(claim_dma_lock);
155
EXPORT_SYMBOL(release_dma_lock);
156
EXPORT_SYMBOL(enable_dma);
157
EXPORT_SYMBOL(disable_dma);
158
EXPORT_SYMBOL(set_dma_mode);
159
EXPORT_SYMBOL(set_dma_addr);
160
EXPORT_SYMBOL(set_dma_count);
161
EXPORT_SYMBOL(get_dma_residue);
162
 

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.