2004-10-27 07:55:00

by Paul Mundt

[permalink] [raw]
Subject: [PATCH] SuperHyway bus support

This adds support for the SuperHyway bus currently used by sh64 and also used
by newer sh4a cores. This just adds the common bus support, with things like
bus scanning being architecture dependent. sh64 presently makes use of this
for its DMAC, with further device support planned.

I've added this under drivers/sh/superhyway/ as there are some other
sh-specific buses that I intend to add under drivers/sh/ at a later point.
Some of the sh dma code is also intended for consolidation there so sh64 can
use it as well.

Against current BK. Comments appreciated.

Signed-off-by: Paul Mundt <[email protected]>

--- linux-2.6/drivers/Makefile 2004-10-27 09:45:42.582996368 +0300
+++ sh64--stable--2.6/drivers/Makefile 2004-10-27 09:10:12.000000000 +0300
@@ -60,3 +59,4 @@
obj-$(CONFIG_CPU_FREQ) += cpufreq/
obj-$(CONFIG_MMC) += mmc/
obj-y += firmware/
+obj-$(CONFIG_SUPERH) += sh/
--- linux-2.6/drivers/sh/Makefile 1970-01-01 02:00:00.000000000 +0200
+++ sh64--stable--2.6/drivers/sh/Makefile 2004-10-27 09:10:12.000000000 +0300
@@ -0,0 +1,6 @@
+#
+# Makefile for the SuperH specific drivers.
+#
+
+obj-$(CONFIG_SUPERHYWAY) += superhyway/
+
--- linux-2.6/drivers/sh/superhyway/Makefile 1970-01-01 02:00:00.000000000 +0200
+++ sh64--stable--2.6/drivers/sh/superhyway/Makefile 2004-10-27 09:10:12.000000000 +0300
@@ -0,0 +1,18 @@
+#
+# Makefile for the SuperHyway bus drivers.
+#
+
+obj-$(CONFIG_SUPERHYWAY) += superhyway.o
+obj-$(CONFIG_SYSFS) += superhyway-sysfs.o
+
+clean-files := devlist.h
+
+$(obj)/superhyway.o: $(obj)/devlist.h
+
+quiet_cmd_devlist = GEN $@
+ cmd_devlist = sed -e 's/^\#.*$$//g;s/^[ ].*$$//g;/^$$/d; \
+ s/\(0x.*\) / { \1, /g;s/$$/ },/' < $< > $@
+
+$(obj)/devlist.h: $(src)/superhyway.ids
+ $(call cmd,devlist)
+
--- linux-2.6/drivers/sh/superhyway/superhyway-sysfs.c 1970-01-01 02:00:00.000000000 +0200
+++ sh64--stable--2.6/drivers/sh/superhyway/superhyway-sysfs.c 2004-10-27 09:10:12.000000000 +0300
@@ -0,0 +1,50 @@
+/*
+ * drivers/sh/superhyway/superhyway-sysfs.c
+ *
+ * SuperHyway Bus sysfs interface
+ *
+ * Copyright (C) 2004 Paul Mundt <[email protected]>
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/device.h>
+#include <linux/types.h>
+#include <linux/superhyway.h>
+
+#define superhyway_ro_attr(name, fmt, field) \
+static ssize_t superhyway_show_##name(struct device *dev, char *buf) \
+{ \
+ struct superhyway_device *s = to_superhyway_device(dev); \
+ return sprintf(buf, fmt, s->field); \
+} \
+static DEVICE_ATTR(name, S_IRUGO, superhyway_show_##name, NULL);
+
+/* VCR flags */
+superhyway_ro_attr(perr_flags, "0x%02x\n", vcr.perr_flags);
+superhyway_ro_attr(merr_flags, "0x%02x\n", vcr.merr_flags);
+superhyway_ro_attr(mod_vers, "0x%04x\n", vcr.mod_vers);
+superhyway_ro_attr(mod_id, "0x%04x\n", vcr.mod_id);
+superhyway_ro_attr(bot_mb, "0x%02x\n", vcr.bot_mb);
+superhyway_ro_attr(top_mb, "0x%02x\n", vcr.top_mb);
+
+/* Misc */
+superhyway_ro_attr(resource, "0x%08lx\n", resource.start);
+
+void superhyway_create_sysfs_files(struct superhyway_device *s)
+{
+ struct device *dev = &s->dev;
+
+ device_create_file(dev, &dev_attr_perr_flags);
+ device_create_file(dev, &dev_attr_merr_flags);
+ device_create_file(dev, &dev_attr_mod_vers);
+ device_create_file(dev, &dev_attr_mod_id);
+ device_create_file(dev, &dev_attr_bot_mb);
+ device_create_file(dev, &dev_attr_top_mb);
+ device_create_file(dev, &dev_attr_resource);
+}
+
--- linux-2.6/drivers/sh/superhyway/superhyway.c 1970-01-01 02:00:00.000000000 +0200
+++ sh64--stable--2.6/drivers/sh/superhyway/superhyway.c 2004-10-27 09:10:12.000000000 +0300
@@ -0,0 +1,234 @@
+/*
+ * drivers/sh/superhyway/superhyway.c
+ *
+ * SuperHyway Bus Driver
+ *
+ * Copyright (C) 2004 Paul Mundt <[email protected]>
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/device.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/list.h>
+#include <linux/superhyway.h>
+
+static struct superhyway_device_info {
+ unsigned int id;
+ const char *name;
+} superhyway_device_table[] __initdata = {
+#include "devlist.h"
+};
+
+static int superhyway_devices;
+
+static struct superhyway_bus superhyway_bus = {
+ .name = "SuperHyway bus",
+};
+
+static void superhyway_name_device(struct superhyway_device *dev)
+{
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(superhyway_device_table); i++)
+ if (superhyway_device_table[i].id == dev->id.id)
+ sprintf(dev->pretty_name, "%s",
+ superhyway_device_table[i].name);
+}
+
+/**
+ * superhyway_add_device - Add a SuperHyway module
+ * @mod_id: Module ID (taken from MODULE.VCR.MOD_ID).
+ * @base: Physical address where module is mapped.
+ * @vcr: VCR value.
+ *
+ * This is responsible for adding a new SuperHyway module. This sets up a new
+ * struct superhyway_device for the module being added. Each one of @mod_id,
+ * @base, and @vcr are registered with the new device for further use
+ * elsewhere.
+ *
+ * Devices are initially added in the order that they are scanned (from the
+ * top-down of the memory map), and are assigned an ID based on the order that
+ * they are added. Any manual addition of a module will thus get the ID after
+ * the devices already discovered regardless of where it resides in memory.
+ *
+ * Further work can and should be done in superhyway_scan_bus(), to be sure
+ * that any new modules are properly discovered and subsequently registered.
+ */
+int superhyway_add_device(unsigned int mod_id, unsigned long base,
+ unsigned long long vcr)
+{
+ struct superhyway_device *dev;
+ int ret;
+
+ dev = kmalloc(sizeof(struct superhyway_device), GFP_KERNEL);
+ if (!dev)
+ return -ENOMEM;
+
+ memset(dev, 0, sizeof(struct superhyway_device));
+
+ dev->id.id = mod_id;
+ sprintf(dev->name, "SuperHyway device %04x\n", dev->id.id);
+
+ superhyway_name_device(dev);
+
+ dev->vcr = *((struct vcr_info *)(&vcr));
+ dev->resource.name = dev->name;
+ dev->resource.start = base;
+ dev->resource.end = dev->resource.start + 0x01000000;
+ dev->dev.parent = &superhyway_bus.dev;
+ dev->dev.bus = &superhyway_bus_type;
+
+ sprintf(dev->dev.bus_id, "%02x", superhyway_devices);
+
+ pr_info(" 0x%04x (%s) control block at 0x%08lx\n",
+ dev->id.id, dev->pretty_name, dev->resource.start);
+
+ superhyway_devices++;
+
+ list_add(&dev->node, &superhyway_bus.devices);
+
+ ret = device_register(&dev->dev);
+ superhyway_create_sysfs_files(dev);
+
+ return ret;
+}
+
+static int __init superhyway_init(void)
+{
+ extern int superhyway_scan_bus(void);
+
+ INIT_LIST_HEAD(&superhyway_bus.devices);
+ strcpy(superhyway_bus.dev.bus_id, "superhyway");
+ device_register(&superhyway_bus.dev);
+
+ return superhyway_scan_bus();
+}
+
+postcore_initcall(superhyway_init);
+
+static const struct superhyway_device_id *
+superhyway_match_id(const struct superhyway_device_id *ids,
+ struct superhyway_device *dev)
+{
+ while (ids->id) {
+ if (ids->id == dev->id.id)
+ return ids;
+
+ ids++;
+ }
+
+ return NULL;
+}
+
+static int superhyway_device_probe(struct device *dev)
+{
+ struct superhyway_device *shyway_dev = to_superhyway_device(dev);
+ struct superhyway_driver *shyway_drv = to_superhyway_driver(dev->driver);
+
+ if (shyway_drv && shyway_drv->probe) {
+ const struct superhyway_device_id *id;
+
+ id = superhyway_match_id(shyway_drv->id_table, shyway_dev);
+ if (id)
+ return shyway_drv->probe(shyway_dev, id);
+ }
+
+ return -ENODEV;
+}
+
+static int superhyway_device_remove(struct device *dev)
+{
+ struct superhyway_device *shyway_dev = to_superhyway_device(dev);
+ struct superhyway_driver *shyway_drv = to_superhyway_driver(dev->driver);
+
+ if (shyway_drv && shyway_drv->remove) {
+ shyway_drv->remove(shyway_dev);
+ return 0;
+ }
+
+ return -ENODEV;
+}
+
+/**
+ * superhyway_register_driver - Register a new SuperHyway driver
+ * @drv: SuperHyway driver to register.
+ *
+ * This registers the passed in @drv. Any devices matching the id table will
+ * automatically be populated and handed off to the driver's specified probe
+ * routine.
+ */
+int superhyway_register_driver(struct superhyway_driver *drv)
+{
+ drv->drv.name = drv->name;
+ drv->drv.bus = &superhyway_bus_type;
+ drv->drv.probe = superhyway_device_probe;
+ drv->drv.remove = superhyway_device_remove;
+
+ return driver_register(&drv->drv);
+}
+
+/**
+ * superhyway_unregister_driver - Unregister a SuperHyway driver
+ * @drv: SuperHyway driver to unregister.
+ *
+ * This cleans up after superhyway_register_driver(), and should be invoked in
+ * the exit path of any module drivers.
+ */
+void superhyway_unregister_driver(struct superhyway_driver *drv)
+{
+ driver_unregister(&drv->drv);
+}
+
+static int superhyway_bus_match(struct device *dev, struct device_driver *drv)
+{
+ struct superhyway_device *shyway_dev = to_superhyway_device(dev);
+ struct superhyway_driver *shyway_drv = to_superhyway_driver(drv);
+ const struct superhyway_device_id *ids = shyway_drv->id_table;
+
+ if (!ids)
+ return -EINVAL;
+ if (superhyway_match_id(ids, shyway_dev))
+ return 1;
+
+ return -ENODEV;
+}
+
+struct bus_type superhyway_bus_type = {
+ .name = "superhyway",
+ .match = superhyway_bus_match,
+};
+
+static int __init superhyway_bus_init(void)
+{
+ return bus_register(&superhyway_bus_type);
+}
+
+static void __exit superhyway_bus_exit(void)
+{
+ struct superhyway_device *dev;
+
+ list_for_each_entry(dev, &superhyway_bus.devices, node) {
+ device_unregister(&dev->dev);
+ kfree(dev);
+ }
+
+ device_unregister(&superhyway_bus.dev);
+ bus_unregister(&superhyway_bus_type);
+}
+
+core_initcall(superhyway_bus_init);
+module_exit(superhyway_bus_exit);
+
+EXPORT_SYMBOL(superhyway_bus_type);
+EXPORT_SYMBOL(superhyway_add_device);
+EXPORT_SYMBOL(superhyway_register_driver);
+EXPORT_SYMBOL(superhyway_unregister_driver);
+
+
--- linux-2.6/drivers/sh/superhyway/superhyway.ids 1970-01-01 02:00:00.000000000 +0200
+++ sh64--stable--2.6/drivers/sh/superhyway/superhyway.ids 2004-10-27 09:10:12.000000000 +0300
@@ -0,0 +1,13 @@
+#
+# This list is a compilation of SuperHyway module IDs and
+# their associated "pretty" names.
+#
+
+0x0183 "SH-5 DMA controller"
+0x1823 "SH-5 Debug module"
+0x204f "SH-5 PCI bridge"
+0x2184 "SH-5 External Memory Interface"
+0x2185 "SH-5 Flash ROM Interface"
+0x448f "SH-5 Peripheral bridge"
+0x51e2 "SH-5 CPU (SH5-101) core"
+
--- linux-2.6/include/linux/superhyway.h 1970-01-01 02:00:00.000000000 +0200
+++ sh64--stable--2.6/include/linux/superhyway.h 2004-10-27 09:10:12.000000000 +0300
@@ -0,0 +1,96 @@
+/*
+ * include/linux/superhyway.h
+ *
+ * SuperHyway Bus definitions
+ *
+ * Copyright (C) 2004 Paul Mundt <[email protected]>
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ */
+
+#ifndef __LINUX_SUPERHYWAY_H
+#define __LINUX_SUPERHYWAY_H
+
+#include <linux/device.h>
+
+/*
+ * SuperHyway IDs
+ */
+#define SUPERHYWAY_DEVICE_ID_SH5_DMAC 0x0183
+
+
+struct vcr_info {
+ u8 perr_flags; /* P-port Error flags */
+ u8 merr_flags; /* Module Error flags */
+ u16 mod_vers; /* Module Version */
+ u16 mod_id; /* Module ID */
+ u8 bot_mb; /* Bottom Memory block */
+ u8 top_mb; /* Top Memory block */
+};
+
+struct superhyway_device_id {
+ unsigned int id;
+ unsigned long driver_data;
+};
+
+struct superhyway_device;
+extern struct bus_type superhyway_bus_type;
+
+struct superhyway_driver {
+ char *name;
+
+ const struct superhyway_device_id *id_table;
+ struct device_driver drv;
+
+ int (*probe)(struct superhyway_device *dev, const struct superhyway_device_id *id);
+ void (*remove)(struct superhyway_device *dev);
+};
+
+#define to_superhyway_driver(d) container_of((d), struct superhyway_driver, drv)
+
+struct superhyway_device {
+ struct list_head node;
+
+ char name[32];
+ char pretty_name[64];
+
+ struct device dev;
+
+ struct superhyway_device_id id;
+ struct superhyway_driver *drv;
+
+ struct resource resource;
+ struct vcr_info vcr;
+};
+
+#define to_superhyway_device(d) container_of((d), struct superhyway_device, dev)
+
+struct superhyway_bus {
+ struct list_head devices;
+ struct device dev;
+ char name[16];
+};
+
+#define superhyway_get_drvdata(d) dev_get_drvdata(&(d)->dev)
+#define superhyway_set_drvdata(d,p) dev_set_drvdata(&(d)->dev, (p))
+
+/* drivers/sh/superhyway/superhyway.c */
+int superhyway_register_driver(struct superhyway_driver *);
+void superhyway_unregister_driver(struct superhyway_driver *);
+int superhyway_add_device(unsigned int, unsigned long, unsigned long long);
+
+/* drivers/sh/superhyway/superhyway-sysfs.c */
+#ifdef CONFIG_SYSFS
+void superhyway_create_sysfs_files(struct superhyway_device *);
+#else
+void superhyway_create_sysfs_files(struct superhyway_device *s)
+{
+ /* Nothing to do */
+}
+#endif
+
+#endif /* __LINUX_SUPERHYWAY_H */
+


