All of lore.kernel.org
 help / color / mirror / Atom feed
From: pawel.moll@arm.com (Pawel Moll)
To: linux-arm-kernel@lists.infradead.org
Subject: [PATCH 02/11] misc: Versatile Express config bus infrastructure
Date: Tue, 04 Sep 2012 12:53:21 +0100	[thread overview]
Message-ID: <1346759601.2605.68.camel@hornet> (raw)
In-Reply-To: <201209032117.35677.arnd@arndb.de>

Hi Arnd,

Thanks for your time!

On Mon, 2012-09-03 at 22:17 +0100, Arnd Bergmann wrote:
> On Monday 03 September 2012, Pawel Moll wrote:
> > +	dcc at 0 {
> > +		#address-cells = <1>;
> > +		#size-cells = <0>;
> > +		#interrupt-cells = <0>;
> > +		arm,vexpress,site = <0xff>; /* Master site */
> > +
> > +		osc at 0 {
> > +			compatible = "arm,vexpress-config,osc";
> > +			reg = <0>;
> > +			freq-range = <50000000 100000000>;
> > +			#clock-cells = <1>;
> > +			clock-output-names = "oscclk0";
> > +		};
> > +	};
> >  };
> 
> The #interrupt-cells property seems misplaced here.

Right. I'm not sure what I meant here, probably a cut-and-paste error.

> > --- a/drivers/misc/Kconfig
> > +++ b/drivers/misc/Kconfig
> > @@ -517,4 +517,5 @@ source "drivers/misc/lis3lv02d/Kconfig"
> >  source "drivers/misc/carma/Kconfig"
> >  source "drivers/misc/altera-stapl/Kconfig"
> >  source "drivers/misc/mei/Kconfig"
> > +source "drivers/misc/vexpress/Kconfig"
> >  endmenu
> > diff --git a/drivers/misc/Makefile b/drivers/misc/Makefile
> > index b88df7a..49964fd 100644
> > --- a/drivers/misc/Makefile
> > +++ b/drivers/misc/Makefile
> > @@ -50,3 +50,4 @@ obj-y				+= carma/
> >  obj-$(CONFIG_USB_SWITCH_FSA9480) += fsa9480.o
> >  obj-$(CONFIG_ALTERA_STAPL)	+=altera-stapl/
> >  obj-$(CONFIG_INTEL_MEI)		+= mei/
> > +obj-y				+= vexpress/
> 
> This does not look like something that should go to drivers/misc (well,
> basically nothing ever does). How about drivers/mfd or drivers/bus instead?

I don't see drivers/bus in 3.6-rc4? If there will be such thing, I guess
I can move config_bus.c to drivers/bus/vexpress-config.c, display.c to
drivers/video/vexpress-display.c (see my other answer), sysreg.c to
drivers/mfd/vexpress-sysreg.c (it is a multifunction device indeed, not
argument about that), but reset.c seems to me should stay as
drivers/misc/vexpress-reset.c - it's hardly a mfd...

> > +#define ADDR_FMT "%u.%x:%x:%x:%x"
> > +
> > +#define ADDR_ARGS(_ptr) \
> > +		_ptr->func, _ptr->addr.site, _ptr->addr.position, \
> > +		_ptr->addr.dcc, _ptr->addr.device
> 
> Can't you use dev_printk() to print the device name in the normal format?

Well, in some places it's used before dev_set_name(), but I guess I can
get rid of those printk-s (they are debug messages anyway).

> > +#define ADDR_TO_U64(addr) \
> > +		(((u64)(addr).site << 32) | ((addr).position << 24) | \
> > +		((addr).dcc << 16) | (addr).device)
> > +
> > +static bool vexpress_config_early = true;
> > +static DEFINE_MUTEX(vexpress_config_early_mutex);
> > +static LIST_HEAD(vexpress_config_early_drivers);
> > +static LIST_HEAD(vexpress_config_early_devices);
> 
> What is the reason for needing early devices that you have to keep in a list
> like this? If it's only for setup purposes, it's probably easier to
> have a platform hook that probes the hardware you want to initialize at boot
> time and only start using the device method at device init time.

