Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

[PATCH] sh: DMA updates

This extends the current SH DMA API somewhat to support a proper virtual
channel abstraction, and also works to represent this through the driver model
by giving each DMAC its own platform device.

There's also a few other minor changes to support a few new CPU subtypes, and
make TEI generation for the SH DMAC configurable.

Signed-off-by: Paul Mundt <lethal@linux-sh.org>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>

authored by

Paul Mundt and committed by
Linus Torvalds
0d831770 0025835c

+293 -122
+37 -14
arch/sh/drivers/dma/dma-api.c
··· 3 3 * 4 4 * SuperH-specific DMA management API 5 5 * 6 - * Copyright (C) 2003, 2004 Paul Mundt 6 + * Copyright (C) 2003, 2004, 2005 Paul Mundt 7 7 * 8 8 * This file is subject to the terms and conditions of the GNU General Public 9 9 * License. See the file "COPYING" in the main directory of this archive ··· 15 15 #include <linux/spinlock.h> 16 16 #include <linux/proc_fs.h> 17 17 #include <linux/list.h> 18 + #include <linux/platform_device.h> 18 19 #include <asm/dma.h> 19 20 20 21 DEFINE_SPINLOCK(dma_spin_lock); ··· 56 55 57 56 struct dma_info *get_dma_info(unsigned int chan) 58 57 { 59 - struct list_head *pos, *tmp; 58 + struct dma_info *info; 60 59 unsigned int total = 0; 61 60 62 61 /* 63 62 * Look for each DMAC's range to determine who the owner of 64 63 * the channel is. 65 64 */ 66 - list_for_each_safe(pos, tmp, &registered_dmac_list) { 67 - struct dma_info *info = list_entry(pos, struct dma_info, list); 68 - 65 + list_for_each_entry(info, &registered_dmac_list, list) { 69 66 total += info->nr_channels; 70 67 if (chan > total) 71 68 continue; ··· 72 73 } 73 74 74 75 return NULL; 76 + } 77 + 78 + static unsigned int get_nr_channels(void) 79 + { 80 + struct dma_info *info; 81 + unsigned int nr = 0; 82 + 83 + if (unlikely(list_empty(&registered_dmac_list))) 84 + return nr; 85 + 86 + list_for_each_entry(info, &registered_dmac_list, list) 87 + nr += info->nr_channels; 88 + 89 + return nr; 75 90 } 76 91 77 92 struct dma_channel *get_dma_channel(unsigned int chan) ··· 186 173 static int dma_read_proc(char *buf, char **start, off_t off, 187 174 int len, int *eof, void *data) 188 175 { 189 - struct list_head *pos, *tmp; 176 + struct dma_info *info; 190 177 char *p = buf; 191 178 192 179 if (list_empty(&registered_dmac_list)) ··· 195 182 /* 196 183 * Iterate over each registered DMAC 197 184 */ 198 - list_for_each_safe(pos, tmp, &registered_dmac_list) { 199 - struct dma_info *info = list_entry(pos, struct dma_info, list); 185 + list_for_each_entry(info, &registered_dmac_list, list) { 200 186 int i; 201 187 202 188 /* ··· 217 205 #endif 218 206 219 207 220 - int __init register_dmac(struct dma_info *info) 208 + int register_dmac(struct dma_info *info) 221 209 { 222 - int i; 210 + unsigned int total_channels, i; 223 211 224 212 INIT_LIST_HEAD(&info->list); 225 213 ··· 228 216 info->nr_channels > 1 ? "s" : ""); 229 217 230 218 BUG_ON((info->flags & DMAC_CHANNELS_CONFIGURED) && !info->channels); 219 + 220 + info->pdev = platform_device_register_simple((char *)info->name, -1, 221 + NULL, 0); 222 + if (IS_ERR(info->pdev)) 223 + return PTR_ERR(info->pdev); 231 224 232 225 /* 233 226 * Don't touch pre-configured channels ··· 249 232 memset(info->channels, 0, size); 250 233 } 251 234 235 + total_channels = get_nr_channels(); 252 236 for (i = 0; i < info->nr_channels; i++) { 253 237 struct dma_channel *chan = info->channels + i; 254 238 255 239 chan->chan = i; 240 + chan->vchan = i + total_channels; 256 241 257 242 memcpy(chan->dev_id, "Unused", 7); 258 243 ··· 264 245 init_MUTEX(&chan->sem); 265 246 init_waitqueue_head(&chan->wait_queue); 266 247 267 - #ifdef CONFIG_SYSFS 268 - dma_create_sysfs_files(chan); 269 - #endif 248 + dma_create_sysfs_files(chan, info); 270 249 } 271 250 272 251 list_add(&info->list, &registered_dmac_list); ··· 272 255 return 0; 273 256 } 274 257 275 - void __exit unregister_dmac(struct dma_info *info) 258 + void unregister_dmac(struct dma_info *info) 276 259 { 260 + unsigned int i; 261 + 262 + for (i = 0; i < info->nr_channels; i++) 263 + dma_remove_sysfs_files(info->channels + i, info); 264 + 277 265 if (!(info->flags & DMAC_CHANNELS_CONFIGURED)) 278 266 kfree(info->channels); 279 267 280 268 list_del(&info->list); 269 + platform_device_unregister(info->pdev); 281 270 } 282 271 283 272 static int __init dma_api_init(void)
+2 -1
arch/sh/drivers/dma/dma-g2.c
··· 140 140 }; 141 141 142 142 static struct dma_info g2_dma_info = { 143 - .name = "G2 DMA", 143 + .name = "g2_dmac", 144 144 .nr_channels = 4, 145 145 .ops = &g2_dma_ops, 146 146 .flags = DMAC_CHANNELS_TEI_CAPABLE, ··· 160 160 static void __exit g2_dma_exit(void) 161 161 { 162 162 free_irq(HW_EVENT_G2_DMA, 0); 163 + unregister_dmac(&g2_dma_info); 163 164 } 164 165 165 166 subsys_initcall(g2_dma_init);
+10 -10
arch/sh/drivers/dma/dma-isa.c
··· 25 25 * such, this code is meant for only the simplest of tasks (and shouldn't be 26 26 * used in any new drivers at all). 27 27 * 28 - * It should also be noted that various functions here are labelled as 29 - * being deprecated. This is due to the fact that the ops->xfer() method is 30 - * the preferred way of doing things (as well as just grabbing the spinlock 31 - * directly). As such, any users of this interface will be warned rather 32 - * loudly. 28 + * NOTE: ops->xfer() is the preferred way of doing things. However, there 29 + * are some users of the ISA DMA API that exist in common code that we 30 + * don't necessarily want to go out of our way to break, so we still 31 + * allow for some compatability at that level. Any new code is strongly 32 + * advised to run far away from the ISA DMA API and use the SH DMA API 33 + * directly. 33 34 */ 34 - 35 - unsigned long __deprecated claim_dma_lock(void) 35 + unsigned long claim_dma_lock(void) 36 36 { 37 37 unsigned long flags; 38 38 ··· 42 42 } 43 43 EXPORT_SYMBOL(claim_dma_lock); 44 44 45 - void __deprecated release_dma_lock(unsigned long flags) 45 + void release_dma_lock(unsigned long flags) 46 46 { 47 47 spin_unlock_irqrestore(&dma_spin_lock, flags); 48 48 } 49 49 EXPORT_SYMBOL(release_dma_lock); 50 50 51 - void __deprecated disable_dma(unsigned int chan) 51 + void disable_dma(unsigned int chan) 52 52 { 53 53 /* Nothing */ 54 54 } 55 55 EXPORT_SYMBOL(disable_dma); 56 56 57 - void __deprecated enable_dma(unsigned int chan) 57 + void enable_dma(unsigned int chan) 58 58 { 59 59 struct dma_info *info = get_dma_info(chan); 60 60 struct dma_channel *channel = &info->channels[chan];
+2 -1
arch/sh/drivers/dma/dma-pvr2.c
··· 80 80 }; 81 81 82 82 static struct dma_info pvr2_dma_info = { 83 - .name = "PowerVR 2 DMA", 83 + .name = "pvr2_dmac", 84 84 .nr_channels = 1, 85 85 .ops = &pvr2_dma_ops, 86 86 .flags = DMAC_CHANNELS_TEI_CAPABLE, ··· 98 98 { 99 99 free_dma(PVR2_CASCADE_CHAN); 100 100 free_irq(HW_EVENT_PVR2_DMA, 0); 101 + unregister_dmac(&pvr2_dma_info); 101 102 } 102 103 103 104 subsys_initcall(pvr2_dma_init);
+83 -53
arch/sh/drivers/dma/dma-sh.c
··· 5 5 * 6 6 * Copyright (C) 2000 Takashi YOSHII 7 7 * Copyright (C) 2003, 2004 Paul Mundt 8 + * Copyright (C) 2005 Andriy Skulysh 8 9 * 9 10 * This file is subject to the terms and conditions of the GNU General Public 10 11 * License. See the file "COPYING" in the main directory of this archive ··· 17 16 #include <linux/irq.h> 18 17 #include <linux/interrupt.h> 19 18 #include <linux/module.h> 19 + #include <asm/dreamcast/dma.h> 20 20 #include <asm/signal.h> 21 21 #include <asm/irq.h> 22 22 #include <asm/dma.h> 23 23 #include <asm/io.h> 24 24 #include "dma-sh.h" 25 25 26 - /* 27 - * The SuperH DMAC supports a number of transmit sizes, we list them here, 28 - * with their respective values as they appear in the CHCR registers. 29 - * 30 - * Defaults to a 64-bit transfer size. 31 - */ 32 - enum { 33 - XMIT_SZ_64BIT, 34 - XMIT_SZ_8BIT, 35 - XMIT_SZ_16BIT, 36 - XMIT_SZ_32BIT, 37 - XMIT_SZ_256BIT, 38 - }; 39 - 40 - /* 41 - * The DMA count is defined as the number of bytes to transfer. 42 - */ 43 - static unsigned int ts_shift[] = { 44 - [XMIT_SZ_64BIT] = 3, 45 - [XMIT_SZ_8BIT] = 0, 46 - [XMIT_SZ_16BIT] = 1, 47 - [XMIT_SZ_32BIT] = 2, 48 - [XMIT_SZ_256BIT] = 5, 49 - }; 50 - 51 26 static inline unsigned int get_dmte_irq(unsigned int chan) 52 27 { 53 - unsigned int irq; 28 + unsigned int irq = 0; 54 29 55 30 /* 56 31 * Normally we could just do DMTE0_IRQ + chan outright, though in the 57 32 * case of the 7751R, the DMTE IRQs for channels > 4 start right above 58 33 * the SCIF 59 34 */ 60 - 61 35 if (chan < 4) { 62 36 irq = DMTE0_IRQ + chan; 63 37 } else { 38 + #ifdef DMTE4_IRQ 64 39 irq = DMTE4_IRQ + chan - 4; 40 + #endif 65 41 } 66 42 67 43 return irq; ··· 56 78 { 57 79 u32 chcr = ctrl_inl(CHCR[chan->chan]); 58 80 59 - chcr >>= 4; 60 - 61 - return ts_shift[chcr & 0x0007]; 81 + return ts_shift[(chcr & CHCR_TS_MASK)>>CHCR_TS_SHIFT]; 62 82 } 63 83 64 84 /* ··· 85 109 86 110 static int sh_dmac_request_dma(struct dma_channel *chan) 87 111 { 112 + char name[32]; 113 + 114 + snprintf(name, sizeof(name), "DMAC Transfer End (Channel %d)", 115 + chan->chan); 116 + 88 117 return request_irq(get_dmte_irq(chan->chan), dma_tei, 89 - SA_INTERRUPT, "DMAC Transfer End", chan); 118 + SA_INTERRUPT, name, chan); 90 119 } 91 120 92 121 static void sh_dmac_free_dma(struct dma_channel *chan) ··· 99 118 free_irq(get_dmte_irq(chan->chan), chan); 100 119 } 101 120 102 - static void sh_dmac_configure_channel(struct dma_channel *chan, unsigned long chcr) 121 + static void 122 + sh_dmac_configure_channel(struct dma_channel *chan, unsigned long chcr) 103 123 { 104 124 if (!chcr) 105 - chcr = RS_DUAL; 125 + chcr = RS_DUAL | CHCR_IE; 126 + 127 + if (chcr & CHCR_IE) { 128 + chcr &= ~CHCR_IE; 129 + chan->flags |= DMA_TEI_CAPABLE; 130 + } else { 131 + chan->flags &= ~DMA_TEI_CAPABLE; 132 + } 106 133 107 134 ctrl_outl(chcr, CHCR[chan->chan]); 108 135 ··· 119 130 120 131 static void sh_dmac_enable_dma(struct dma_channel *chan) 121 132 { 122 - int irq = get_dmte_irq(chan->chan); 133 + int irq; 123 134 u32 chcr; 124 135 125 136 chcr = ctrl_inl(CHCR[chan->chan]); 126 - chcr |= CHCR_DE | CHCR_IE; 137 + chcr |= CHCR_DE; 138 + 139 + if (chan->flags & DMA_TEI_CAPABLE) 140 + chcr |= CHCR_IE; 141 + 127 142 ctrl_outl(chcr, CHCR[chan->chan]); 128 143 129 - enable_irq(irq); 144 + if (chan->flags & DMA_TEI_CAPABLE) { 145 + irq = get_dmte_irq(chan->chan); 146 + enable_irq(irq); 147 + } 130 148 } 131 149 132 150 static void sh_dmac_disable_dma(struct dma_channel *chan) 133 151 { 134 - int irq = get_dmte_irq(chan->chan); 152 + int irq; 135 153 u32 chcr; 136 154 137 - disable_irq(irq); 155 + if (chan->flags & DMA_TEI_CAPABLE) { 156 + irq = get_dmte_irq(chan->chan); 157 + disable_irq(irq); 158 + } 138 159 139 160 chcr = ctrl_inl(CHCR[chan->chan]); 140 161 chcr &= ~(CHCR_DE | CHCR_TE | CHCR_IE); ··· 157 158 * If we haven't pre-configured the channel with special flags, use 158 159 * the defaults. 159 160 */ 160 - if (!(chan->flags & DMA_CONFIGURED)) 161 + if (unlikely(!(chan->flags & DMA_CONFIGURED))) 161 162 sh_dmac_configure_channel(chan, 0); 162 163 163 164 sh_dmac_disable_dma(chan); ··· 177 178 * cascading to the PVR2 DMAC. In this case, we still need to write 178 179 * SAR and DAR, regardless of value, in order for cascading to work. 179 180 */ 180 - if (chan->sar || (mach_is_dreamcast() && chan->chan == 2)) 181 + if (chan->sar || (mach_is_dreamcast() && 182 + chan->chan == PVR2_CASCADE_CHAN)) 181 183 ctrl_outl(chan->sar, SAR[chan->chan]); 182 - if (chan->dar || (mach_is_dreamcast() && chan->chan == 2)) 184 + if (chan->dar || (mach_is_dreamcast() && 185 + chan->chan == PVR2_CASCADE_CHAN)) 183 186 ctrl_outl(chan->dar, DAR[chan->chan]); 184 187 185 188 ctrl_outl(chan->count >> calc_xmit_shift(chan), DMATCR[chan->chan]); ··· 199 198 return ctrl_inl(DMATCR[chan->chan]) << calc_xmit_shift(chan); 200 199 } 201 200 201 + #ifdef CONFIG_CPU_SUBTYPE_SH7780 202 + #define dmaor_read_reg() ctrl_inw(DMAOR) 203 + #define dmaor_write_reg(data) ctrl_outw(data, DMAOR) 204 + #else 205 + #define dmaor_read_reg() ctrl_inl(DMAOR) 206 + #define dmaor_write_reg(data) ctrl_outl(data, DMAOR) 207 + #endif 208 + 209 + static inline int dmaor_reset(void) 210 + { 211 + unsigned long dmaor = dmaor_read_reg(); 212 + 213 + /* Try to clear the error flags first, incase they are set */ 214 + dmaor &= ~(DMAOR_NMIF | DMAOR_AE); 215 + dmaor_write_reg(dmaor); 216 + 217 + dmaor |= DMAOR_INIT; 218 + dmaor_write_reg(dmaor); 219 + 220 + /* See if we got an error again */ 221 + if ((dmaor_read_reg() & (DMAOR_AE | DMAOR_NMIF))) { 222 + printk(KERN_ERR "dma-sh: Can't initialize DMAOR.\n"); 223 + return -EINVAL; 224 + } 225 + 226 + return 0; 227 + } 228 + 202 229 #if defined(CONFIG_CPU_SH4) 203 230 static irqreturn_t dma_err(int irq, void *dev_id, struct pt_regs *regs) 204 231 { 205 - unsigned long dmaor = ctrl_inl(DMAOR); 206 - 207 - printk("DMAE: DMAOR=%lx\n", dmaor); 208 - 209 - ctrl_outl(ctrl_inl(DMAOR)&~DMAOR_NMIF, DMAOR); 210 - ctrl_outl(ctrl_inl(DMAOR)&~DMAOR_AE, DMAOR); 211 - ctrl_outl(ctrl_inl(DMAOR)|DMAOR_DME, DMAOR); 212 - 232 + dmaor_reset(); 213 233 disable_irq(irq); 214 234 215 235 return IRQ_HANDLED; ··· 246 224 }; 247 225 248 226 static struct dma_info sh_dmac_info = { 249 - .name = "SuperH DMAC", 250 - .nr_channels = 4, 227 + .name = "sh_dmac", 228 + .nr_channels = CONFIG_NR_ONCHIP_DMA_CHANNELS, 251 229 .ops = &sh_dmac_ops, 252 230 .flags = DMAC_CHANNELS_TEI_CAPABLE, 253 231 }; ··· 270 248 make_ipr_irq(irq, DMA_IPR_ADDR, DMA_IPR_POS, DMA_PRIORITY); 271 249 } 272 250 273 - ctrl_outl(0x8000 | DMAOR_DME, DMAOR); 251 + /* 252 + * Initialize DMAOR, and clean up any error flags that may have 253 + * been set. 254 + */ 255 + i = dmaor_reset(); 256 + if (i < 0) 257 + return i; 274 258 275 259 return register_dmac(info); 276 260 } ··· 286 258 #ifdef CONFIG_CPU_SH4 287 259 free_irq(DMAE_IRQ, 0); 288 260 #endif 261 + unregister_dmac(&sh_dmac_info); 289 262 } 290 263 291 264 subsys_initcall(sh_dmac_init); 292 265 module_exit(sh_dmac_exit); 293 266 267 + MODULE_AUTHOR("Takashi YOSHII, Paul Mundt, Andriy Skulysh"); 268 + MODULE_DESCRIPTION("SuperH On-Chip DMAC Support"); 294 269 MODULE_LICENSE("GPL"); 295 -
+33 -11
arch/sh/drivers/dma/dma-sh.h
··· 11 11 #ifndef __DMA_SH_H 12 12 #define __DMA_SH_H 13 13 14 + #include <asm/cpu/dma.h> 15 + 14 16 /* Definitions for the SuperH DMAC */ 15 17 #define REQ_L 0x00000000 16 18 #define REQ_E 0x00080000 ··· 28 26 #define SM_DEC 0x00002000 29 27 #define RS_IN 0x00000200 30 28 #define RS_OUT 0x00000300 31 - #define TM_BURST 0x0000080 32 - #define TS_8 0x00000010 33 - #define TS_16 0x00000020 34 - #define TS_32 0x00000030 35 - #define TS_64 0x00000000 36 29 #define TS_BLK 0x00000040 37 30 #define CHCR_DE 0x00000001 38 31 #define CHCR_TE 0x00000002 39 32 #define CHCR_IE 0x00000004 40 33 41 - /* Define the default configuration for dual address memory-memory transfer. 42 - * The 0x400 value represents auto-request, external->external. 43 - */ 44 - #define RS_DUAL (DM_INC | SM_INC | 0x400 | TS_32) 45 - 46 - #define DMAOR_COD 0x00000008 34 + /* DMAOR definitions */ 47 35 #define DMAOR_AE 0x00000004 48 36 #define DMAOR_NMIF 0x00000002 49 37 #define DMAOR_DME 0x00000001 50 38 39 + /* 40 + * Define the default configuration for dual address memory-memory transfer. 41 + * The 0x400 value represents auto-request, external->external. 42 + */ 43 + #define RS_DUAL (DM_INC | SM_INC | 0x400 | TS_32) 44 + 51 45 #define MAX_DMAC_CHANNELS (CONFIG_NR_ONCHIP_DMA_CHANNELS) 46 + 47 + /* 48 + * Subtypes that have fewer channels than this simply need to change 49 + * CONFIG_NR_ONCHIP_DMA_CHANNELS. Likewise, subtypes with a larger number 50 + * of channels should expand on this. 51 + * 52 + * For most subtypes we can easily figure these values out with some 53 + * basic calculation, unfortunately on other subtypes these are more 54 + * scattered, so we just leave it unrolled for simplicity. 55 + */ 56 + #define SAR ((unsigned long[]){SH_DMAC_BASE + 0x00, SH_DMAC_BASE + 0x10, \ 57 + SH_DMAC_BASE + 0x20, SH_DMAC_BASE + 0x30, \ 58 + SH_DMAC_BASE + 0x50, SH_DMAC_BASE + 0x60}) 59 + #define DAR ((unsigned long[]){SH_DMAC_BASE + 0x04, SH_DMAC_BASE + 0x14, \ 60 + SH_DMAC_BASE + 0x24, SH_DMAC_BASE + 0x34, \ 61 + SH_DMAC_BASE + 0x54, SH_DMAC_BASE + 0x64}) 62 + #define DMATCR ((unsigned long[]){SH_DMAC_BASE + 0x08, SH_DMAC_BASE + 0x18, \ 63 + SH_DMAC_BASE + 0x28, SH_DMAC_BASE + 0x38, \ 64 + SH_DMAC_BASE + 0x58, SH_DMAC_BASE + 0x68}) 65 + #define CHCR ((unsigned long[]){SH_DMAC_BASE + 0x0c, SH_DMAC_BASE + 0x1c, \ 66 + SH_DMAC_BASE + 0x2c, SH_DMAC_BASE + 0x3c, \ 67 + SH_DMAC_BASE + 0x5c, SH_DMAC_BASE + 0x6c}) 68 + 69 + #define DMAOR (SH_DMAC_BASE + 0x40) 52 70 53 71 #endif /* __DMA_SH_H */ 54 72
+26 -5
arch/sh/drivers/dma/dma-sysfs.c
··· 3 3 * 4 4 * sysfs interface for SH DMA API 5 5 * 6 - * Copyright (C) 2004 Paul Mundt 6 + * Copyright (C) 2004, 2005 Paul Mundt 7 7 * 8 8 * This file is subject to the terms and conditions of the GNU General Public 9 9 * License. See the file "COPYING" in the main directory of this archive ··· 12 12 #include <linux/kernel.h> 13 13 #include <linux/init.h> 14 14 #include <linux/sysdev.h> 15 + #include <linux/platform_device.h> 15 16 #include <linux/module.h> 17 + #include <linux/err.h> 16 18 #include <linux/string.h> 17 19 #include <asm/dma.h> 18 20 ··· 79 77 unsigned long config; 80 78 81 79 config = simple_strtoul(buf, NULL, 0); 82 - dma_configure_channel(channel->chan, config); 80 + dma_configure_channel(channel->vchan, config); 83 81 84 82 return count; 85 83 } ··· 113 111 dma_ro_attr(count, "0x%08x\n"); 114 112 dma_ro_attr(flags, "0x%08lx\n"); 115 113 116 - int __init dma_create_sysfs_files(struct dma_channel *chan) 114 + int dma_create_sysfs_files(struct dma_channel *chan, struct dma_info *info) 117 115 { 118 116 struct sys_device *dev = &chan->dev; 117 + char name[16]; 119 118 int ret; 120 119 121 - dev->id = chan->chan; 120 + dev->id = chan->vchan; 122 121 dev->cls = &dma_sysclass; 123 122 124 123 ret = sysdev_register(dev); ··· 132 129 sysdev_create_file(dev, &attr_flags); 133 130 sysdev_create_file(dev, &attr_config); 134 131 135 - return 0; 132 + snprintf(name, sizeof(name), "dma%d", chan->chan); 133 + return sysfs_create_link(&info->pdev->dev.kobj, &dev->kobj, name); 134 + } 135 + 136 + void dma_remove_sysfs_files(struct dma_channel *chan, struct dma_info *info) 137 + { 138 + struct sys_device *dev = &chan->dev; 139 + char name[16]; 140 + 141 + sysdev_remove_file(dev, &attr_dev_id); 142 + sysdev_remove_file(dev, &attr_count); 143 + sysdev_remove_file(dev, &attr_mode); 144 + sysdev_remove_file(dev, &attr_flags); 145 + sysdev_remove_file(dev, &attr_config); 146 + 147 + snprintf(name, sizeof(name), "dma%d", chan->chan); 148 + sysfs_remove_link(&info->pdev->dev.kobj, name); 149 + 150 + sysdev_unregister(dev); 136 151 } 137 152
+2
arch/sh/kernel/cpu/bus.c
··· 109 109 /* This is needed for USB OHCI to work */ 110 110 if (dev->dma_mask) 111 111 dev->dev.dma_mask = dev->dma_mask; 112 + if (dev->coherent_dma_mask) 113 + dev->dev.coherent_dma_mask = dev->coherent_dma_mask; 112 114 113 115 snprintf(dev->dev.bus_id, BUS_ID_SIZE, "%s%u", 114 116 dev->name, dev->dev_id);
+1
include/asm-sh/bus-sh.h
··· 21 21 void *mapbase; 22 22 unsigned int irq[6]; 23 23 u64 *dma_mask; 24 + u64 coherent_dma_mask; 24 25 }; 25 26 26 27 #define to_sh_dev(d) container_of((d), struct sh_dev, dev)
+30 -1
include/asm-sh/cpu-sh3/dma.h
··· 3 3 4 4 #define SH_DMAC_BASE 0xa4000020 5 5 6 - #endif /* __ASM_CPU_SH3_DMA_H */ 6 + /* Definitions for the SuperH DMAC */ 7 + #define TM_BURST 0x00000020 8 + #define TS_8 0x00000000 9 + #define TS_16 0x00000008 10 + #define TS_32 0x00000010 11 + #define TS_128 0x00000018 7 12 13 + #define CHCR_TS_MASK 0x18 14 + #define CHCR_TS_SHIFT 3 15 + 16 + #define DMAOR_INIT DMAOR_DME 17 + 18 + /* 19 + * The SuperH DMAC supports a number of transmit sizes, we list them here, 20 + * with their respective values as they appear in the CHCR registers. 21 + */ 22 + enum { 23 + XMIT_SZ_8BIT, 24 + XMIT_SZ_16BIT, 25 + XMIT_SZ_32BIT, 26 + XMIT_SZ_128BIT, 27 + }; 28 + 29 + static unsigned int ts_shift[] __attribute__ ((used)) = { 30 + [XMIT_SZ_8BIT] = 0, 31 + [XMIT_SZ_16BIT] = 1, 32 + [XMIT_SZ_32BIT] = 2, 33 + [XMIT_SZ_128BIT] = 4, 34 + }; 35 + 36 + #endif /* __ASM_CPU_SH3_DMA_H */
+42 -10
include/asm-sh/cpu-sh4/dma.h
··· 1 1 #ifndef __ASM_CPU_SH4_DMA_H 2 2 #define __ASM_CPU_SH4_DMA_H 3 3 4 + #ifdef CONFIG_CPU_SH4A 5 + #define SH_DMAC_BASE 0xfc808020 6 + #else 4 7 #define SH_DMAC_BASE 0xffa00000 8 + #endif 5 9 6 - #define SAR ((unsigned long[]){SH_DMAC_BASE + 0x00, SH_DMAC_BASE + 0x10, \ 7 - SH_DMAC_BASE + 0x20, SH_DMAC_BASE + 0x30}) 8 - #define DAR ((unsigned long[]){SH_DMAC_BASE + 0x04, SH_DMAC_BASE + 0x14, \ 9 - SH_DMAC_BASE + 0x24, SH_DMAC_BASE + 0x34}) 10 - #define DMATCR ((unsigned long[]){SH_DMAC_BASE + 0x08, SH_DMAC_BASE + 0x18, \ 11 - SH_DMAC_BASE + 0x28, SH_DMAC_BASE + 0x38}) 12 - #define CHCR ((unsigned long[]){SH_DMAC_BASE + 0x0c, SH_DMAC_BASE + 0x1c, \ 13 - SH_DMAC_BASE + 0x2c, SH_DMAC_BASE + 0x3c}) 14 - #define DMAOR (SH_DMAC_BASE + 0x40) 10 + /* Definitions for the SuperH DMAC */ 11 + #define TM_BURST 0x0000080 12 + #define TS_8 0x00000010 13 + #define TS_16 0x00000020 14 + #define TS_32 0x00000030 15 + #define TS_64 0x00000000 16 + 17 + #define CHCR_TS_MASK 0x30 18 + #define CHCR_TS_SHIFT 4 19 + 20 + #define DMAOR_COD 0x00000008 21 + 22 + #define DMAOR_INIT ( 0x8000 | DMAOR_DME ) 23 + 24 + /* 25 + * The SuperH DMAC supports a number of transmit sizes, we list them here, 26 + * with their respective values as they appear in the CHCR registers. 27 + * 28 + * Defaults to a 64-bit transfer size. 29 + */ 30 + enum { 31 + XMIT_SZ_64BIT, 32 + XMIT_SZ_8BIT, 33 + XMIT_SZ_16BIT, 34 + XMIT_SZ_32BIT, 35 + XMIT_SZ_256BIT, 36 + }; 37 + 38 + /* 39 + * The DMA count is defined as the number of bytes to transfer. 40 + */ 41 + static unsigned int ts_shift[] __attribute__ ((used)) = { 42 + [XMIT_SZ_64BIT] = 3, 43 + [XMIT_SZ_8BIT] = 0, 44 + [XMIT_SZ_16BIT] = 1, 45 + [XMIT_SZ_32BIT] = 2, 46 + [XMIT_SZ_256BIT] = 5, 47 + }; 15 48 16 49 #endif /* __ASM_CPU_SH4_DMA_H */ 17 -
+14 -13
include/asm-sh/dma-mapping.h
··· 4 4 #include <linux/config.h> 5 5 #include <linux/mm.h> 6 6 #include <asm/scatterlist.h> 7 + #include <asm/cacheflush.h> 7 8 #include <asm/io.h> 8 9 9 10 extern struct bus_type pci_bus_type; ··· 142 141 } 143 142 } 144 143 145 - static inline void dma_sync_single_for_cpu(struct device *dev, 146 - dma_addr_t dma_handle, size_t size, 147 - enum dma_data_direction dir) 144 + static void dma_sync_single_for_cpu(struct device *dev, 145 + dma_addr_t dma_handle, size_t size, 146 + enum dma_data_direction dir) 148 147 __attribute__ ((alias("dma_sync_single"))); 149 148 150 - static inline void dma_sync_single_for_device(struct device *dev, 151 - dma_addr_t dma_handle, size_t size, 152 - enum dma_data_direction dir) 153 - __attribute__ ((alias("dma_sync_single"))); 154 - 155 - static inline void dma_sync_sg_for_cpu(struct device *dev, 156 - struct scatterlist *sg, int nelems, 149 + static void dma_sync_single_for_device(struct device *dev, 150 + dma_addr_t dma_handle, size_t size, 157 151 enum dma_data_direction dir) 152 + __attribute__ ((alias("dma_sync_single"))); 153 + 154 + static void dma_sync_sg_for_cpu(struct device *dev, 155 + struct scatterlist *sg, int nelems, 156 + enum dma_data_direction dir) 158 157 __attribute__ ((alias("dma_sync_sg"))); 159 158 160 - static inline void dma_sync_sg_for_device(struct device *dev, 161 - struct scatterlist *sg, int nelems, 162 - enum dma_data_direction dir) 159 + static void dma_sync_sg_for_device(struct device *dev, 160 + struct scatterlist *sg, int nelems, 161 + enum dma_data_direction dir) 163 162 __attribute__ ((alias("dma_sync_sg"))); 164 163 165 164 static inline int dma_get_cache_alignment(void)
+11 -3
include/asm-sh/dma.h
··· 15 15 #include <linux/spinlock.h> 16 16 #include <linux/wait.h> 17 17 #include <linux/sysdev.h> 18 + #include <linux/device.h> 18 19 #include <asm/cpu/dma.h> 19 20 #include <asm/semaphore.h> 20 21 ··· 55 54 * DMA channel capabilities / flags 56 55 */ 57 56 enum { 58 - DMA_CONFIGURED = 0x00, 59 57 DMA_TEI_CAPABLE = 0x01, 58 + DMA_CONFIGURED = 0x02, 60 59 }; 61 60 62 61 extern spinlock_t dma_spin_lock; ··· 75 74 struct dma_channel { 76 75 char dev_id[16]; 77 76 78 - unsigned int chan; 77 + unsigned int chan; /* Physical channel number */ 78 + unsigned int vchan; /* Virtual channel number */ 79 79 unsigned int mode; 80 80 unsigned int count; 81 81 ··· 93 91 }; 94 92 95 93 struct dma_info { 94 + struct platform_device *pdev; 95 + 96 96 const char *name; 97 97 unsigned int nr_channels; 98 98 unsigned long flags; ··· 134 130 135 131 #ifdef CONFIG_SYSFS 136 132 /* arch/sh/drivers/dma/dma-sysfs.c */ 137 - extern int dma_create_sysfs_files(struct dma_channel *); 133 + extern int dma_create_sysfs_files(struct dma_channel *, struct dma_info *); 134 + extern void dma_remove_sysfs_files(struct dma_channel *, struct dma_info *); 135 + #else 136 + #define dma_create_sysfs_file(channel, info) do { } while (0) 137 + #define dma_remove_sysfs_file(channel, info) do { } while (0) 138 138 #endif 139 139 140 140 #ifdef CONFIG_PCI