linux/arch/sh/drivers/dma/dma-sysfs.c
<<
>>
Prefs
   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/sysdev.h>
  15#include <linux/platform_device.h>
  16#include <linux/module.h>
  17#include <linux/err.h>
  18#include <linux/string.h>
  19#include <asm/dma.h>
  20
  21static struct sysdev_class dma_sysclass = {
  22        .name = "dma",
  23};
  24EXPORT_SYMBOL(dma_sysclass);
  25
  26static ssize_t dma_show_devices(struct sys_device *dev,
  27                                struct sysdev_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
  47static SYSDEV_ATTR(devices, S_IRUGO, dma_show_devices, NULL);
  48
  49static int __init dma_sysclass_init(void)
  50{
  51        int ret;
  52
  53        ret = sysdev_class_register(&dma_sysclass);
  54        if (unlikely(ret))
  55                return ret;
  56
  57        return sysfs_create_file(&dma_sysclass.kset.kobj, &attr_devices.attr);
  58}
  59postcore_initcall(dma_sysclass_init);
  60
  61static ssize_t dma_show_dev_id(struct sys_device *dev,
  62                                struct sysdev_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
  68static ssize_t dma_store_dev_id(struct sys_device *dev,
  69                                struct sysdev_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
  77static SYSDEV_ATTR(dev_id, S_IRUGO | S_IWUSR, dma_show_dev_id, dma_store_dev_id);
  78
  79static ssize_t dma_store_config(struct sys_device *dev,
  80                                struct sysdev_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
  92static SYSDEV_ATTR(config, S_IWUSR, NULL, dma_store_config);
  93
  94static ssize_t dma_show_mode(struct sys_device *dev,
  95                                struct sysdev_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
 101static ssize_t dma_store_mode(struct sys_device *dev,
 102                              struct sysdev_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
 110static SYSDEV_ATTR(mode, S_IRUGO | S_IWUSR, dma_show_mode, dma_store_mode);
 111
 112#define dma_ro_attr(field, fmt)                                         \
 113static ssize_t dma_show_##field(struct sys_device *dev,                 \
 114                                struct sysdev_attribute *attr, char *buf)\
 115{                                                                       \
 116        struct dma_channel *channel = to_dma_channel(dev);              \
 117        return sprintf(buf, fmt, channel->field);                       \
 118}                                                                       \
 119static SYSDEV_ATTR(field, S_IRUGO, dma_show_##field, NULL);
 120
 121dma_ro_attr(count, "0x%08x\n");
 122dma_ro_attr(flags, "0x%08lx\n");
 123
 124int dma_create_sysfs_files(struct dma_channel *chan, struct dma_info *info)
 125{
 126        struct sys_device *dev = &chan->dev;
 127        char name[16];
 128        int ret;
 129
 130        dev->id  = chan->vchan;
 131        dev->cls = &dma_sysclass;
 132
 133        ret = sysdev_register(dev);
 134        if (ret)
 135                return ret;
 136
 137        ret |= sysdev_create_file(dev, &attr_dev_id);
 138        ret |= sysdev_create_file(dev, &attr_count);
 139        ret |= sysdev_create_file(dev, &attr_mode);
 140        ret |= sysdev_create_file(dev, &attr_flags);
 141        ret |= sysdev_create_file(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
 152void dma_remove_sysfs_files(struct dma_channel *chan, struct dma_info *info)
 153{
 154        struct sys_device *dev = &chan->dev;
 155        char name[16];
 156
 157        sysdev_remove_file(dev, &attr_dev_id);
 158        sysdev_remove_file(dev, &attr_count);
 159        sysdev_remove_file(dev, &attr_mode);
 160        sysdev_remove_file(dev, &attr_flags);
 161        sysdev_remove_file(dev, &attr_config);
 162
 163        snprintf(name, sizeof(name), "dma%d", chan->chan);
 164        sysfs_remove_link(&info->pdev->dev.kobj, name);
 165
 166        sysdev_unregister(dev);
 167}
 168