summaryrefslogtreecommitdiffstats
path: root/arch/mips/txx9/generic/setup.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/mips/txx9/generic/setup.c')
-rw-r--r--arch/mips/txx9/generic/setup.c84
1 files changed, 84 insertions, 0 deletions
diff --git a/arch/mips/txx9/generic/setup.c b/arch/mips/txx9/generic/setup.c
index 7f9101257615..3b7d77d61ce0 100644
--- a/arch/mips/txx9/generic/setup.c
+++ b/arch/mips/txx9/generic/setup.c
@@ -24,6 +24,7 @@
#include <linux/serial_core.h>
#include <linux/mtd/physmap.h>
#include <linux/leds.h>
+#include <linux/sysdev.h>
#include <asm/bootinfo.h>
#include <asm/time.h>
#include <asm/reboot.h>
@@ -912,3 +913,86 @@ void __init txx9_aclc_init(unsigned long baseaddr, int irq,
platform_device_put(pdev);
#endif
}
+
+static struct sysdev_class txx9_sramc_sysdev_class;
+
+struct txx9_sramc_sysdev {
+ struct sys_device dev;
+ struct bin_attribute bindata_attr;
+ void __iomem *base;
+};
+
+static ssize_t txx9_sram_read(struct kobject *kobj,
+ struct bin_attribute *bin_attr,
+ char *buf, loff_t pos, size_t size)
+{
+ struct txx9_sramc_sysdev *dev = bin_attr->private;
+ size_t ramsize = bin_attr->size;
+
+ if (pos >= ramsize)
+ return 0;
+ if (pos + size > ramsize)
+ size = ramsize - pos;
+ memcpy_fromio(buf, dev->base + pos, size);
+ return size;
+}
+
+static ssize_t txx9_sram_write(struct kobject *kobj,
+ struct bin_attribute *bin_attr,
+ char *buf, loff_t pos, size_t size)
+{
+ struct txx9_sramc_sysdev *dev = bin_attr->private;
+ size_t ramsize = bin_attr->size;
+
+ if (pos >= ramsize)
+ return 0;
+ if (pos + size > ramsize)
+ size = ramsize - pos;
+ memcpy_toio(dev->base + pos, buf, size);
+ return size;
+}
+
+void __init txx9_sramc_init(struct resource *r)
+{
+ struct txx9_sramc_sysdev *dev;
+ size_t size;
+ int err;
+
+ if (!txx9_sramc_sysdev_class.name) {
+ txx9_sramc_sysdev_class.name = "txx9_sram";
+ err = sysdev_class_register(&txx9_sramc_sysdev_class);
+ if (err) {
+ txx9_sramc_sysdev_class.name = NULL;
+ return;
+ }
+ }
+ dev = kzalloc(sizeof(*dev), GFP_KERNEL);
+ if (!dev)
+ return;
+ size = resource_size(r);
+ dev->base = ioremap(r->start, size);
+ if (!dev->base)
+ goto exit;
+ dev->dev.cls = &txx9_sramc_sysdev_class;
+ dev->bindata_attr.attr.name = "bindata";
+ dev->bindata_attr.attr.mode = S_IRUSR | S_IWUSR;
+ dev->bindata_attr.read = txx9_sram_read;
+ dev->bindata_attr.write = txx9_sram_write;
+ dev->bindata_attr.size = size;
+ dev->bindata_attr.private = dev;
+ err = sysdev_register(&dev->dev);
+ if (err)
+ goto exit;
+ err = sysfs_create_bin_file(&dev->dev.kobj, &dev->bindata_attr);
+ if (err) {
+ sysdev_unregister(&dev->dev);
+ goto exit;
+ }
+ return;
+exit:
+ if (dev) {
+ if (dev->base)
+ iounmap(dev->base);
+ kfree(dev);
+ }
+}