~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/arch/sh/drivers/dma/dma-sh.c

Version: ~ [ linux-6.11-rc3 ] ~ [ linux-6.10.4 ] ~ [ linux-6.9.12 ] ~ [ linux-6.8.12 ] ~ [ linux-6.7.12 ] ~ [ linux-6.6.45 ] ~ [ linux-6.5.13 ] ~ [ linux-6.4.16 ] ~ [ linux-6.3.13 ] ~ [ linux-6.2.16 ] ~ [ linux-6.1.104 ] ~ [ linux-6.0.19 ] ~ [ linux-5.19.17 ] ~ [ linux-5.18.19 ] ~ [ linux-5.17.15 ] ~ [ linux-5.16.20 ] ~ [ linux-5.15.164 ] ~ [ linux-5.14.21 ] ~ [ linux-5.13.19 ] ~ [ linux-5.12.19 ] ~ [ linux-5.11.22 ] ~ [ linux-5.10.223 ] ~ [ linux-5.9.16 ] ~ [ linux-5.8.18 ] ~ [ linux-5.7.19 ] ~ [ linux-5.6.19 ] ~ [ linux-5.5.19 ] ~ [ linux-5.4.281 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.319 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.336 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.337 ] ~ [ linux-4.4.302 ] ~ [ linux-3.10.108 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.9 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

Diff markup

Differences between /arch/sh/drivers/dma/dma-sh.c (Architecture ppc) and /arch/alpha/drivers/dma/dma-sh.c (Architecture alpha)


  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                                                   

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

sflogo.php