Funnily enough the first version didn't have anything "early related"...
Till I actually defined the real clock dependency in the tree :-(

So it's all about clocks, that must be available really early. The
particular problem I faced was the amba_probe() trying to enable
apb_pclk of each device and failing...

Now, during the clock registration the device model is not initialized
yet, so I can't do normal devices registration. I've stolen some ideas
from the early platform bus code...

> > +static int vexpress_config_match(struct device *dev, struct device_driver *drv)
> > +{
> > +	struct vexpress_config_device *vecdev = to_vexpress_config_device(dev);
> > +	struct vexpress_config_driver *vecdrv = to_vexpress_config_driver(drv);
> > +
> > +	if (vecdrv->funcs) {
> > +		const unsigned *func = vecdrv->funcs;
> > +
> > +		while (*func) {
> > +			if (*func == vecdev->func)
> > +				return 1;
> > +			func++;
> > +		}
> > +	}
> > +
> > +	return 0;
> > +}
> > +
> > +static struct device vexpress_config_bus = {
> > +	.init_name = "vexpress-config",
> > +};
> 
> No static devices in new code please. Just put it into the device tree.

Hm. This is just a dummy device serving as a default parent, similarly
to:

struct device platform_bus = {
        .init_name      = "platform",
};
EXPORT_SYMBOL_GPL(platform_bus);

Without that I can see two options:

1. Create some kind of a device (platform?) for the dcc/mcc node and use
it as a parent.
2. Scan the device tree "downwards" searching for a node that has a
device already associated with it (but this may not work at the early
stage).

> > +struct bus_type vexpress_config_bus_type = {
> > +	.name = "vexpress-config",
> > +	.match = vexpress_config_match,
> > +};
> 
> What is the reason for having a separate bus_type here?
> Is this a discoverable bus? If it is, why do you need a
> device tree binding for the child devices?

It is not a discoverable bus, but the devices are very different from
the "normal" platform devices and have specific read/write interface, so
it seemed to me that a separate bus would make sense. And I didn't want
to reinvent the wheel with my own "device/driver model".

> > +#define VEXPRESS_COMPATIBLE_TO_FUNC(_compatible, _func) \
> > +	{ \
> > +		.compatible = "arm,vexpress-config," _compatible, \
> > +		.data = (void *)VEXPRESS_CONFIG_FUNC_##_func \
> > +	}
> > +
> > +static struct of_device_id vexpress_config_devices_matches[] = {
> > +	VEXPRESS_COMPATIBLE_TO_FUNC("osc", OSC),
> > +	VEXPRESS_COMPATIBLE_TO_FUNC("volt", VOLT),
> > +	VEXPRESS_COMPATIBLE_TO_FUNC("amp", AMP),
> > +	VEXPRESS_COMPATIBLE_TO_FUNC("temp", TEMP),
> > +	VEXPRESS_COMPATIBLE_TO_FUNC("reset", RESET),
> > +	VEXPRESS_COMPATIBLE_TO_FUNC("scc", SCC),
> > +	VEXPRESS_COMPATIBLE_TO_FUNC("muxfpga", MUXFPGA),
> > +	VEXPRESS_COMPATIBLE_TO_FUNC("shutdown", SHUTDOWN),
> > +	VEXPRESS_COMPATIBLE_TO_FUNC("reboot", REBOOT),
> > +	VEXPRESS_COMPATIBLE_TO_FUNC("dvimode", DVIMODE),
> > +	VEXPRESS_COMPATIBLE_TO_FUNC("power", POWER),
> > +	VEXPRESS_COMPATIBLE_TO_FUNC("energy", ENERGY),
> > +	{},
> > +};
> 
> What is the purpose of this lookup? Can't you make the child devices get
> probed by the compatible value?

Ok, there are two reasons for this table existence:

1. vexpress_config_of_populate() below - I need a comprehensive list of
compatible values to be able to search the tree and create respective
devices.

2. Non-DT static devices - I need something to be able to match a driver
with a device, and the "functions list" seemed appropriate.

> > +static void vexpress_config_of_device_add(struct device_node *node)
> > +{
> > +	int err;
> > +	struct vexpress_config_device *vecdev;
> > +	const struct of_device_id *match;
> > +	u32 value;
> > +
> > +	if (!of_device_is_available(node))
> > +		return;
> > +
> > +	vecdev = kzalloc(sizeof(*vecdev), GFP_KERNEL);
> > +	if (WARN_ON(!vecdev))
> > +		return;
> > +
> > +	vecdev->dev.of_node = of_node_get(node);
> > +
> > +	vecdev->name = node->name;
> > +
> > +	match = of_match_node(vexpress_config_devices_matches, node);
> > +	vecdev->func = (unsigned)match->data;
> > +
> > +	err = of_property_read_u32(node->parent, "arm,vexpress,site", &value);
> > +	if (!err)
> > +		vecdev->addr.site = value;
> > +
> > +	err = of_property_read_u32(node->parent, "arm,vexpress,position",
> > +			&value);
> > +	if (!err)
> > +		vecdev->addr.position = value;
> > +
> > +	err = of_property_read_u32(node->parent, "arm,vexpress,dcc", &value);
> > +	if (!err)
> > +		vecdev->addr.dcc = value;
> > +
> > +	err = of_property_read_u32(node, "reg", &value);
> > +	if (!err) {
> > +		vecdev->addr.device = value;
> > +	} else {
> > +		pr_err("Invalid reg property in '%s'! (%d)\n",
> > +				node->full_name, err);
> > +		kfree(vecdev);
> > +		return;
> > +	}
> > +
> > +	err = vexpress_config_device_register(vecdev);
> > +	if (err) {
> > +		pr_err("Failed to add OF device '%s'! (%d)\n",
> > +				node->full_name, err);
> > +		kfree(vecdev);
> > +		return;
> > +	}
> > +}
> > +
> > +void vexpress_config_of_populate(void)
> > +{
> > +	struct device_node *node;
> > +
> > +	for_each_matching_node(node, vexpress_config_devices_matches)
> > +		vexpress_config_of_device_add(node);
> > +}
> 
> This is unusual. Why do you only add the matching devices rather than
> all of them? Doing it your way also means O(n^2) rather than O(n)
> traversal through the list of children.

Em, I'm not sure what do you mean... The idea is shamelessly stolen from
of_irq_init() and of_clk_init()...

> > +int vexpress_config_device_register(struct vexpress_config_device *vecdev)
> > +{
> > +	pr_debug("Registering %sdevice '%s." ADDR_FMT "'\n",
> > +			vexpress_config_early ? "early " : "",
> > +			vecdev->name, ADDR_ARGS(vecdev));
> > +
> > +	if (vecdev->addr.site == VEXPRESS_SITE_MASTER)
> > +		vecdev->addr.site = vexpress_config_get_master_site();
> > +
> > +	if (!vecdev->bridge) {
> > +		spin_lock(&vexpress_config_bridges_lock);
> > +		vexpress_config_bridge_find(&vecdev->dev, NULL);
> > +		spin_unlock(&vexpress_config_bridges_lock);
> > +	}
> > +
> > +	if (vexpress_config_early) {
> > +		list_add(&vecdev->early, &vexpress_config_early_devices);
> > +		vexpress_config_early_bind();
> > +
> > +		return 0;
> > +	}
> > +
> > +	device_initialize(&vecdev->dev);
> > +	vecdev->dev.bus = &vexpress_config_bus_type;
> > +	if (!vecdev->dev.parent)
> > +		vecdev->dev.parent = &vexpress_config_bus;
> > +
> > +	dev_set_name(&vecdev->dev, "%s." ADDR_FMT,
> > +			vecdev->name, ADDR_ARGS(vecdev));
> > +
> > +	return device_add(&vecdev->dev);
> > +}
> > +EXPORT_SYMBOL(vexpress_config_device_register);
> 
> Why is this exported to non-GPL drivers? It looks like the only caller should be
> in this file.

Hm. There's no hidden agenda behind the non-GPL export, if that's what
you are afraid of ;-) Now, why it is exported at all? Because
platform_device_register is, I suppose (you can tell that I was looking
at the platform bus code ;-). The non-DT platform code is using it, so
it can't be static, but I wouldn't really expect any module to use it.
So I can make it EXPORT_SYMBOL_GPL or drop it, no problem.