Attachments:
(No filename) (12.88 kB)
(No filename) (189.00 B)
Download all attachments

2005-01-07 07:22:42

by Greg KH

[permalink] [raw]
Subject: Re: [PATCH] SuperHyway bus support

On Wed, Oct 27, 2004 at 10:52:48AM +0300, Paul Mundt wrote:
> This adds support for the SuperHyway bus currently used by sh64 and also used
> by newer sh4a cores. This just adds the common bus support, with things like
> bus scanning being architecture dependent. sh64 presently makes use of this
> for its DMAC, with further device support planned.

So it looks like you are just adding a fake "bus" driver and then
manually adding the bus devices to the root device. Why not just
complete the conversion and register the real devices properly?

A few other comments on the patch:

> --- linux-2.6/drivers/sh/superhyway/Makefile 1970-01-01 02:00:00.000000000 +0200
> +++ sh64--stable--2.6/drivers/sh/superhyway/Makefile 2004-10-27 09:10:12.000000000 +0300
> @@ -0,0 +1,18 @@
> +#
> +# Makefile for the SuperHyway bus drivers.
> +#
> +
> +obj-$(CONFIG_SUPERHYWAY) += superhyway.o
> +obj-$(CONFIG_SYSFS) += superhyway-sysfs.o
> +
> +clean-files := devlist.h
> +
> +$(obj)/superhyway.o: $(obj)/devlist.h
> +
> +quiet_cmd_devlist = GEN $@
> + cmd_devlist = sed -e 's/^\#.*$$//g;s/^[ ].*$$//g;/^$$/d; \
> + s/\(0x.*\) / { \1, /g;s/$$/ },/' < $< > $@
> +
> +$(obj)/devlist.h: $(src)/superhyway.ids
> + $(call cmd,devlist)

