1 /* 2 * arch/sh/drivers/dma/dma-sysfs.c 3 * 4 * sysfs interface for SH DMA API 5 * 6 * Copyright (C) 2004 - 2006 Paul Mundt 7 * 8 * This file is subject to the terms and conditions of the GNU General Public 9 * License. See the file "COPYING" in the main directory of this archive 10 * for more details. 11 */ 12 #include <linux/kernel.h> 13 #include <linux/init.h> 14 #include <linux/stat.h> 15 #include <linux/device.h> 16 #include <linux/platform_device.h> 17 #include <linux/err.h> 18 #include <linux/string.h> 19 #include <asm/dma.h> 20 21 static struct bus_type dma_subsys = { 22 .name = "dma", 23 .dev_name = "dma", 24 }; 25 26 static ssize_t dma_show_devices(struct device *dev, 27 struct device_attribute *attr, char *buf) 28 { 29 ssize_t len = 0; 30 int i; 31 32 for (i = 0; i < MAX_DMA_CHANNELS; i++) { 33 struct dma_info *info = get_dma_info(i); 34 struct dma_channel *channel = get_dma_channel(i); 35 36 if (unlikely(!info) || !channel) 37 continue; 38 39 len += sprintf(buf + len, "%2d: %14s %s\n", 40 channel->chan, info->name, 41 channel->dev_id); 42 } 43 44 return len; 45 } 46 47 static DEVICE_ATTR(devices, S_IRUGO, dma_show_devices, NULL); 48 49 static int __init dma_subsys_init(void) 50 { 51 int ret; 52 53 ret = subsys_system_register(&dma_subsys, NULL); 54 if (unlikely(ret)) 55 return ret; 56 57 return device_create_file(dma_subsys.dev_root, &dev_attr_devices); 58 } 59 postcore_initcall(dma_subsys_init); 60 61 static ssize_t dma_show_dev_id(struct device *dev, 62 struct device_attribute *attr, char *buf) 63 { 64 struct dma_channel *channel = to_dma_channel(dev); 65 return sprintf(buf, "%s\n", channel->dev_id); 66 } 67 68 static ssize_t dma_store_dev_id(struct device *dev, 69 struct device_attribute *attr, 70 const char *buf, size_t count) 71 { 72 struct dma_channel *channel = to_dma_channel(dev); 73 strcpy(channel->dev_id, buf); 74 return count; 75 } 76 77 static DEVICE_ATTR(dev_id, S_IRUGO | S_IWUSR, dma_show_dev_id, dma_store_dev_id); 78 79 static ssize_t dma_store_config(struct device *dev, 80 struct device_attribute *attr, 81 const char *buf, size_t count) 82 { 83 struct dma_channel *channel = to_dma_channel(dev); 84 unsigned long config; 85 86 config = simple_strtoul(buf, NULL, 0); 87 dma_configure_channel(channel->vchan, config); 88 89 return count; 90 } 91 92 static DEVICE_ATTR(config, S_IWUSR, NULL, dma_store_config); 93 94 static ssize_t dma_show_mode(struct device *dev, 95 struct device_attribute *attr, char *buf) 96 { 97 struct dma_channel *channel = to_dma_channel(dev); 98 return sprintf(buf, "0x%08x\n", channel->mode); 99 } 100 101 static ssize_t dma_store_mode(struct device *dev, 102 struct device_attribute *attr, 103 const char *buf, size_t count) 104 { 105 struct dma_channel *channel = to_dma_channel(dev); 106 channel->mode = simple_strtoul(buf, NULL, 0); 107 return count; 108 } 109 110 static DEVICE_ATTR(mode, S_IRUGO | S_IWUSR, dma_show_mode, dma_store_mode); 111 112 #define dma_ro_attr(field, fmt) \ 113 static ssize_t dma_show_##field(struct device *dev, \ 114 struct device_attribute *attr, char *buf)\ 115 { \ 116 struct dma_channel *channel = to_dma_channel(dev); \ 117 return sprintf(buf, fmt, channel->field); \ 118 } \ 119 static DEVICE_ATTR(field, S_IRUGO, dma_show_##field, NULL); 120 121 dma_ro_attr(count, "0x%08x\n"); 122 dma_ro_attr(flags, "0x%08lx\n"); 123 124 int dma_create_sysfs_files(struct dma_channel *chan, struct dma_info *info) 125 { 126 struct device *dev = &chan->dev; 127 char name[16]; 128 int ret; 129 130 dev->id = chan->vchan; 131 dev->bus = &dma_subsys; 132 133 ret = device_register(dev); 134 if (ret) 135 return ret; 136 137 ret |= device_create_file(dev, &dev_attr_dev_id); 138 ret |= device_create_file(dev, &dev_attr_count); 139 ret |= device_create_file(dev, &dev_attr_mode); 140 ret |= device_create_file(dev, &dev_attr_flags); 141 ret |= device_create_file(dev, &dev_attr_config); 142 143 if (unlikely(ret)) { 144 dev_err(&info->pdev->dev, "Failed creating attrs\n"); 145 return ret; 146 } 147 148 snprintf(name, sizeof(name), "dma%d", chan->chan); 149 return sysfs_create_link(&info->pdev->dev.kobj, &dev->kobj, name); 150 } 151 152 void dma_remove_sysfs_files(struct dma_channel *chan, struct dma_info *info) 153 { 154 struct device *dev = &chan->dev; 155 char name[16]; 156 157 device_remove_file(dev, &dev_attr_dev_id); 158 device_remove_file(dev, &dev_attr_count); 159 device_remove_file(dev, &dev_attr_mode); 160 device_remove_file(dev, &dev_attr_flags); 161 device_remove_file(dev, &dev_attr_config); 162 163 snprintf(name, sizeof(name), "dma%d", chan->chan); 164 sysfs_remove_link(&info->pdev->dev.kobj, name); 165 166 device_unregister(dev); 167 } 168