Cheers!

Pawel

  reply	other threads:[~2012-09-04 11:53 UTC|newest]

Thread overview: 36+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2012-09-03 16:25 [PATCH 00/11] Versatile Express infrastructure Pawel Moll
2012-09-03 16:25 ` [PATCH 01/11] input: ambakmi: Add missing clk_[un]prepare() calls Pawel Moll
2012-09-04 13:37   ` Thomas Petazzoni
2012-09-04 13:45     ` Pawel Moll
2012-09-03 16:25 ` [PATCH 02/11] misc: Versatile Express config bus infrastructure Pawel Moll
2012-09-03 21:17   ` Arnd Bergmann
2012-09-04 11:53     ` Pawel Moll [this message]
2012-09-04 12:45       ` Arnd Bergmann
2012-09-04 16:41         ` Pawel Moll
2012-09-03 16:25 ` [PATCH 03/11] misc: Versatile Express reset driver Pawel Moll
2012-09-03 16:25 ` [PATCH 04/11] misc: Versatile Express display muxer driver Pawel Moll
2012-09-03 21:21   ` Arnd Bergmann
2012-09-04 11:53     ` Pawel Moll
2012-09-03 16:25 ` [PATCH 05/11] clk: Versatile Express clock generators ("osc") driver Pawel Moll
2012-09-10 19:14   ` Mike Turquette
2012-09-11 16:10     ` Pawel Moll
2012-09-11 18:00       ` Linus Walleij
2012-09-12 16:56         ` Pawel Moll
2012-09-11 18:33       ` Mike Turquette
2012-09-03 16:25 ` [PATCH 06/11] clk: Common clocks implementation for Versatile Express Pawel Moll
2012-09-03 21:24   ` Arnd Bergmann
2012-09-04 11:53     ` Pawel Moll
2012-09-04 12:43       ` Linus Walleij
2012-09-04 17:12         ` Ryan Harkin
2012-09-10 20:10   ` Mike Turquette
2012-09-03 16:25 ` [PATCH 07/11] regulators: Versatile Express regulator driver Pawel Moll
2012-09-03 16:25 ` [PATCH 08/11] hwmon: Versatile Express hwmon driver Pawel Moll
2012-09-03 16:25 ` [PATCH 09/11] misc: Versatile Express system registers driver Pawel Moll
2012-09-03 16:25 ` [PATCH 10/11] ARM: vexpress: Add config bus components and clocks to DTs Pawel Moll
2012-09-04 12:58   ` Rob Herring
2012-09-04 13:05     ` Pawel Moll
2012-09-04 14:31       ` Rob Herring
2012-09-04 15:37         ` Pawel Moll
2012-09-04 17:51           ` Rob Herring
2012-09-19  9:44             ` Pawel Moll
2012-09-03 16:25 ` [PATCH 11/11] ARM: vexpress: Start using new Versatile Express infrastructure Pawel Moll

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1346759601.2605.68.camel@hornet \
    --to=pawel.moll@arm.com \
    --cc=linux-arm-kernel@lists.infradead.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.