We are depreciating device lists within the kernel. The PCI device list
will be going away sometime in the future, and we shouldn't be adding
new ones. Can't this just be determined from userspace instead like
'lspci' and 'lsusb' do?

> +void superhyway_create_sysfs_files(struct superhyway_device *s)
> +{
> + struct device *dev = &s->dev;
> +
> + device_create_file(dev, &dev_attr_perr_flags);
> + device_create_file(dev, &dev_attr_merr_flags);
> + device_create_file(dev, &dev_attr_mod_vers);
> + device_create_file(dev, &dev_attr_mod_id);
> + device_create_file(dev, &dev_attr_bot_mb);
> + device_create_file(dev, &dev_attr_top_mb);
> + device_create_file(dev, &dev_attr_resource);

Can you use a default attribute list instead of manually creating the
files individually? Also, I don't see the code that removes these
attributes. Please don't rely on the sysfs function of automatically
cleaning up the attributes when the device is removed, that might not
work in the future.

> +static struct superhyway_bus superhyway_bus = {
> + .name = "SuperHyway bus",
> +};

Please don't add sysfs directories that have spaces in them. How about
"superhyway_bus" instead?

> +/**
> + * superhyway_add_device - Add a SuperHyway module
> + * @mod_id: Module ID (taken from MODULE.VCR.MOD_ID).
> + * @base: Physical address where module is mapped.
> + * @vcr: VCR value.
> + *
> + * This is responsible for adding a new SuperHyway module. This sets up a new
> + * struct superhyway_device for the module being added. Each one of @mod_id,
> + * @base, and @vcr are registered with the new device for further use
> + * elsewhere.
> + *
> + * Devices are initially added in the order that they are scanned (from the
> + * top-down of the memory map), and are assigned an ID based on the order that
> + * they are added. Any manual addition of a module will thus get the ID after
> + * the devices already discovered regardless of where it resides in memory.
> + *
> + * Further work can and should be done in superhyway_scan_bus(), to be sure
> + * that any new modules are properly discovered and subsequently registered.
> + */
> +int superhyway_add_device(unsigned int mod_id, unsigned long base,
> + unsigned long long vcr)
> +{
> + struct superhyway_device *dev;
> + int ret;
> +
> + dev = kmalloc(sizeof(struct superhyway_device), GFP_KERNEL);
> + if (!dev)
> + return -ENOMEM;
> +
> + memset(dev, 0, sizeof(struct superhyway_device));
> +
> + dev->id.id = mod_id;
> + sprintf(dev->name, "SuperHyway device %04x\n", dev->id.id);
> +
> + superhyway_name_device(dev);
> +
> + dev->vcr = *((struct vcr_info *)(&vcr));
> + dev->resource.name = dev->name;
> + dev->resource.start = base;
> + dev->resource.end = dev->resource.start + 0x01000000;
> + dev->dev.parent = &superhyway_bus.dev;
> + dev->dev.bus = &superhyway_bus_type;
> +
> + sprintf(dev->dev.bus_id, "%02x", superhyway_devices);
> +
> + pr_info(" 0x%04x (%s) control block at 0x%08lx\n",
> + dev->id.id, dev->pretty_name, dev->resource.start);

Shouldn't this be a debug message?

> +static void __exit superhyway_bus_exit(void)
> +{
> + struct superhyway_device *dev;
> +
> + list_for_each_entry(dev, &superhyway_bus.devices, node) {
> + device_unregister(&dev->dev);
> + kfree(dev);
> + }

Ick, not good, userspace could still have a reference on the device
through sysfs. Don't kfree it here, do it in the release function
(which you need to do.)

Also, why have a local list of devices and not just use the list the
driver core provides for you?

> +struct superhyway_device {
> + struct list_head node;
> +
> + char name[32];
> + char pretty_name[64];

Do you need the name and pretty_name?

> +struct superhyway_bus {
> + struct list_head devices;
> + struct device dev;
> + char name[16];
> +};

Is the name really necessary?

> +/* drivers/sh/superhyway/superhyway-sysfs.c */
> +#ifdef CONFIG_SYSFS
> +void superhyway_create_sysfs_files(struct superhyway_device *);
> +#else
> +void superhyway_create_sysfs_files(struct superhyway_device *s)
> +{
> + /* Nothing to do */
> +}
> +#endif

Why ifdef this function? That should not be needed.

thanks,

greg k-h

2005-01-07 09:43:55

by Paul Mundt

[permalink] [raw]
Subject: Re: [PATCH] SuperHyway bus support

On Thu, Jan 06, 2005 at 11:22:22PM -0800, Greg KH wrote:
> So it looks like you are just adding a fake "bus" driver and then
> manually adding the bus devices to the root device. Why not just
> complete the conversion and register the real devices properly?
>
Can you elaborate on what you mean by registering the "real devices properly"?

> We are depreciating device lists within the kernel. The PCI device list
> will be going away sometime in the future, and we shouldn't be adding
> new ones. Can't this just be determined from userspace instead like
> 'lspci' and 'lsusb' do?
>
Yes, this can be done in userspace, so that stuff can be dropped.

> > +void superhyway_create_sysfs_files(struct superhyway_device *s)
> > +{
> > + struct device *dev = &s->dev;
> > +
> > + device_create_file(dev, &dev_attr_perr_flags);
> > + device_create_file(dev, &dev_attr_merr_flags);
> > + device_create_file(dev, &dev_attr_mod_vers);
> > + device_create_file(dev, &dev_attr_mod_id);
> > + device_create_file(dev, &dev_attr_bot_mb);
> > + device_create_file(dev, &dev_attr_top_mb);
> > + device_create_file(dev, &dev_attr_resource);
>
> Can you use a default attribute list instead of manually creating the
> files individually? Also, I don't see the code that removes these
> attributes. Please don't rely on the sysfs function of automatically
> cleaning up the attributes when the device is removed, that might not
> work in the future.
>
Yes, I can use the dev_attrs for this. Thanks for pointing that out.

> > +static struct superhyway_bus superhyway_bus = {
> > + .name = "SuperHyway bus",
> > +};
>
> Please don't add sysfs directories that have spaces in them. How about
> "superhyway_bus" instead?
>
Ok.

> > + pr_info(" 0x%04x (%s) control block at 0x%08lx\n",
> > + dev->id.id, dev->pretty_name, dev->resource.start);
>
> Shouldn't this be a debug message?
>
Yes, probably. Though with the devlist in userspace I suppose it's not overly
useful to have here anyways.

> > +static void __exit superhyway_bus_exit(void)
> > +{
> > + struct superhyway_device *dev;
> > +
> > + list_for_each_entry(dev, &superhyway_bus.devices, node) {
> > + device_unregister(&dev->dev);
> > + kfree(dev);
> > + }
>
> Ick, not good, userspace could still have a reference on the device
> through sysfs. Don't kfree it here, do it in the release function
> (which you need to do.)
>
Ok.

> Also, why have a local list of devices and not just use the list the
> driver core provides for you?
>
Probably because I wasn't aware that the driver core provided one. Now that I
see the bus_for_each_xxx() stuff I'll drop the list and use that instead.

> > +struct superhyway_device {
> > + struct list_head node;
> > +
> > + char name[32];
> > + char pretty_name[64];
>
> Do you need the name and pretty_name?
>
No, the pretty_name was only added for the devlist. I'll clean that up.

> > +struct superhyway_bus {
> > + struct list_head devices;
> > + struct device dev;
> > + char name[16];
> > +};
>
> Is the name really necessary?
>
Probably not. With that and the list gone I can drop this struct entirely and
just have the root device as a struct device.

> > +/* drivers/sh/superhyway/superhyway-sysfs.c */
> > +#ifdef CONFIG_SYSFS
> > +void superhyway_create_sysfs_files(struct superhyway_device *);
> > +#else
> > +void superhyway_create_sysfs_files(struct superhyway_device *s)
> > +{
> > + /* Nothing to do */
> > +}
> > +#endif
>
> Why ifdef this function? That should not be needed.
>
superhyway_add_device() calls this. We don't want to assume that CONFIG_SYSFS
will always be enabled. I can move the ifdef in to superhyway_add_device() if
you think it would be cleaner. (And this is needed as we happen to have
superhyway_create_sysfs_files() defined in superhyway-sysfs.c which is only
compiled in when CONFIG_SYSFS is set, and I would rather not link this in
unconditionally).

Thanks for looking at this, I'll post a cleaned up version shortly.


Attachments:
(No filename) (3.88 kB)
(No filename) (189.00 B)
Download all attachments

2005-01-07 16:33:51

by Paul Mundt

[permalink] [raw]
Subject: Re: [PATCH] SuperHyway bus support

On Fri, Jan 07, 2005 at 11:41:04AM +0200, Paul Mundt wrote:
> > Also, why have a local list of devices and not just use the list the
> > driver core provides for you?
> >
> Probably because I wasn't aware that the driver core provided one. Now that I
> see the bus_for_each_xxx() stuff I'll drop the list and use that instead.
>
I dropped this entirely as the release() stuff did what I was looking for..

> Thanks for looking at this, I'll post a cleaned up version shortly.

Here it is against current BK.. let me know if you have any other issues.

Signed-off-by: Paul Mundt <[email protected]>

drivers/Makefile | 1
drivers/sh/Makefile | 6
drivers/sh/superhyway/Makefile | 7 +
drivers/sh/superhyway/superhyway-sysfs.c | 47 +++++++
drivers/sh/superhyway/superhyway.c | 205 +++++++++++++++++++++++++++++++
5 files changed, 266 insertions(+)

--- linux-2.6/drivers/Makefile 2004-12-31 03:37:37.000000000 +0200
+++ linux-sh64-2.6/drivers/Makefile 2005-01-07 18:18:42.055174960 +0200
@@ -62,3 +62,4 @@
obj-$(CONFIG_INFINIBAND) += infiniband/
obj-y += firmware/
obj-$(CONFIG_CRYPTO) += crypto/
+obj-$(CONFIG_SUPERH) += sh/
diff -urN linux-2.6/drivers/sh/Makefile linux-sh64-2.6/drivers/sh/Makefile
--- linux-2.6/drivers/sh/Makefile 1970-01-01 02:00:00.000000000 +0200
+++ linux-sh64-2.6/drivers/sh/Makefile 2004-12-07 14:16:02.000000000 +0200
@@ -0,0 +1,6 @@
+#
+# Makefile for the SuperH specific drivers.
+#
+
+obj-$(CONFIG_SUPERHYWAY) += superhyway/
+
diff -urN linux-2.6/drivers/sh/superhyway/Makefile linux-sh64-2.6/drivers/sh/superhyway/Makefile
--- linux-2.6/drivers/sh/superhyway/Makefile 1970-01-01 02:00:00.000000000 +0200
+++ linux-sh64-2.6/drivers/sh/superhyway/Makefile 2005-01-07 18:19:26.394434368 +0200
@@ -0,0 +1,7 @@
+#
+# Makefile for the SuperHyway bus drivers.
+#
+
+obj-$(CONFIG_SUPERHYWAY) += superhyway.o
+obj-$(CONFIG_SYSFS) += superhyway-sysfs.o
+
diff -urN linux-2.6/drivers/sh/superhyway/superhyway.c linux-sh64-2.6/drivers/sh/superhyway/superhyway.c
--- linux-2.6/drivers/sh/superhyway/superhyway.c 1970-01-01 02:00:00.000000000 +0200
+++ linux-sh64-2.6/drivers/sh/superhyway/superhyway.c 2005-01-07 18:15:08.102700680 +0200
@@ -0,0 +1,205 @@
+/*
+ * drivers/sh/superhyway/superhyway.c
+ *
+ * SuperHyway Bus Driver
+ *
+ * Copyright (C) 2004, 2005 Paul Mundt <[email protected]>
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/device.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/list.h>
+#include <linux/superhyway.h>
+
+static int superhyway_devices;
+
+static struct device superhyway_bus_device = {
+ .bus_id = "superhyway",
+};
+
+static void superhyway_device_release(struct device *dev)
+{
+ kfree(to_superhyway_device(dev));
+}
+
+/**
+ * superhyway_add_device - Add a SuperHyway module
+ * @mod_id: Module ID (taken from MODULE.VCR.MOD_ID).
+ * @base: Physical address where module is mapped.
+ * @vcr: VCR value.
+ *
+ * This is responsible for adding a new SuperHyway module. This sets up a new
+ * struct superhyway_device for the module being added. Each one of @mod_id,
+ * @base, and @vcr are registered with the new device for further use
+ * elsewhere.
+ *
+ * Devices are initially added in the order that they are scanned (from the
+ * top-down of the memory map), and are assigned an ID based on the order that
+ * they are added. Any manual addition of a module will thus get the ID after
+ * the devices already discovered regardless of where it resides in memory.
+ *
+ * Further work can and should be done in superhyway_scan_bus(), to be sure
+ * that any new modules are properly discovered and subsequently registered.
+ */
+int superhyway_add_device(unsigned int mod_id, unsigned long base,
+ unsigned long long vcr)
+{
+ struct superhyway_device *dev;
+
+ dev = kmalloc(sizeof(struct superhyway_device), GFP_KERNEL);
+ if (!dev)
+ return -ENOMEM;
+
+ memset(dev, 0, sizeof(struct superhyway_device));
+
+ dev->id.id = mod_id;
+ sprintf(dev->name, "SuperHyway device %04x", dev->id.id);
+
+ dev->vcr = *((struct vcr_info *)(&vcr));
+ dev->resource.name = dev->name;
+ dev->resource.start = base;
+ dev->resource.end = dev->resource.start + 0x01000000;
+ dev->dev.parent = &superhyway_bus_device;
+ dev->dev.bus = &superhyway_bus_type;
+ dev->dev.release = superhyway_device_release;
+
+ sprintf(dev->dev.bus_id, "%02x", superhyway_devices);
+
+ superhyway_devices++;
+
+ return device_register(&dev->dev);
+}
+
+static int __init superhyway_init(void)
+{
+ extern int superhyway_scan_bus(void);
+
+ device_register(&superhyway_bus_device);
+
+ return superhyway_scan_bus();
+}
+
+postcore_initcall(superhyway_init);
+
+static const struct superhyway_device_id *
+superhyway_match_id(const struct superhyway_device_id *ids,
+ struct superhyway_device *dev)
+{
+ while (ids->id) {
+ if (ids->id == dev->id.id)
+ return ids;
+
+ ids++;
+ }
+
+ return NULL;
+}
+
+static int superhyway_device_probe(struct device *dev)
+{
+ struct superhyway_device *shyway_dev = to_superhyway_device(dev);
+ struct superhyway_driver *shyway_drv = to_superhyway_driver(dev->driver);
+
+ if (shyway_drv && shyway_drv->probe) {
+ const struct superhyway_device_id *id;
+
+ id = superhyway_match_id(shyway_drv->id_table, shyway_dev);
+ if (id)
+ return shyway_drv->probe(shyway_dev, id);
+ }
+
+ return -ENODEV;
+}
+
+static int superhyway_device_remove(struct device *dev)
+{
+ struct superhyway_device *shyway_dev = to_superhyway_device(dev);
+ struct superhyway_driver *shyway_drv = to_superhyway_driver(dev->driver);
+
+ if (shyway_drv && shyway_drv->remove) {
+ shyway_drv->remove(shyway_dev);
+ return 0;
+ }
+
+ return -ENODEV;
+}
+
+/**
+ * superhyway_register_driver - Register a new SuperHyway driver
+ * @drv: SuperHyway driver to register.
+ *
+ * This registers the passed in @drv. Any devices matching the id table will
+ * automatically be populated and handed off to the driver's specified probe
+ * routine.
+ */
+int superhyway_register_driver(struct superhyway_driver *drv)
+{
+ drv->drv.name = drv->name;
+ drv->drv.bus = &superhyway_bus_type;
+ drv->drv.probe = superhyway_device_probe;
+ drv->drv.remove = superhyway_device_remove;
+
+ return driver_register(&drv->drv);
+}
+
+/**
+ * superhyway_unregister_driver - Unregister a SuperHyway driver
+ * @drv: SuperHyway driver to unregister.
+ *
+ * This cleans up after superhyway_register_driver(), and should be invoked in
+ * the exit path of any module drivers.
+ */
+void superhyway_unregister_driver(struct superhyway_driver *drv)
+{
+ driver_unregister(&drv->drv);
+}
+
+static int superhyway_bus_match(struct device *dev, struct device_driver *drv)
+{
+ struct superhyway_device *shyway_dev = to_superhyway_device(dev);
+ struct superhyway_driver *shyway_drv = to_superhyway_driver(drv);
+ const struct superhyway_device_id *ids = shyway_drv->id_table;
+
+ if (!ids)
+ return -EINVAL;
+ if (superhyway_match_id(ids, shyway_dev))
+ return 1;
+
+ return -ENODEV;
+}
+
+struct bus_type superhyway_bus_type = {
+ .name = "superhyway",
+ .match = superhyway_bus_match,
+#ifdef CONFIG_SYSFS
+ .dev_attrs = superhyway_dev_attrs,
+#endif
+};
+
+static int __init superhyway_bus_init(void)
+{
+ return bus_register(&superhyway_bus_type);
+}
+
+static void __exit superhyway_bus_exit(void)
+{
+ device_unregister(&superhyway_bus_device);
+ bus_unregister(&superhyway_bus_type);
+}
+
+core_initcall(superhyway_bus_init);
+module_exit(superhyway_bus_exit);
+
+EXPORT_SYMBOL(superhyway_bus_type);
+EXPORT_SYMBOL(superhyway_add_device);
+EXPORT_SYMBOL(superhyway_register_driver);
+EXPORT_SYMBOL(superhyway_unregister_driver);
+
diff -urN linux-2.6/drivers/sh/superhyway/superhyway-sysfs.c linux-sh64-2.6/drivers/sh/superhyway/superhyway-sysfs.c
--- linux-2.6/drivers/sh/superhyway/superhyway-sysfs.c 1970-01-01 02:00:00.000000000 +0200
+++ linux-sh64-2.6/drivers/sh/superhyway/superhyway-sysfs.c 2005-01-07 18:08:57.463046472 +0200
@@ -0,0 +1,47 @@
+/*
+ * drivers/sh/superhyway/superhyway-sysfs.c
+ *
+ * SuperHyway Bus sysfs interface
+ *
+ * Copyright (C) 2004, 2005 Paul Mundt <[email protected]>
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/device.h>
+#include <linux/types.h>
+#include <linux/superhyway.h>
+
+#define superhyway_ro_attr(name, fmt, field) \
+static ssize_t name##_show(struct device *dev, char *buf) \
+{ \
+ struct superhyway_device *s = to_superhyway_device(dev); \
+ return sprintf(buf, fmt, s->field); \
+}
+
+/* VCR flags */
+superhyway_ro_attr(perr_flags, "0x%02x\n", vcr.perr_flags);
+superhyway_ro_attr(merr_flags, "0x%02x\n", vcr.merr_flags);
+superhyway_ro_attr(mod_vers, "0x%04x\n", vcr.mod_vers);
+superhyway_ro_attr(mod_id, "0x%04x\n", vcr.mod_id);
+superhyway_ro_attr(bot_mb, "0x%02x\n", vcr.bot_mb);
+superhyway_ro_attr(top_mb, "0x%02x\n", vcr.top_mb);
+
+/* Misc */
+superhyway_ro_attr(resource, "0x%08lx\n", resource.start);
+
+struct device_attribute superhyway_dev_attrs[] = {
+ __ATTR_RO(perr_flags),
+ __ATTR_RO(merr_flags),
+ __ATTR_RO(mod_vers),
+ __ATTR_RO(mod_id),
+ __ATTR_RO(bot_mb),
+ __ATTR_RO(top_mb),
+ __ATTR_RO(resource),
+ __ATTR_NULL,
+};
+


Attachments:
(No filename) (9.34 kB)
(No filename) (189.00 B)
Download all attachments

2005-01-12 08:21:37

by Greg KH

[permalink] [raw]
Subject: Re: [PATCH] SuperHyway bus support

On Fri, Jan 07, 2005 at 06:29:45PM +0200, Paul Mundt wrote:
> On Fri, Jan 07, 2005 at 11:41:04AM +0200, Paul Mundt wrote:
> > > Also, why have a local list of devices and not just use the list the
> > > driver core provides for you?
> > >
> > Probably because I wasn't aware that the driver core provided one. Now that I
> > see the bus_for_each_xxx() stuff I'll drop the list and use that instead.
> >
> I dropped this entirely as the release() stuff did what I was looking for..
>
> > Thanks for looking at this, I'll post a cleaned up version shortly.
>
> Here it is against current BK.. let me know if you have any other issues.
>
> Signed-off-by: Paul Mundt <[email protected]>
>
> drivers/Makefile | 1
> drivers/sh/Makefile | 6
> drivers/sh/superhyway/Makefile | 7 +
> drivers/sh/superhyway/superhyway-sysfs.c | 47 +++++++
> drivers/sh/superhyway/superhyway.c | 205 +++++++++++++++++++++++++++++++

No Kconfig file to enable this option?

> +static struct device superhyway_bus_device = {
> + .bus_id = "superhyway",
> +};

This device doesn't have a release function, as it's tied to the module.
Are you sure it's race free? :)

> +static int __init superhyway_init(void)
> +{
> + extern int superhyway_scan_bus(void);

This should go in a .h file somewhere.

> +EXPORT_SYMBOL(superhyway_bus_type);
> +EXPORT_SYMBOL(superhyway_add_device);
> +EXPORT_SYMBOL(superhyway_register_driver);
> +EXPORT_SYMBOL(superhyway_unregister_driver);

Did you forget a .h file with these function prototypes?

Other than that, looks a whole lot better, nice job.

greg k-h

2005-01-12 12:56:11

by Paul Mundt

[permalink] [raw]
Subject: Re: [PATCH] SuperHyway bus support

On Wed, Jan 12, 2005 at 12:17:22AM -0800, Greg KH wrote:
> > drivers/Makefile | 1
> > drivers/sh/Makefile | 6
> > drivers/sh/superhyway/Makefile | 7 +
> > drivers/sh/superhyway/superhyway-sysfs.c | 47 +++++++
> > drivers/sh/superhyway/superhyway.c | 205 +++++++++++++++++++++++++++++++
>
> No Kconfig file to enable this option?
>
It's in the arch-specific code, it will go in with the next sh64 update.
Though I can always add a drivers/sh/Kconfig that does this too (I didn't
think it was worth the trouble for a single option at the moment).

> > +static struct device superhyway_bus_device = {
> > + .bus_id = "superhyway",
> > +};
>
> This device doesn't have a release function, as it's tied to the module.
> Are you sure it's race free? :)
>
I wasn't aware that it needed one. I copied this mostly verbatim from the
platform bus code where there is also no release function.

Looking at some of the other bus drivers, I see that w1 makes use of a release
function for its bus device, but it does this only for completion handling in
a kernel thread, which clearly has no application here.

The only thing I would see a release routine being useful for in this case
would be for refcounting, but the driver core already does that for us. Is
there something obvious that I'm missing?

> > +static int __init superhyway_init(void)
> > +{
> > + extern int superhyway_scan_bus(void);
>
> This should go in a .h file somewhere.
>
Done.

> > +EXPORT_SYMBOL(superhyway_bus_type);
> > +EXPORT_SYMBOL(superhyway_add_device);
> > +EXPORT_SYMBOL(superhyway_register_driver);
> > +EXPORT_SYMBOL(superhyway_unregister_driver);
>
> Did you forget a .h file with these function prototypes?
>
Yes, it would seem that way. Here we go again:

drivers/sh/Makefile | 6
drivers/sh/superhyway/Makefile | 7 +
drivers/sh/superhyway/superhyway-sysfs.c | 45 ++++++
drivers/sh/superhyway/superhyway.c | 201 +++++++++++++++++++++++++++++++
include/linux/superhyway.h | 79 ++++++++++++
5 files changed, 338 insertions(+)

diff -urN linux-2.6/drivers/sh/Makefile linux-sh64-2.6/drivers/sh/Makefile
--- linux-2.6/drivers/sh/Makefile 1970-01-01 02:00:00.000000000 +0200
+++ linux-sh64-2.6/drivers/sh/Makefile 2004-12-07 14:16:02.000000000 +0200
@@ -0,0 +1,6 @@
+#
+# Makefile for the SuperH specific drivers.
+#
+
+obj-$(CONFIG_SUPERHYWAY) += superhyway/
+
diff -urN linux-2.6/drivers/sh/superhyway/Makefile linux-sh64-2.6/drivers/sh/superhyway/Makefile
--- linux-2.6/drivers/sh/superhyway/Makefile 1970-01-01 02:00:00.000000000 +0200
+++ linux-sh64-2.6/drivers/sh/superhyway/Makefile 2005-01-07 18:19:26.000000000 +0200
@@ -0,0 +1,7 @@
+#
+# Makefile for the SuperHyway bus drivers.
+#
+
+obj-$(CONFIG_SUPERHYWAY) += superhyway.o
+obj-$(CONFIG_SYSFS) += superhyway-sysfs.o
+
diff -urN linux-2.6/drivers/sh/superhyway/superhyway.c linux-sh64-2.6/drivers/sh/superhyway/superhyway.c
--- linux-2.6/drivers/sh/superhyway/superhyway.c 1970-01-01 02:00:00.000000000 +0200
+++ linux-sh64-2.6/drivers/sh/superhyway/superhyway.c 2005-01-12 14:37:54.675100400 +0200
@@ -0,0 +1,201 @@
+/*
+ * drivers/sh/superhyway/superhyway.c
+ *
+ * SuperHyway Bus Driver
+ *
+ * Copyright (C) 2004, 2005 Paul Mundt <[email protected]>
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ */
+#include <linux/kernel.h>
+#include <linux/device.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/list.h>
+#include <linux/superhyway.h>
+
+static int superhyway_devices;
+
+static struct device superhyway_bus_device = {
+ .bus_id = "superhyway",
+};
+
+static void superhyway_device_release(struct device *dev)
+{
+ kfree(to_superhyway_device(dev));
+}
+
+/**
+ * superhyway_add_device - Add a SuperHyway module
+ * @mod_id: Module ID (taken from MODULE.VCR.MOD_ID).
+ * @base: Physical address where module is mapped.
+ * @vcr: VCR value.
+ *
+ * This is responsible for adding a new SuperHyway module. This sets up a new
+ * struct superhyway_device for the module being added. Each one of @mod_id,
+ * @base, and @vcr are registered with the new device for further use
+ * elsewhere.
+ *
+ * Devices are initially added in the order that they are scanned (from the
+ * top-down of the memory map), and are assigned an ID based on the order that
+ * they are added. Any manual addition of a module will thus get the ID after
+ * the devices already discovered regardless of where it resides in memory.
+ *
+ * Further work can and should be done in superhyway_scan_bus(), to be sure
+ * that any new modules are properly discovered and subsequently registered.
+ */
+int superhyway_add_device(unsigned int mod_id, unsigned long base,
+ unsigned long long vcr)
+{
+ struct superhyway_device *dev;
+
+ dev = kmalloc(sizeof(struct superhyway_device), GFP_KERNEL);
+ if (!dev)
+ return -ENOMEM;
+
+ memset(dev, 0, sizeof(struct superhyway_device));
+
+ dev->id.id = mod_id;
+ sprintf(dev->name, "SuperHyway device %04x", dev->id.id);
+
+ dev->vcr = *((struct vcr_info *)(&vcr));
+ dev->resource.name = dev->name;
+ dev->resource.start = base;
+ dev->resource.end = dev->resource.start + 0x01000000;
+ dev->dev.parent = &superhyway_bus_device;
+ dev->dev.bus = &superhyway_bus_type;
+ dev->dev.release = superhyway_device_release;
+
+ sprintf(dev->dev.bus_id, "%02x", superhyway_devices);
+
+ superhyway_devices++;
+
+ return device_register(&dev->dev);
+}
+
+static int __init superhyway_init(void)
+{
+ device_register(&superhyway_bus_device);
+ return superhyway_scan_bus();
+}
+
+postcore_initcall(superhyway_init);
+
+static const struct superhyway_device_id *
+superhyway_match_id(const struct superhyway_device_id *ids,
+ struct superhyway_device *dev)
+{
+ while (ids->id) {
+ if (ids->id == dev->id.id)
+ return ids;
+
+ ids++;
+ }
+
+ return NULL;
+}
+
+static int superhyway_device_probe(struct device *dev)
+{
+ struct superhyway_device *shyway_dev = to_superhyway_device(dev);
+ struct superhyway_driver *shyway_drv = to_superhyway_driver(dev->driver);
+
+ if (shyway_drv && shyway_drv->probe) {
+ const struct superhyway_device_id *id;
+
+ id = superhyway_match_id(shyway_drv->id_table, shyway_dev);
+ if (id)
+ return shyway_drv->probe(shyway_dev, id);
+ }
+
+ return -ENODEV;
+}
+
+static int superhyway_device_remove(struct device *dev)
+{
+ struct superhyway_device *shyway_dev = to_superhyway_device(dev);
+ struct superhyway_driver *shyway_drv = to_superhyway_driver(dev->driver);
+
+ if (shyway_drv && shyway_drv->remove) {
+ shyway_drv->remove(shyway_dev);
+ return 0;
+ }
+
+ return -ENODEV;
+}
+
+/**
+ * superhyway_register_driver - Register a new SuperHyway driver
+ * @drv: SuperHyway driver to register.
+ *
+ * This registers the passed in @drv. Any devices matching the id table will
+ * automatically be populated and handed off to the driver's specified probe
+ * routine.
+ */
+int superhyway_register_driver(struct superhyway_driver *drv)
+{
+ drv->drv.name = drv->name;
+ drv->drv.bus = &superhyway_bus_type;
+ drv->drv.probe = superhyway_device_probe;
+ drv->drv.remove = superhyway_device_remove;
+
+ return driver_register(&drv->drv);
+}
+
+/**
+ * superhyway_unregister_driver - Unregister a SuperHyway driver
+ * @drv: SuperHyway driver to unregister.
+ *
+ * This cleans up after superhyway_register_driver(), and should be invoked in
+ * the exit path of any module drivers.
+ */
+void superhyway_unregister_driver(struct superhyway_driver *drv)
+{
+ driver_unregister(&drv->drv);
+}
+
+static int superhyway_bus_match(struct device *dev, struct device_driver *drv)
+{
+ struct superhyway_device *shyway_dev = to_superhyway_device(dev);
+ struct superhyway_driver *shyway_drv = to_superhyway_driver(drv);
+ const struct superhyway_device_id *ids = shyway_drv->id_table;
+
+ if (!ids)
+ return -EINVAL;
+ if (superhyway_match_id(ids, shyway_dev))
+ return 1;
+
+ return -ENODEV;
+}
+
+struct bus_type superhyway_bus_type = {
+ .name = "superhyway",
+ .match = superhyway_bus_match,
+#ifdef CONFIG_SYSFS
+ .dev_attrs = superhyway_dev_attrs,
+#endif
+};
+
+static int __init superhyway_bus_init(void)
+{
+ return bus_register(&superhyway_bus_type);
+}
+
+static void __exit superhyway_bus_exit(void)
+{
+ device_unregister(&superhyway_bus_device);
+ bus_unregister(&superhyway_bus_type);
+}
+
+core_initcall(superhyway_bus_init);
+module_exit(superhyway_bus_exit);
+
+EXPORT_SYMBOL(superhyway_bus_type);
+EXPORT_SYMBOL(superhyway_add_device);
+EXPORT_SYMBOL(superhyway_register_driver);
+EXPORT_SYMBOL(superhyway_unregister_driver);
+
+MODULE_LICENSE("GPL");
diff -urN linux-2.6/drivers/sh/superhyway/superhyway-sysfs.c linux-sh64-2.6/drivers/sh/superhyway/superhyway-sysfs.c
--- linux-2.6/drivers/sh/superhyway/superhyway-sysfs.c 1970-01-01 02:00:00.000000000 +0200
+++ linux-sh64-2.6/drivers/sh/superhyway/superhyway-sysfs.c 2005-01-12 14:38:00.443223512 +0200
@@ -0,0 +1,45 @@
+/*
+ * drivers/sh/superhyway/superhyway-sysfs.c
+ *
+ * SuperHyway Bus sysfs interface
+ *
+ * Copyright (C) 2004, 2005 Paul Mundt <[email protected]>
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ */
+#include <linux/kernel.h>
+#include <linux/device.h>
+#include <linux/types.h>
+#include <linux/superhyway.h>
+
+#define superhyway_ro_attr(name, fmt, field) \
+static ssize_t name##_show(struct device *dev, char *buf) \
+{ \
+ struct superhyway_device *s = to_superhyway_device(dev); \
+ return sprintf(buf, fmt, s->field); \
+}
+
+/* VCR flags */
+superhyway_ro_attr(perr_flags, "0x%02x\n", vcr.perr_flags);
+superhyway_ro_attr(merr_flags, "0x%02x\n", vcr.merr_flags);
+superhyway_ro_attr(mod_vers, "0x%04x\n", vcr.mod_vers);
+superhyway_ro_attr(mod_id, "0x%04x\n", vcr.mod_id);
+superhyway_ro_attr(bot_mb, "0x%02x\n", vcr.bot_mb);
+superhyway_ro_attr(top_mb, "0x%02x\n", vcr.top_mb);
+
+/* Misc */
+superhyway_ro_attr(resource, "0x%08lx\n", resource.start);
+
+struct device_attribute superhyway_dev_attrs[] = {
+ __ATTR_RO(perr_flags),
+ __ATTR_RO(merr_flags),
+ __ATTR_RO(mod_vers),
+ __ATTR_RO(mod_id),
+ __ATTR_RO(bot_mb),
+ __ATTR_RO(top_mb),
+ __ATTR_RO(resource),
+ __ATTR_NULL,
+};
+
--- linux-2.6/include/linux/superhyway.h 2005-01-12 14:43:04.969928416 +0200
+++ linux-sh64-2.6/include/linux/superhyway.h 2005-01-12 14:43:37.278016840 +0200
@@ -0,0 +1,79 @@
+/*
+ * include/linux/superhyway.h
+ *
+ * SuperHyway Bus definitions
+ *
+ * Copyright (C) 2004, 2005 Paul Mundt <[email protected]>
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ */
+#ifndef __LINUX_SUPERHYWAY_H
+#define __LINUX_SUPERHYWAY_H
+
+#include <linux/device.h>
+
+/*
+ * SuperHyway IDs
+ */
+#define SUPERHYWAY_DEVICE_ID_SH5_DMAC 0x0183
+
+struct vcr_info {
+ u8 perr_flags; /* P-port Error flags */
+ u8 merr_flags; /* Module Error flags */
+ u16 mod_vers; /* Module Version */
+ u16 mod_id; /* Module ID */
+ u8 bot_mb; /* Bottom Memory block */
+ u8 top_mb; /* Top Memory block */
+};
+
+struct superhyway_device_id {
+ unsigned int id;
+ unsigned long driver_data;
+};
+
+struct superhyway_device;
+extern struct bus_type superhyway_bus_type;
+
+struct superhyway_driver {
+ char *name;
+
+ const struct superhyway_device_id *id_table;
+ struct device_driver drv;
+
+ int (*probe)(struct superhyway_device *dev, const struct superhyway_device_id *id);
+ void (*remove)(struct superhyway_device *dev);
+};
+
+#define to_superhyway_driver(d) container_of((d), struct superhyway_driver, drv)
+
+struct superhyway_device {
+ char name[32];
+
+ struct device dev;
+
+ struct superhyway_device_id id;
+ struct superhyway_driver *drv;
+
+ struct resource resource;
+ struct vcr_info vcr;
+};
+
+#define to_superhyway_device(d) container_of((d), struct superhyway_device, dev)
+
+#define superhyway_get_drvdata(d) dev_get_drvdata(&(d)->dev)
+#define superhyway_set_drvdata(d,p) dev_set_drvdata(&(d)->dev, (p))
+
+extern int superhyway_scan_bus(void);
+
+/* drivers/sh/superhyway/superhyway.c */
+int superhyway_register_driver(struct superhyway_driver *);
+void superhyway_unregister_driver(struct superhyway_driver *);
+int superhyway_add_device(unsigned int, unsigned long, unsigned long long);
+
+/* drivers/sh/superhyway/superhyway-sysfs.c */
+extern struct device_attribute superhyway_dev_attrs[];
+
+#endif /* __LINUX_SUPERHYWAY_H */
+


Attachments:
(No filename) (12.45 kB)
(No filename) (189.00 B)
Download all attachments

2005-01-25 14:16:00

by Paul Mundt

[permalink] [raw]
Subject: Re: [PATCH] SuperHyway bus support

On Wed, Jan 12, 2005 at 02:48:36PM +0200, Paul Mundt wrote:
> > Did you forget a .h file with these function prototypes?
> >
> Yes, it would seem that way. Here we go again:
>
I haven't heard anything else from you about this since the last update,
do you have any more issues with this code? If not, can you merge this?


Attachments:
(No filename) (323.00 B)
(No filename) (189.00 B)
Download all attachments

2005-01-25 20:33:31

by Greg KH

[permalink] [raw]
Subject: Re: [PATCH] SuperHyway bus support

On Tue, Jan 25, 2005 at 04:08:44PM +0200, Paul Mundt wrote:
> On Wed, Jan 12, 2005 at 02:48:36PM +0200, Paul Mundt wrote:
> > > Did you forget a .h file with these function prototypes?
> > >
> > Yes, it would seem that way. Here we go again:
> >
> I haven't heard anything else from you about this since the last update,
> do you have any more issues with this code? If not, can you merge this?

I don't have any more issues, it's in my TODO queue, and I should get to
it tonight or tomorrow (supposed to be working on my house this week,
not merging patches...)

thanks,

greg k-h

2005-02-01 22:06:27

by Greg KH

[permalink] [raw]
Subject: Re: [PATCH] SuperHyway bus support

On Wed, Jan 12, 2005 at 02:48:36PM +0200, Paul Mundt wrote:
> Yes, it would seem that way. Here we go again:
>
> drivers/sh/Makefile | 6
> drivers/sh/superhyway/Makefile | 7 +
> drivers/sh/superhyway/superhyway-sysfs.c | 45 ++++++
> drivers/sh/superhyway/superhyway.c | 201 +++++++++++++++++++++++++++++++
> include/linux/superhyway.h | 79 ++++++++++++
> 5 files changed, 338 insertions(+)

Sorry for taking so long on this. I've added it to my trees and it will
show up in the next -mm releases. After 2.6.11 is out I'll forward it
on to Linus.

thanks,

greg k-h

2005-02-01 22:26:52

by Sam Ravnborg

[permalink] [raw]
Subject: Re: [PATCH] SuperHyway bus support

On Tue, Feb 01, 2005 at 02:05:52PM -0800, Greg KH wrote:
> > drivers/sh/Makefile | 6
> > drivers/sh/superhyway/Makefile | 7 +
> > drivers/sh/superhyway/superhyway-sysfs.c | 45 ++++++
> > drivers/sh/superhyway/superhyway.c | 201 +++++++++++++++++++++++++++++++
> > include/linux/superhyway.h | 79 ++++++++++++
> > 5 files changed, 338 insertions(+)

Why does it need a .h file in include/linux/?
Only use include/linux/* for .h files which is used by other parts of
the kernel.

[I've lost the original mail - so cannot see the actual source].

Sam

2005-02-01 22:37:27

by Greg KH

[permalink] [raw]
Subject: Re: [PATCH] SuperHyway bus support

On Tue, Feb 01, 2005 at 11:23:27PM +0100, Sam Ravnborg wrote:
> On Tue, Feb 01, 2005 at 02:05:52PM -0800, Greg KH wrote:
> > > drivers/sh/Makefile | 6
> > > drivers/sh/superhyway/Makefile | 7 +
> > > drivers/sh/superhyway/superhyway-sysfs.c | 45 ++++++
> > > drivers/sh/superhyway/superhyway.c | 201 +++++++++++++++++++++++++++++++
> > > include/linux/superhyway.h | 79 ++++++++++++
> > > 5 files changed, 338 insertions(+)
>
> Why does it need a .h file in include/linux/?
> Only use include/linux/* for .h files which is used by other parts of
> the kernel.
>
> [I've lost the original mail - so cannot see the actual source].

Other parts of the kernel will use that .h file when they register
themselves with the sh bus. Right Paul?

thanks,

greg k-h

2005-02-02 07:04:49

by Paul Mundt

[permalink] [raw]
Subject: Re: [PATCH] SuperHyway bus support

On Tue, Feb 01, 2005 at 02:30:08PM -0800, Greg KH wrote:
> On Tue, Feb 01, 2005 at 11:23:27PM +0100, Sam Ravnborg wrote:
> > On Tue, Feb 01, 2005 at 02:05:52PM -0800, Greg KH wrote:
> > > > drivers/sh/Makefile | 6
> > > > drivers/sh/superhyway/Makefile | 7 +
> > > > drivers/sh/superhyway/superhyway-sysfs.c | 45 ++++++
> > > > drivers/sh/superhyway/superhyway.c | 201 +++++++++++++++++++++++++++++++
> > > > include/linux/superhyway.h | 79 ++++++++++++
> > > > 5 files changed, 338 insertions(+)
> >
> > Why does it need a .h file in include/linux/?
> > Only use include/linux/* for .h files which is used by other parts of
> > the kernel.
> >
> > [I've lost the original mail - so cannot see the actual source].
>
> Other parts of the kernel will use that .h file when they register
> themselves with the sh bus. Right Paul?
>
Yes, that's correct. Any driver with a SuperHyway device will need it,
and this will be on multiple architectures (sh and sh64).


Attachments:
(No filename) (1.01 kB)
(No filename) (189.00 B)
Download all attachments

2005-02-02 07:10:15

by Paul Mundt

[permalink] [raw]
Subject: Re: [PATCH] SuperHyway bus support

On Tue, Feb 01, 2005 at 02:05:52PM -0800, Greg KH wrote:
> On Wed, Jan 12, 2005 at 02:48:36PM +0200, Paul Mundt wrote:
> > Yes, it would seem that way. Here we go again:
> >
> > drivers/sh/Makefile | 6
> > drivers/sh/superhyway/Makefile | 7 +
> > drivers/sh/superhyway/superhyway-sysfs.c | 45 ++++++
> > drivers/sh/superhyway/superhyway.c | 201 +++++++++++++++++++++++++++++++
> > include/linux/superhyway.h | 79 ++++++++++++
> > 5 files changed, 338 insertions(+)
>
> Sorry for taking so long on this. I've added it to my trees and it will
> show up in the next -mm releases. After 2.6.11 is out I'll forward it
> on to Linus.
>
There's an older version of this patch currently still in -mm, so this
patch won't actually apply there directly. I can send an incremental -mm
patch that gets the current -mm implementation up to date with these
changes (or if Andrew can back out the current patch in -mm and apply this
one in place, that works too).


Attachments:
(No filename) (1.00 kB)
(No filename) (189.00 B)
Download all attachments

2005-02-02 22:26:35

by Greg KH

[permalink] [raw]
Subject: Re: [PATCH] SuperHyway bus support

On Wed, Feb 02, 2005 at 09:10:01AM +0200, Paul Mundt wrote:
> On Tue, Feb 01, 2005 at 02:05:52PM -0800, Greg KH wrote:
> > On Wed, Jan 12, 2005 at 02:48:36PM +0200, Paul Mundt wrote:
> > > Yes, it would seem that way. Here we go again:
> > >
> > > drivers/sh/Makefile | 6
> > > drivers/sh/superhyway/Makefile | 7 +
> > > drivers/sh/superhyway/superhyway-sysfs.c | 45 ++++++
> > > drivers/sh/superhyway/superhyway.c | 201 +++++++++++++++++++++++++++++++
> > > include/linux/superhyway.h | 79 ++++++++++++
> > > 5 files changed, 338 insertions(+)
> >
> > Sorry for taking so long on this. I've added it to my trees and it will
> > show up in the next -mm releases. After 2.6.11 is out I'll forward it
> > on to Linus.
> >
> There's an older version of this patch currently still in -mm, so this
> patch won't actually apply there directly. I can send an incremental -mm
> patch that gets the current -mm implementation up to date with these
> changes (or if Andrew can back out the current patch in -mm and apply this
> one in place, that works too).

If Andrew could just drop the patch in his tree, he will get this
version in through the bk-drivers tree that he pulls into the -mm
releases.

thanks,

greg k-h