123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276 |
- /* linux/arch/arm/mach-bast/dma-sysfs.c
- *
- * (c) 2005 Simtec Electronics
- * Ben Dooks <ben@simtec.co.uk>
- *
- * S3C2440 DMA core sysfs interface
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
- */
- #include <linux/module.h>
- #include <linux/init.h>
- #include <linux/sched.h>
- #include <linux/spinlock.h>
- #include <linux/interrupt.h>
- #include <linux/sysdev.h>
- #include <linux/config.h>
- #include <asm/system.h>
- #include <asm/irq.h>
- #include <asm/hardware.h>
- #include <asm/io.h>
- #include <asm/dma.h>
- #include <asm/mach/dma.h>
- #include <asm/arch/map.h>
- extern struct sysdev_class dma_sysclass;
- extern s3c24xx_dma_chan_t s3c24xx_chans[S3C24XX_DMA_CHANNELS];
- #define dma_rdreg(chan, reg) readl((chan)->regs + (reg))
- static const char *s3c24xx_dma_decode_state(s3c24xx_dma_state_t state)
- {
- switch (state) {
- case S3C24XX_DMA_IDLE:
- return "Idle";
- case S3C24XX_DMA_RUNNING:
- return "Running";
- case S3C24XX_DMA_PAUSED:
- return "Paused";
- default:
- return "Invalid";
- }
- return NULL;
- }
- static const char *s3c24xx_dma_decode_loadstate(s3c24xx_dma_loadst_t state)
- {
- switch (state) {
- case S3C24XX_DMALOAD_NONE:
- return "Nothing Loaded";
- case S3C24XX_DMALOAD_1LOADED:
- return "1 Loaded";
- case S3C24XX_DMALOAD_1RUNNING:
- return "1 Running";
- case S3C24XX_DMALOAD_1LOADED_1RUNNING:
- return "1 Loaded, 1 Running";
- default:
- return "Invalid Load State";
- }
- return NULL;
- }
- static const char *s3c24xx_dma_decode_source(s3c24xx_dmasrc_t source)
- {
- switch (source) {
- case S3C24XX_DMASRC_HW:
- return "Hardware";
- case S3C24XX_DMASRC_MEM:
- return "Memory";
- default:
- return "Unknown Source";
- }
- return NULL;
- }
- struct outbuff {
- char *buff;
- int offset;
- int size;
- };
- static inline void outbuf_init(struct outbuff *ob, char *buf, int size)
- {
- ob->buff = buf;
- ob->offset = 0;
- ob->size = size;
- }
- static void outbuf_pf(struct outbuff *ob, const char *fmt, ...)
- {
- va_list va;
- va_start(va, fmt);
- ob->offset += vsnprintf(ob->buff + ob->offset,
- ob->size - ob->offset,
- fmt, va);
- va_end(va);
- }
- static void dma_sysfs_showregs(s3c24xx_dma_chan_t *chan, struct outbuff *buf)
- {
- outbuf_pf(buf, "Hardware Registers:\n\n");
- outbuf_pf(buf, " DISRC \t\t\t%08lx\n", readl(chan->regs + 0x00));
- outbuf_pf(buf, " DISRCC\t\t\t%08lx\n", readl(chan->regs + 0x04));
- outbuf_pf(buf, " DIDST \t\t\t%08lx\n", readl(chan->regs + 0x08));
- outbuf_pf(buf, " DIDSTC\t\t\t%08lx\n", readl(chan->regs + 0x0C));
- outbuf_pf(buf, " DCON \t\t\t%08lx\n", readl(chan->regs + 0x10));
- outbuf_pf(buf, " DSTAT \t\t\t%08lx\n", readl(chan->regs + 0x14));
- outbuf_pf(buf, " DCSRC \t\t\t%08lx\n", readl(chan->regs + 0x18));
- outbuf_pf(buf, " DCDST \t\t\t%08lx\n", readl(chan->regs + 0x1c));
- outbuf_pf(buf, " DMTRG \t\t\t%08lx\n", readl(chan->regs + 0x20));
- }
- static void dma_sysfs_showbuf(s3c24xx_dma_chan_t *chan,
- struct outbuff *buf,
- s3c24xx_dma_buf_t *ptr)
- {
- if (ptr == NULL)
- return;
- outbuf_pf(buf, " buff %p: data=%08x, size=%08x, id=%08x\n",
- ptr, ptr->data, ptr->size, ptr->id);
- }
- static void dma_sysfs_showbuffers(s3c24xx_dma_chan_t *chan, struct outbuff *buf)
- {
- s3c24xx_dma_buf_t *ptr = chan->next;
- unsigned long flags;
- local_irq_save(flags);
- outbuf_pf(buf, "Current Buffer:\n");
- dma_sysfs_showbuf(chan, buf, chan->curr);
- outbuf_pf(buf, "\nBuffer Queue: %p -> %p\n", chan->next, chan->end);
- for (; ptr != NULL; ptr = ptr->next)
- dma_sysfs_showbuf(chan, buf, ptr);
- local_irq_restore(flags);
- }
- static void dma_sysfs_showstate(s3c24xx_dma_chan_t *chan, struct outbuff *buf)
- {
- outbuf_pf(buf, "IRQ:\t\t\t\t%d\n", chan->irq);
- outbuf_pf(buf, "Register Base:\t\t\t0x%08x\n", chan->regs);
- outbuf_pf(buf, "Address Register:\t\t0x%08lx\n", chan->addr_reg);
- outbuf_pf(buf, "Hardware Register:\t\t0x%08lx\n", chan->dev_addr);
- outbuf_pf(buf, "Load Timeout:\t\t\t0x%08x\n", chan->load_timeout);
- outbuf_pf(buf, "Data Source:\t\t\t%s\n",
- s3c24xx_dma_decode_source(chan->source));
- outbuf_pf(buf, "Channel State:\t\t\t%s (%d)\n",
- s3c24xx_dma_decode_state(chan->state), chan->state);
- outbuf_pf(buf, "Load State:\t\t\t%s (%d)\n",
- s3c24xx_dma_decode_loadstate(chan->load_state),
- chan->load_state);
- if (chan->client != NULL) {
- outbuf_pf(buf, "Claimed by:\t\t\t%s\n",
- chan->client->name);
- } else {
- outbuf_pf(buf, "Claimed by:\t\t\tNo-one\n");
- }
- }
- static inline s3c24xx_dma_chan_t *dev_to_chan(struct sys_device *dev)
- {
- return &s3c24xx_chans[dev->id];
- }
- static ssize_t dma_sysfs_show_regs(struct sys_device *dev, char *buf)
- {
- s3c24xx_dma_chan_t *cp = dev_to_chan(dev);
- struct outbuff buff;
- outbuf_init(&buff, buf, PAGE_SIZE);
- dma_sysfs_showregs(cp, &buff);
- return buff.offset;
- }
- static ssize_t dma_sysfs_show_state(struct sys_device *dev, char *buf)
- {
- s3c24xx_dma_chan_t *cp = dev_to_chan(dev);
- struct outbuff buff;
- outbuf_init(&buff, buf, PAGE_SIZE);
- dma_sysfs_showstate(cp, &buff);
- return buff.offset;
- }
- static ssize_t dma_sysfs_show_buffers(struct sys_device *dev, char *buf)
- {
- s3c24xx_dma_chan_t *cp = dev_to_chan(dev);
- struct outbuff buff;
- outbuf_init(&buff, buf, PAGE_SIZE);
- dma_sysfs_showbuffers(cp, &buff);
- return buff.offset;
- }
- static ssize_t dma_sysfs_show_all(struct sys_device *dev, char *buf)
- {
- s3c24xx_dma_chan_t *cp = dev_to_chan(dev);
- struct outbuff buff;
- outbuf_init(&buff, buf, PAGE_SIZE);
- dma_sysfs_showstate(cp, &buff);
- dma_sysfs_showregs(cp, &buff);
- dma_sysfs_showbuffers(cp, &buff);
- return buff.offset;
- }
- static SYSDEV_ATTR(all, S_IRUGO, dma_sysfs_show_all, NULL);
- static SYSDEV_ATTR(regs, S_IRUGO, dma_sysfs_show_regs, NULL);
- static SYSDEV_ATTR(state, S_IRUGO, dma_sysfs_show_state, NULL);
- static SYSDEV_ATTR(buffers, S_IRUGO, dma_sysfs_show_buffers, NULL);
- static struct sysdev_attribute *attrs[] = {
- &attr_all,
- &attr_regs,
- &attr_state,
- &attr_buffers,
- };
- static int dma_sysfs_attach(struct sys_device *dev)
- {
- int i;
- for (i = 0; i < ARRAY_SIZE(attrs); i++)
- sysdev_create_file(dev, attrs[i]);
- return 0;
- }
- static int dma_sysfs_remove(struct sys_device *dev)
- {
- int i;
- for (i = 0; i < ARRAY_SIZE(attrs); i++)
- sysdev_create_file(dev, attrs[i]);
- return 0;
- }
- static struct sysdev_driver dma_sysfs_driver = {
- .add = dma_sysfs_attach,
- .remove = dma_sysfs_remove,
- };
- static int __init s3c24xx_init_dma_sysfs(void)
- {
- printk("S3C24XX DMA sysfs support, (c) 2005 Simtec Electronics\n");
- return sysdev_driver_register(&dma_sysclass, &dma_sysfs_driver);
- }
- __initcall(s3c24xx_init_dma_sysfs);
|