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