* Re: [RFC PATCH] [media]: of: move graph helpers from drivers/media/v4l2-core to drivers/of
From: Laurent Pinchart @ 2014-02-11 17:24 UTC (permalink / raw)
To: Philipp Zabel
Cc: Russell King - ARM Linux, Rob Herring, Mauro Carvalho Chehab,
Grant Likely, Rob Herring, Sylwester Nawrocki, Tomi Valkeinen,
Kyungmin Park,
linux-kernel-u79uwXL29TY76Z2rM5mHXA@public.gmane.org,
linux-media-u79uwXL29TY76Z2rM5mHXA@public.gmane.org,
devicetree-u79uwXL29TY76Z2rM5mHXA@public.gmane.org, Philipp Zabel
In-Reply-To: <1392136617.6943.33.camel-/rZezPiN1rtR6QfukMTsflXZhhPuCNm+@public.gmane.org>
Hi Philipp,
On Tuesday 11 February 2014 17:36:57 Philipp Zabel wrote:
> Am Dienstag, den 11.02.2014, 16:23 +0100 schrieb Laurent Pinchart:
> > On Tuesday 11 February 2014 14:52:48 Russell King - ARM Linux wrote:
> > > On Tue, Feb 11, 2014 at 07:56:33AM -0600, Rob Herring wrote:
> > > > On Tue, Feb 11, 2014 at 5:45 AM, Philipp Zabel wrote:
> > > > > This allows to reuse the same parser code from outside the V4L2
> > > > > framework, most importantly from display drivers. There have been
> > > > > patches that duplicate the code (and I am going to send one of my
> > > > > own),
> > > > > such as
> > > > > http://lists.freedesktop.org/archives/dri-devel/2013-August/043308.h
> > > > > tml
> > > > > and others that parse the same binding in a different way:
> > > > > https://www.mail-archive.com/linux-omap-u79uwXL29TY76Z2rM5mHXA@public.gmane.org/msg100761.ht
> > > > > ml
> > > > >
> > > > > I think that all common video interface parsing helpers should be
> > > > > moved to a single place, outside of the specific subsystems, so that
> > > > > it can be reused by all drivers.
> > > >
> > > > Perhaps that should be done rather than moving to drivers/of now and
> > > > then again to somewhere else.
> > >
> > > Do you have a better suggestion where it should move to?
> > >
> > > drivers/gpu/drm - no, because v4l2 wants to use it
> > > drivers/media/video - no, because DRM drivers want to use it
> > > drivers/video - no, because v4l2 and drm drivers want to use it
> >
> > Just pointing out a missing location (which might be rejected due to
> > similar concerns), there's also drivers/media, which isn't V4L-specific.
>
> Since drivers/Makefile has media/ in obj-y, moving the graph helpers to
> drivers/media should technically work.
>
> > > Maybe drivers/of-graph/ ? Or maybe it's just as good a place to move it
> > > into drivers/of ?
>
> include/media/of_graph.h,
> drivers/media/of_graph.c?
I'm personally fine with that.
--
Regards,
Laurent Pinchart
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply
* Re: [RFC PATCH] [media]: of: move graph helpers from drivers/media/v4l2-core to drivers/of
From: Sylwester Nawrocki @ 2014-02-11 17:22 UTC (permalink / raw)
To: Philipp Zabel, Laurent Pinchart
Cc: Russell King - ARM Linux, Rob Herring, Mauro Carvalho Chehab,
Grant Likely, Rob Herring, Tomi Valkeinen, Kyungmin Park,
linux-kernel-u79uwXL29TY76Z2rM5mHXA@public.gmane.org,
linux-media-u79uwXL29TY76Z2rM5mHXA@public.gmane.org,
devicetree-u79uwXL29TY76Z2rM5mHXA@public.gmane.org, Philipp Zabel,
Guennadi Liakhovetski
In-Reply-To: <1392136617.6943.33.camel-/rZezPiN1rtR6QfukMTsflXZhhPuCNm+@public.gmane.org>
(adding Guennadi to Cc)
On 11/02/14 17:36, Philipp Zabel wrote:
> Am Dienstag, den 11.02.2014, 16:23 +0100 schrieb Laurent Pinchart:
>> Hi Russell,
>>
>> On Tuesday 11 February 2014 14:52:48 Russell King - ARM Linux wrote:
>>> On Tue, Feb 11, 2014 at 07:56:33AM -0600, Rob Herring wrote:
>>>> On Tue, Feb 11, 2014 at 5:45 AM, Philipp Zabel wrote:
>>>>> This allows to reuse the same parser code from outside the V4L2
>>>>> framework, most importantly from display drivers. There have been
>>>>> patches that duplicate the code (and I am going to send one of my own),
>>>>> such as
>>>>> http://lists.freedesktop.org/archives/dri-devel/2013-August/043308.html
>>>>> and others that parse the same binding in a different way:
>>>>> https://www.mail-archive.com/linux-omap-u79uwXL29TY76Z2rM5mHXA@public.gmane.org/msg100761.html
>>>>>
>>>>> I think that all common video interface parsing helpers should be moved
>>>>> to a single place, outside of the specific subsystems, so that it can
>>>>> be reused by all drivers.
>>>>
>>>> Perhaps that should be done rather than moving to drivers/of now and
>>>> then again to somewhere else.
>>>
>>> Do you have a better suggestion where it should move to?
>>>
>>> drivers/gpu/drm - no, because v4l2 wants to use it
>>> drivers/media/video - no, because DRM drivers want to use it
>>> drivers/video - no, because v4l2 and drm drivers want to use it
>>
>> Just pointing out a missing location (which might be rejected due to similar
>> concerns), there's also drivers/media, which isn't V4L-specific.
>
> Since drivers/Makefile has media/ in obj-y, moving the graph helpers to
> drivers/media should technically work.
>
>>> Maybe drivers/of-graph/ ? Or maybe it's just as good a place to move it
>>> into drivers/of ?
>
> include/media/of_graph.h,
> drivers/media/of_graph.c?
drivers/media sounds like a good alternative to me.
I would just remove also v4l2_of_{parse/get}* and update the users
to call of_graph_* directly, there should not be many of them.
--
Thanks,
Sylwester
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply
* Re: [PATCH] of: Turn of_match_node into a static inline when CONFIG_OF isn't set
From: Laurent Pinchart @ 2014-02-11 17:20 UTC (permalink / raw)
To: Josh Cartwright
Cc: linux-kernel-u79uwXL29TY76Z2rM5mHXA,
devicetree-u79uwXL29TY76Z2rM5mHXA, Grant Likely, Rob Herring
In-Reply-To: <20140211164825.GC841-OP5zVEFNDbfdOxZ39nK119BPR1lH4CV8@public.gmane.org>
Hi Josh,
On Tuesday 11 February 2014 10:48:26 Josh Cartwright wrote:
> On Tue, Feb 11, 2014 at 03:55:35PM +0100, Laurent Pinchart wrote:
> > On Tuesday 11 February 2014 08:41:08 Josh Cartwright wrote:
> > > On Tue, Feb 11, 2014 at 01:36:51PM +0100, Laurent Pinchart wrote:
> > > > when CONFIG_OF is disabled of_match_node is defined as a macro that
> > > > evaluates to NULL. This breaks compilation of drivers that dereference
> > > > the function's return value directly. Fix it by turning the macro into
> > > > a static inline function that returns NULL.
> > >
> > > Just this past week I did the same thing, but noticed that it breaks the
> > > following usecase:
> > >
> > > #ifdef CONFIG_OF
> > > static const struct of_device_id foobar_matches[] = {
> > > { .compatible = "foobar,whatsit", },
> > > { },
> > > };
> > > #endif
> > >
> > > static int probeme(struct platform_device *pdev)
> > > {
> > > struct of_device_id *id;
> > >
> > > id = of_match_node(foobar_matches, pdev->dev.of_node);
> > > if (id) {
> > > /* ... */
> > > }
> > > return 0;
> > >
> > > }
> > >
> > > When !CONFIG_OF and with your change, this will fail to build due to
> > > foobar_matches being undefined.
> >
> > Good point. What would you think about
> >
> > #define of_match_node(_matches, _node) ((const struct of_device_id
> > *)NULL)
>
> I've just sent out a patchset that cleans up at least a couple of users
> that directly do of_match_node(matches, np)->data using
> of_find_matching_node_and_match. Not sure if that will fix the usage
> you have in mind, though.
Not quite. My use case is pretty simple:
state->info = of_match_node(adv7604_of_id, np)->data;
> I am a bit weary about having an of_match_node() user that both directly
> dereferences the result (i.e. of_match_node(matches, np)->data) _and_
> builds when !CONFIG_OF; most likely due to a traumatic childhood event
> where demons flew out my nose.
I can assign the intermediate value to a variable before dereferencing it and
drop my of_match_node() patch if it makes everybody happier.
--
Regards,
Laurent Pinchart
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply
* Re: [PATCH 4/8] ARM: mvebu: make use of of_find_matching_node_and_match
From: Thomas Petazzoni @ 2014-02-11 17:10 UTC (permalink / raw)
To: Jason Cooper
Cc: Josh Cartwright, Andrew Lunn, Russell King,
devicetree-u79uwXL29TY76Z2rM5mHXA,
linux-kernel-u79uwXL29TY76Z2rM5mHXA, Gregory Clement,
linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
Sebastian Hesselbarth
In-Reply-To: <20140211165314.GA8533-u4khhh1J0LxI1Ri9qeTfzeTW4wlIGRCZ@public.gmane.org>
Dear Jason Cooper,
On Tue, 11 Feb 2014 11:53:14 -0500, Jason Cooper wrote:
> > - np = of_find_matching_node(NULL, of_system_controller_table);
> > + np = of_find_matching_node_and_match(NULL, of_system_controller_table,
> > + &match);
> > if (np) {
> > - const struct of_device_id *match =
> > - of_match_node(of_system_controller_table, np);
>
>
> > - BUG_ON(!match);
>
> Gregory, is it ok to remove this? It was added with the original code
> submission for mach-mvebu. mvebu_restart() will handle this
> gracefully...
The BUG_ON here can normally never be reached. If
of_find_matching_node() returns a non-NULL result, then of_match_node()
should also return a non-NULL result.
Or I'm missing something :)
Thomas
--
Thomas Petazzoni, CTO, Free Electrons
Embedded Linux, Kernel and Android engineering
http://free-electrons.com
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply
* Re: [PATCH 1/2] uhci-platform: Change compatible string from platform-uhci to generic-uhci
From: Alan Stern @ 2014-02-11 17:07 UTC (permalink / raw)
To: Hans de Goede
Cc: Greg Kroah-Hartman, Maxime Ripard, Arnd Bergmann, linux-usb,
linux-sunxi-/JYPxA39Uh5TLH3MbocFFw,
linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r, devicetree
In-Reply-To: <1392137686-6562-1-git-send-email-hdegoede-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>
On Tue, 11 Feb 2014, Hans de Goede wrote:
> This brings the uhci-platform bindings in sync with what we've done for
> the ohci- and ehci-platform drivers. As discussed there using platform as a
> prefix is a bit weird as the platform bus is a Linux specific thing and
> the bindings are supposed to be OS agnostic.
>
> Note that the old platform-uhci compatible string is kept around for, well,
> compatibility reasons.
>
> While at it rename the bindings txt file to match the name of all the
> other ?hci-platform bindings docs.
>
> Signed-off-by: Hans de Goede <hdegoede-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>
Acked-by: Alan Stern <stern-nwvwT67g6+6dFdvTe/nMLpVzexx5G7lz@public.gmane.org>
^ permalink raw reply
* Re: ohci-/ehci-platform: Change compatible string to ?hci-platform
From: Hans de Goede @ 2014-02-11 17:04 UTC (permalink / raw)
To: Florian Fainelli, Arnd Bergmann
Cc: Alan Stern, Greg Kroah-Hartman, Roger Quadros, Tony Prisk,
Maxime Ripard, linux-usb, linux-sunxi-/JYPxA39Uh5TLH3MbocFFw,
linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r, devicetree,
Al Cooper, Marc Carino
In-Reply-To: <4195343.2rfzYCCiXV@lenovo>
Hi Florian,
On 02/11/2014 06:01 PM, Florian Fainelli wrote:
> Le mardi 11 février 2014, 16:43:37 Arnd Bergmann a écrit :
>> On Tuesday 11 February 2014 10:27:12 Alan Stern wrote:
>>> It might even be a good idea to change the "xhci-platform" string to
>>> match, it that doesn't cause too much trouble.
>>
>> The original xhci binding was contributed by Al Cooper, but I don't
>> see any dts files using it. I agree that xhci-generic is a better
>> name than xhci-platform, and I think we should make that the recommended
>> string. If Al or someone thinks the xhci-generic string might already
>> be used in production devices, we should however allow both names
>> in the binding and in the driver.
>
> The platform on which "xhci-platform" is currently used is Broadcom STB for
> which Marc submitted the base support recently. The BCM7445 reference DTS will
> probably be updated at some point to reflect that.
Note I've just send a patch with the xhci-platform -> generic-xhci change
Arnd requested. I've left xhci-platform in the list of compatible strings
for now (marked as deprecated in the docs), so there should be no issues
regardless of what the dts version getting merged ends up using.
Would be good if we could ensure it uses generic-xhci though, and then
drop the xhci-platform compatible all-together in a follow-up patch.
Regards,
Hans
--
You received this message because you are subscribed to the Google Groups "linux-sunxi" group.
To unsubscribe from this group and stop receiving emails from it, send an email to linux-sunxi+unsubscribe-/JYPxA39Uh5TLH3MbocFF+G/Ez6ZCGd0@public.gmane.org
For more options, visit https://groups.google.com/groups/opt_out.
^ permalink raw reply
* Re: ohci-/ehci-platform: Change compatible string to ?hci-platform
From: Florian Fainelli @ 2014-02-11 17:01 UTC (permalink / raw)
To: Arnd Bergmann
Cc: Alan Stern, Hans de Goede, Greg Kroah-Hartman, Roger Quadros,
Tony Prisk, Maxime Ripard, linux-usb,
linux-sunxi-/JYPxA39Uh5TLH3MbocFFw,
linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r, devicetree,
Al Cooper, Marc Carino
In-Reply-To: <1635726.gc3dEs0zOi@wuerfel>
Le mardi 11 février 2014, 16:43:37 Arnd Bergmann a écrit :
> On Tuesday 11 February 2014 10:27:12 Alan Stern wrote:
> > It might even be a good idea to change the "xhci-platform" string to
> > match, it that doesn't cause too much trouble.
>
> The original xhci binding was contributed by Al Cooper, but I don't
> see any dts files using it. I agree that xhci-generic is a better
> name than xhci-platform, and I think we should make that the recommended
> string. If Al or someone thinks the xhci-generic string might already
> be used in production devices, we should however allow both names
> in the binding and in the driver.
The platform on which "xhci-platform" is currently used is Broadcom STB for
which Marc submitted the base support recently. The BCM7445 reference DTS will
probably be updated at some point to reflect that.
--
Florian
--
You received this message because you are subscribed to the Google Groups "linux-sunxi" group.
To unsubscribe from this group and stop receiving emails from it, send an email to linux-sunxi+unsubscribe-/JYPxA39Uh5TLH3MbocFF+G/Ez6ZCGd0@public.gmane.org
For more options, visit https://groups.google.com/groups/opt_out.
^ permalink raw reply
* Re: [PATCH 2/2] ARM: shmobile: koelsch: add Ether DT support
From: Laurent Pinchart @ 2014-02-11 17:01 UTC (permalink / raw)
To: Sergei Shtylyov
Cc: horms, robh+dt, pawel.moll, mark.rutland, ijc+devicetree, galak,
linux-sh, devicetree, magnus.damm, linux, linux-arm-kernel
In-Reply-To: <201402070114.27279.sergei.shtylyov@cogentembedded.com>
Hi Sergei,
Thanks a lot for the patch.
On Friday 07 February 2014 01:14:26 Sergei Shtylyov wrote:
> Define the Koelsch board dependent part of the Ether device node.
>
> Signed-off-by: Sergei Shtylyov <sergei.shtylyov@cogentembedded.com>
>
> ---
> arch/arm/boot/dts/r8a7791-koelsch.dts | 31 +++++++++++++++++++++++++++++-
> 1 file changed, 30 insertions(+), 1 deletion(-)
>
> Index: renesas/arch/arm/boot/dts/r8a7791-koelsch.dts
> ===================================================================
> --- renesas.orig/arch/arm/boot/dts/r8a7791-koelsch.dts
> +++ renesas/arch/arm/boot/dts/r8a7791-koelsch.dts
> @@ -2,7 +2,8 @@
> * Device Tree Source for the Koelsch board
> *
> * Copyright (C) 2013 Renesas Electronics Corporation
> - * Copyright (C) 2013 Renesas Solutions Corp.
> + * Copyright (C) 2013-2014 Renesas Solutions Corp.
> + * Copyright (C) 2014 Cogent Embedded, Inc.
> *
> * This file is licensed under the terms of the GNU General Public License
> * version 2. This program is licensed "as is" without any warranty of any
> @@ -122,12 +123,40 @@
> renesas,function = "scif1";
> };
>
> + ether_pins: ether {
> + renesas,groups = "eth_link", "eth_mdio", "eth_rmii";
> + renesas,function = "eth";
> + };
> +
> + phy1_pins: phy1 {
> + renesas,groups = "intc_irq0";
> + renesas,function = "intc";
> + };
> +
> qspi_pins: spi {
> renesas,groups = "qspi_ctrl", "qspi_data4";
> renesas,function = "qspi";
> };
> };
>
> +ðer {
> + pinctrl-0 = <ðer_pins>;
> + pinctrl-names = "default";
> +
> + phy-handle = <&phy1>;
> + renesas,ether-link-active-low;
> + status = "ok";
> +
> + phy1: ethernet-phy@1 {
> + reg = <1>;
> + interrupt-parent = <&irqc0>;
> + interrupts = <0 IRQ_TYPE_LEVEL_LOW>;
> +
> + pinctrl-0 = <&phy1_pins>;
> + pinctrl-names = "default";
I think the PHY pins should be moved to the ethernet device. The reason for
this is that the PHY device is discovered dynamically at runtime, and has thus
no DT node associated with its struct device to control pinctrl automatically.
This should probably be fixed, but in the meantime moving the PHY pins to the
ethernet device should fix the problem.
As a last step we're missing a DT equivalent to our board code
koelsch_ksz8041_fixup() workaround. Adding a property to specify LEDs usage to
the PHY DT node shouldn't be difficult, but associating that node to the PHY
device and handling the property in the PHY driver will require a bit of work.
Is this on your to-do list ?
> + };
> +};
> +
> &sata0 {
> status = "okay";
> };
--
Regards,
Laurent Pinchart
^ permalink raw reply
* [PATCH 2/2] xhci-platform: Change compatible string from xhci-platform to generic-xhci
From: Hans de Goede @ 2014-02-11 16:54 UTC (permalink / raw)
To: Greg Kroah-Hartman
Cc: Maxime Ripard, Arnd Bergmann, linux-usb,
linux-sunxi-/JYPxA39Uh5TLH3MbocFFw,
linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r, devicetree,
Hans de Goede
In-Reply-To: <1392137686-6562-1-git-send-email-hdegoede-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>
This brings the xhci-platform bindings in sync with what we've done for
the ohci- and ehci-platform drivers. As discussed there using platform as a
postfix is a bit weird as the platform bus is a Linux specific thing and
the bindings are supposed to be OS agnostic.
Note that the old xhci-platform compatible string is kept around for, well,
compatibility reasons.
Signed-off-by: Hans de Goede <hdegoede-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>
---
Documentation/devicetree/bindings/usb/usb-xhci.txt | 4 ++--
drivers/usb/host/xhci-plat.c | 1 +
2 files changed, 3 insertions(+), 2 deletions(-)
diff --git a/Documentation/devicetree/bindings/usb/usb-xhci.txt b/Documentation/devicetree/bindings/usb/usb-xhci.txt
index 5752df0..90f8f60 100644
--- a/Documentation/devicetree/bindings/usb/usb-xhci.txt
+++ b/Documentation/devicetree/bindings/usb/usb-xhci.txt
@@ -1,14 +1,14 @@
USB xHCI controllers
Required properties:
- - compatible: should be "xhci-platform".
+ - compatible: should be "generic-xhci" (deprecated: "xhci-platform").
- reg: should contain address and length of the standard XHCI
register set for the device.
- interrupts: one XHCI interrupt should be described here.
Example:
usb@f0931000 {
- compatible = "xhci-platform";
+ compatible = "generic-xhci";
reg = <0xf0931000 0x8c8>;
interrupts = <0x0 0x4e 0x0>;
};
diff --git a/drivers/usb/host/xhci-plat.c b/drivers/usb/host/xhci-plat.c
index 8abda5c..8affef9 100644
--- a/drivers/usb/host/xhci-plat.c
+++ b/drivers/usb/host/xhci-plat.c
@@ -226,6 +226,7 @@ static const struct dev_pm_ops xhci_plat_pm_ops = {
#ifdef CONFIG_OF
static const struct of_device_id usb_xhci_of_match[] = {
+ { .compatible = "generic-xhci" },
{ .compatible = "xhci-platform" },
{ },
};
--
1.8.5.3
^ permalink raw reply related
* [PATCH 1/2] uhci-platform: Change compatible string from platform-uhci to generic-uhci
From: Hans de Goede @ 2014-02-11 16:54 UTC (permalink / raw)
To: Greg Kroah-Hartman
Cc: Maxime Ripard, Arnd Bergmann, linux-usb,
linux-sunxi-/JYPxA39Uh5TLH3MbocFFw,
linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r, devicetree,
Hans de Goede
This brings the uhci-platform bindings in sync with what we've done for
the ohci- and ehci-platform drivers. As discussed there using platform as a
prefix is a bit weird as the platform bus is a Linux specific thing and
the bindings are supposed to be OS agnostic.
Note that the old platform-uhci compatible string is kept around for, well,
compatibility reasons.
While at it rename the bindings txt file to match the name of all the
other ?hci-platform bindings docs.
Signed-off-by: Hans de Goede <hdegoede-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>
---
Documentation/devicetree/bindings/usb/platform-uhci.txt | 15 ---------------
Documentation/devicetree/bindings/usb/usb-uhci.txt | 15 +++++++++++++++
drivers/usb/host/uhci-platform.c | 1 +
3 files changed, 16 insertions(+), 15 deletions(-)
delete mode 100644 Documentation/devicetree/bindings/usb/platform-uhci.txt
create mode 100644 Documentation/devicetree/bindings/usb/usb-uhci.txt
diff --git a/Documentation/devicetree/bindings/usb/platform-uhci.txt b/Documentation/devicetree/bindings/usb/platform-uhci.txt
deleted file mode 100644
index a4fb071..0000000
--- a/Documentation/devicetree/bindings/usb/platform-uhci.txt
+++ /dev/null
@@ -1,15 +0,0 @@
-Generic Platform UHCI Controller
------------------------------------------------------
-
-Required properties:
-- compatible : "platform-uhci"
-- reg : Should contain 1 register ranges(address and length)
-- interrupts : UHCI controller interrupt
-
-Example:
-
- uhci@d8007b00 {
- compatible = "platform-uhci";
- reg = <0xd8007b00 0x200>;
- interrupts = <43>;
- };
diff --git a/Documentation/devicetree/bindings/usb/usb-uhci.txt b/Documentation/devicetree/bindings/usb/usb-uhci.txt
new file mode 100644
index 0000000..2981334
--- /dev/null
+++ b/Documentation/devicetree/bindings/usb/usb-uhci.txt
@@ -0,0 +1,15 @@
+Generic Platform UHCI Controller
+-----------------------------------------------------
+
+Required properties:
+- compatible : "generic-uhci" (deprecated: "platform-uhci")
+- reg : Should contain 1 register ranges(address and length)
+- interrupts : UHCI controller interrupt
+
+Example:
+
+ uhci@d8007b00 {
+ compatible = "generic-uhci";
+ reg = <0xd8007b00 0x200>;
+ interrupts = <43>;
+ };
diff --git a/drivers/usb/host/uhci-platform.c b/drivers/usb/host/uhci-platform.c
index 44e6c9d..01833ab 100644
--- a/drivers/usb/host/uhci-platform.c
+++ b/drivers/usb/host/uhci-platform.c
@@ -148,6 +148,7 @@ static void uhci_hcd_platform_shutdown(struct platform_device *op)
}
static const struct of_device_id platform_uhci_ids[] = {
+ { .compatible = "generic-uhci", },
{ .compatible = "platform-uhci", },
{}
};
--
1.8.5.3
^ permalink raw reply related
* [PATCH 3/3] mfd: vexpress: Define the device as MFD cells
From: Pawel Moll @ 2014-02-11 16:53 UTC (permalink / raw)
To: linux-kernel, linux-arm-kernel, devicetree, lm-sensors, arm
Cc: Rob Herring, Mark Rutland, Ian Campbell, Kumar Gala,
Greg Kroah-Hartman, Mike Turquette, Jean Delvare, Guenter Roeck,
Samuel Ortiz, Lee Jones, Arnd Bergmann, Grant Likely,
Dmitry Eremin-Solenikov, David Woodhouse, Liam Girdwood,
Mark Brown, Pawel Moll
In-Reply-To: <1392137610-27842-1-git-send-email-pawel.moll@arm.com>
This patch - finally, after over 6 months! :-( - addresses
Samuel's request to split the vexpress-sysreg driver into
smaller portions and define the device in a form of MFD
cells:
* LEDs code has been completely removed and replaced with
"gpio-leds" nodes in the tree (referencing dedicated
GPIO subnodes in sysreg - bindings documentation updated);
this also better fits the reality as some variants of the
motherboard don't have all the LEDs populated
* syscfg bridge code has been extracted into a separate
driver (placed in drivers/misc for no better place)
* all the ID & MISC registers are defined as sysconf
making them available for other drivers should they need
to use them (and also to the user via /sys/kernel/debug/regmap
which can be helpful in platform debugging)
Signed-off-by: Pawel Moll <pawel.moll@arm.com>
---
.../devicetree/bindings/arm/vexpress-sysreg.txt | 36 +-
arch/arm/boot/dts/vexpress-v2m-rs1.dtsi | 76 ++-
arch/arm/boot/dts/vexpress-v2m.dtsi | 76 ++-
arch/arm/mach-vexpress/ct-ca9x4.c | 2 +-
arch/arm/mach-vexpress/v2m.c | 15 +-
drivers/mfd/Kconfig | 12 +
drivers/mfd/Makefile | 2 +-
drivers/mfd/vexpress-sysreg.c | 517 +++++----------------
drivers/misc/Kconfig | 9 +
drivers/misc/Makefile | 1 +
drivers/misc/vexpress-syscfg.c | 320 +++++++++++++
include/linux/vexpress.h | 16 +-
12 files changed, 646 insertions(+), 436 deletions(-)
create mode 100644 drivers/misc/vexpress-syscfg.c
diff --git a/Documentation/devicetree/bindings/arm/vexpress-sysreg.txt b/Documentation/devicetree/bindings/arm/vexpress-sysreg.txt
index 57b423f..00318d0 100644
--- a/Documentation/devicetree/bindings/arm/vexpress-sysreg.txt
+++ b/Documentation/devicetree/bindings/arm/vexpress-sysreg.txt
@@ -8,6 +8,8 @@ interrupt generation, MMC and NOR Flash control etc.
Required node properties:
- compatible value : = "arm,vexpress,sysreg";
- reg : physical base address and the size of the registers window
+
+Deprecated properties, replaced by GPIO subnodes (see below):
- gpio-controller : specifies that the node is a GPIO controller
- #gpio-cells : size of the GPIO specifier, should be 2:
- first cell is the pseudo-GPIO line number:
@@ -16,12 +18,42 @@ Required node properties:
2 - NOR FLASH WPn
- second cell can take standard GPIO flags (currently ignored).
+Control registers providing pseudo-GPIO lines must be represented
+by subnodes, each of them requiring the following properties:
+- compatible value : one of
+ "arm,vexpress-sysreg,sys_led"
+ "arm,vexpress-sysreg,sys_mci"
+ "arm,vexpress-sysreg,sys_flash"
+- gpio-controller : makes the node a GPIO controller
+- #gpio-cells : size of the GPIO specifier, must be 2:
+ - first cell is the function number:
+ - for sys_led : 0..7 = LED 0..7
+ - for sys_mci : 0 = MMC CARDIN, 1 = MMC WPROT
+ - for sys_flash : 0 = NOR FLASH WPn
+ - second cell can take standard GPIO flags (currently ignored).
+
Example:
v2m_sysreg: sysreg@10000000 {
compatible = "arm,vexpress-sysreg";
reg = <0x10000000 0x1000>;
- gpio-controller;
- #gpio-cells = <2>;
+
+ v2m_led_gpios: sys_led@08 {
+ compatible = "arm,vexpress-sysreg,sys_led";
+ gpio-controller;
+ #gpio-cells = <2>;
+ };
+
+ v2m_mmc_gpios: sys_mci@48 {
+ compatible = "arm,vexpress-sysreg,sys_mci";
+ gpio-controller;
+ #gpio-cells = <2>;
+ };
+
+ v2m_flash_gpios: sys_flash@4c {
+ compatible = "arm,vexpress-sysreg,sys_flash";
+ gpio-controller;
+ #gpio-cells = <2>;
+ };
};
This block also can also act a bridge to the platform's configuration
diff --git a/arch/arm/boot/dts/vexpress-v2m-rs1.dtsi b/arch/arm/boot/dts/vexpress-v2m-rs1.dtsi
index ac870fb..756c986 100644
--- a/arch/arm/boot/dts/vexpress-v2m-rs1.dtsi
+++ b/arch/arm/boot/dts/vexpress-v2m-rs1.dtsi
@@ -74,8 +74,24 @@
v2m_sysreg: sysreg@010000 {
compatible = "arm,vexpress-sysreg";
reg = <0x010000 0x1000>;
- gpio-controller;
- #gpio-cells = <2>;
+
+ v2m_led_gpios: sys_led@08 {
+ compatible = "arm,vexpress-sysreg,sys_led";
+ gpio-controller;
+ #gpio-cells = <2>;
+ };
+
+ v2m_mmc_gpios: sys_mci@48 {
+ compatible = "arm,vexpress-sysreg,sys_mci";
+ gpio-controller;
+ #gpio-cells = <2>;
+ };
+
+ v2m_flash_gpios: sys_flash@4c {
+ compatible = "arm,vexpress-sysreg,sys_flash";
+ gpio-controller;
+ #gpio-cells = <2>;
+ };
};
v2m_sysctl: sysctl@020000 {
@@ -113,8 +129,8 @@
compatible = "arm,pl180", "arm,primecell";
reg = <0x050000 0x1000>;
interrupts = <9 10>;
- cd-gpios = <&v2m_sysreg 0 0>;
- wp-gpios = <&v2m_sysreg 1 0>;
+ cd-gpios = <&v2m_mmc_gpios 0 0>;
+ wp-gpios = <&v2m_mmc_gpios 1 0>;
max-frequency = <12000000>;
vmmc-supply = <&v2m_fixed_3v3>;
clocks = <&v2m_clk24mhz>, <&smbclk>;
@@ -265,6 +281,58 @@
clock-output-names = "v2m:refclk32khz";
};
+ leds {
+ compatible = "gpio-leds";
+
+ user@1 {
+ label = "v2m:green:user1";
+ gpios = <&v2m_led_gpios 0 0>;
+ linux,default-trigger = "heartbeat";
+ };
+
+ user@2 {
+ label = "v2m:green:user2";
+ gpios = <&v2m_led_gpios 1 0>;
+ linux,default-trigger = "mmc0";
+ };
+
+ user@3 {
+ label = "v2m:green:user3";
+ gpios = <&v2m_led_gpios 2 0>;
+ linux,default-trigger = "cpu0";
+ };
+
+ user@4 {
+ label = "v2m:green:user4";
+ gpios = <&v2m_led_gpios 3 0>;
+ linux,default-trigger = "cpu1";
+ };
+
+ user@5 {
+ label = "v2m:green:user5";
+ gpios = <&v2m_led_gpios 4 0>;
+ linux,default-trigger = "cpu2";
+ };
+
+ user@6 {
+ label = "v2m:green:user6";
+ gpios = <&v2m_led_gpios 5 0>;
+ linux,default-trigger = "cpu3";
+ };
+
+ user@7 {
+ label = "v2m:green:user7";
+ gpios = <&v2m_led_gpios 6 0>;
+ linux,default-trigger = "cpu4";
+ };
+
+ user@8 {
+ label = "v2m:green:user8";
+ gpios = <&v2m_led_gpios 7 0>;
+ linux,default-trigger = "cpu5";
+ };
+ };
+
mcc {
compatible = "arm,vexpress,config-bus";
arm,vexpress,config-bridge = <&v2m_sysreg>;
diff --git a/arch/arm/boot/dts/vexpress-v2m.dtsi b/arch/arm/boot/dts/vexpress-v2m.dtsi
index f142036..ba856d6 100644
--- a/arch/arm/boot/dts/vexpress-v2m.dtsi
+++ b/arch/arm/boot/dts/vexpress-v2m.dtsi
@@ -73,8 +73,24 @@
v2m_sysreg: sysreg@00000 {
compatible = "arm,vexpress-sysreg";
reg = <0x00000 0x1000>;
- gpio-controller;
- #gpio-cells = <2>;
+
+ v2m_led_gpios: sys_led@08 {
+ compatible = "arm,vexpress-sysreg,sys_led";
+ gpio-controller;
+ #gpio-cells = <2>;
+ };
+
+ v2m_mmc_gpios: sys_mci@48 {
+ compatible = "arm,vexpress-sysreg,sys_mci";
+ gpio-controller;
+ #gpio-cells = <2>;
+ };
+
+ v2m_flash_gpios: sys_flash@4c {
+ compatible = "arm,vexpress-sysreg,sys_flash";
+ gpio-controller;
+ #gpio-cells = <2>;
+ };
};
v2m_sysctl: sysctl@01000 {
@@ -112,8 +128,8 @@
compatible = "arm,pl180", "arm,primecell";
reg = <0x05000 0x1000>;
interrupts = <9 10>;
- cd-gpios = <&v2m_sysreg 0 0>;
- wp-gpios = <&v2m_sysreg 1 0>;
+ cd-gpios = <&v2m_mmc_gpios 0 0>;
+ wp-gpios = <&v2m_mmc_gpios 1 0>;
max-frequency = <12000000>;
vmmc-supply = <&v2m_fixed_3v3>;
clocks = <&v2m_clk24mhz>, <&smbclk>;
@@ -264,6 +280,58 @@
clock-output-names = "v2m:refclk32khz";
};
+ leds {
+ compatible = "gpio-leds";
+
+ user@1 {
+ label = "v2m:green:user1";
+ gpios = <&v2m_led_gpios 0 0>;
+ linux,default-trigger = "heartbeat";
+ };
+
+ user@2 {
+ label = "v2m:green:user2";
+ gpios = <&v2m_led_gpios 1 0>;
+ linux,default-trigger = "mmc0";
+ };
+
+ user@3 {
+ label = "v2m:green:user3";
+ gpios = <&v2m_led_gpios 2 0>;
+ linux,default-trigger = "cpu0";
+ };
+
+ user@4 {
+ label = "v2m:green:user4";
+ gpios = <&v2m_led_gpios 3 0>;
+ linux,default-trigger = "cpu1";
+ };
+
+ user@5 {
+ label = "v2m:green:user5";
+ gpios = <&v2m_led_gpios 4 0>;
+ linux,default-trigger = "cpu2";
+ };
+
+ user@6 {
+ label = "v2m:green:user6";
+ gpios = <&v2m_led_gpios 5 0>;
+ linux,default-trigger = "cpu3";
+ };
+
+ user@7 {
+ label = "v2m:green:user7";
+ gpios = <&v2m_led_gpios 6 0>;
+ linux,default-trigger = "cpu4";
+ };
+
+ user@8 {
+ label = "v2m:green:user8";
+ gpios = <&v2m_led_gpios 7 0>;
+ linux,default-trigger = "cpu5";
+ };
+ };
+
mcc {
compatible = "arm,vexpress,config-bus";
arm,vexpress,config-bridge = <&v2m_sysreg>;
diff --git a/arch/arm/mach-vexpress/ct-ca9x4.c b/arch/arm/mach-vexpress/ct-ca9x4.c
index 35e394a..494d70b 100644
--- a/arch/arm/mach-vexpress/ct-ca9x4.c
+++ b/arch/arm/mach-vexpress/ct-ca9x4.c
@@ -160,7 +160,7 @@ static void __init ct_ca9x4_init(void)
amba_device_register(ct_ca9x4_amba_devs[i], &iomem_resource);
platform_device_register(&pmu_device);
- vexpress_sysreg_config_device_register(&osc1_device);
+ vexpress_syscfg_device_register(&osc1_device);
}
#ifdef CONFIG_SMP
diff --git a/arch/arm/mach-vexpress/v2m.c b/arch/arm/mach-vexpress/v2m.c
index ac95220..90f04c9 100644
--- a/arch/arm/mach-vexpress/v2m.c
+++ b/arch/arm/mach-vexpress/v2m.c
@@ -201,8 +201,9 @@ static struct platform_device v2m_cf_device = {
static struct mmci_platform_data v2m_mmci_data = {
.ocr_mask = MMC_VDD_32_33|MMC_VDD_33_34,
- .gpio_wp = VEXPRESS_GPIO_MMC_WPROT,
- .gpio_cd = VEXPRESS_GPIO_MMC_CARDIN,
+ .status = vexpress_get_mci_cardin,
+ .gpio_cd = -1,
+ .gpio_wp = -1,
};
static struct resource v2m_sysreg_resources[] = {
@@ -351,10 +352,10 @@ static void __init v2m_init(void)
for (i = 0; i < ARRAY_SIZE(v2m_amba_devs); i++)
amba_device_register(v2m_amba_devs[i], &iomem_resource);
- vexpress_sysreg_config_device_register(&v2m_muxfpga_device);
- vexpress_sysreg_config_device_register(&v2m_shutdown_device);
- vexpress_sysreg_config_device_register(&v2m_reboot_device);
- vexpress_sysreg_config_device_register(&v2m_dvimode_device);
+ vexpress_syscfg_device_register(&v2m_muxfpga_device);
+ vexpress_syscfg_device_register(&v2m_shutdown_device);
+ vexpress_syscfg_device_register(&v2m_reboot_device);
+ vexpress_syscfg_device_register(&v2m_dvimode_device);
ct_desc->init_tile();
}
@@ -409,8 +410,6 @@ void __init v2m_dt_init_early(void)
{
u32 dt_hbi;
- vexpress_sysreg_of_early_init();
-
/* Confirm board type against DT property, if available */
if (of_property_read_u32(of_allnodes, "arm,hbi", &dt_hbi) == 0) {
u32 hbi = vexpress_get_hbi(VEXPRESS_SITE_MASTER);
diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig
index 08657fa..f341110 100644
--- a/drivers/mfd/Kconfig
+++ b/drivers/mfd/Kconfig
@@ -1219,3 +1219,15 @@ config MCP_UCB1200_TS
depends on MCP_UCB1200 && INPUT
endmenu
+
+config MFD_VEXPRESS_SYSREG
+ bool "Versatile Express System Registers"
+ depends on VEXPRESS_CONFIG
+ default y
+ select CLKSRC_MMIO
+ select GPIO_GENERIC_PLATFORM
+ select MFD_CORE
+ select MFD_SYSCON
+ help
+ System Registers are the platform configuration block
+ on the ARM Ltd. Versatile Express board.
diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile
index 816b258..6c4ff74 100644
--- a/drivers/mfd/Makefile
+++ b/drivers/mfd/Makefile
@@ -161,7 +161,7 @@ obj-$(CONFIG_MFD_RC5T583) += rc5t583.o rc5t583-irq.o
obj-$(CONFIG_MFD_SEC_CORE) += sec-core.o sec-irq.o
obj-$(CONFIG_MFD_SYSCON) += syscon.o
obj-$(CONFIG_MFD_LM3533) += lm3533-core.o lm3533-ctrlbank.o
-obj-$(CONFIG_VEXPRESS_CONFIG) += vexpress-sysreg.o
+obj-$(CONFIG_MFD_VEXPRESS_SYSREG) += vexpress-sysreg.o
obj-$(CONFIG_MFD_RETU) += retu-mfd.o
obj-$(CONFIG_MFD_AS3711) += as3711.o
obj-$(CONFIG_MFD_AS3722) += as3722.o
diff --git a/drivers/mfd/vexpress-sysreg.c b/drivers/mfd/vexpress-sysreg.c
index b4138a7..f639dff 100644
--- a/drivers/mfd/vexpress-sysreg.c
+++ b/drivers/mfd/vexpress-sysreg.c
@@ -11,25 +11,21 @@
* Copyright (C) 2012 ARM Limited
*/
+#include <linux/basic_mmio_gpio.h>
#include <linux/err.h>
-#include <linux/gpio.h>
#include <linux/io.h>
-#include <linux/leds.h>
+#include <linux/mfd/core.h>
#include <linux/of_address.h>
#include <linux/of_platform.h>
#include <linux/platform_device.h>
-#include <linux/regulator/driver.h>
-#include <linux/sched.h>
#include <linux/slab.h>
#include <linux/stat.h>
-#include <linux/timer.h>
#include <linux/vexpress.h>
#define SYS_ID 0x000
#define SYS_SW 0x004
#define SYS_LED 0x008
#define SYS_100HZ 0x024
-#define SYS_FLAGS 0x030
#define SYS_FLAGSSET 0x030
#define SYS_FLAGSCLR 0x034
#define SYS_NVFLAGS 0x038
@@ -51,36 +47,32 @@
#define SYS_ID_HBI_SHIFT 16
#define SYS_PROCIDx_HBI_SHIFT 0
-#define SYS_LED_LED(n) (1 << (n))
-
#define SYS_MCI_CARDIN (1 << 0)
#define SYS_MCI_WPROT (1 << 1)
-#define SYS_FLASH_WPn (1 << 0)
-
#define SYS_MISC_MASTERSITE (1 << 14)
-#define SYS_CFGCTRL_START (1 << 31)
-#define SYS_CFGCTRL_WRITE (1 << 30)
-#define SYS_CFGCTRL_DCC(n) (((n) & 0xf) << 26)
-#define SYS_CFGCTRL_FUNC(n) (((n) & 0x3f) << 20)
-#define SYS_CFGCTRL_SITE(n) (((n) & 0x3) << 16)
-#define SYS_CFGCTRL_POSITION(n) (((n) & 0xf) << 12)
-#define SYS_CFGCTRL_DEVICE(n) (((n) & 0xfff) << 0)
-#define SYS_CFGSTAT_ERR (1 << 1)
-#define SYS_CFGSTAT_COMPLETE (1 << 0)
+static void __iomem *__vexpress_sysreg_base;
+static void __iomem *vexpress_sysreg_base(void)
+{
+ if (!__vexpress_sysreg_base) {
+ struct device_node *node = of_find_compatible_node(NULL, NULL,
+ "arm,vexpress-sysreg");
-static void __iomem *vexpress_sysreg_base;
-static struct device *vexpress_sysreg_dev;
-static LIST_HEAD(vexpress_sysreg_config_funcs);
-static struct device *vexpress_sysreg_config_bridge;
+ __vexpress_sysreg_base = of_iomap(node, 0);
+ }
+
+ WARN_ON(!__vexpress_sysreg_base);
+
+ return __vexpress_sysreg_base;
+}
static int vexpress_sysreg_get_master(void)
{
- if (readl(vexpress_sysreg_base + SYS_MISC) & SYS_MISC_MASTERSITE)
+ if (readl(vexpress_sysreg_base() + SYS_MISC) & SYS_MISC_MASTERSITE)
return VEXPRESS_SITE_DB2;
return VEXPRESS_SITE_DB1;
@@ -88,8 +80,13 @@ static int vexpress_sysreg_get_master(void)
void vexpress_flags_set(u32 data)
{
- writel(~0, vexpress_sysreg_base + SYS_FLAGSCLR);
- writel(data, vexpress_sysreg_base + SYS_FLAGSSET);
+ writel(~0, vexpress_sysreg_base() + SYS_FLAGSCLR);
+ writel(data, vexpress_sysreg_base() + SYS_FLAGSSET);
+}
+
+unsigned int vexpress_get_mci_cardin(struct device *dev)
+{
+ return readl(vexpress_sysreg_base() + SYS_MCI) & SYS_MCI_CARDIN;
}
u32 vexpress_get_procid(int site)
@@ -97,7 +94,7 @@ u32 vexpress_get_procid(int site)
if (site == VEXPRESS_SITE_MASTER)
site = vexpress_sysreg_get_master();
- return readl(vexpress_sysreg_base + (site == VEXPRESS_SITE_DB1 ?
+ return readl(vexpress_sysreg_base() + (site == VEXPRESS_SITE_DB1 ?
SYS_PROCID0 : SYS_PROCID1));
}
@@ -107,7 +104,7 @@ u32 vexpress_get_hbi(int site)
switch (site) {
case VEXPRESS_SITE_MB:
- id = readl(vexpress_sysreg_base + SYS_ID);
+ id = readl(vexpress_sysreg_base() + SYS_ID);
return (id >> SYS_ID_HBI_SHIFT) & SYS_HBI_MASK;
case VEXPRESS_SITE_MASTER:
case VEXPRESS_SITE_DB1:
@@ -121,406 +118,122 @@ u32 vexpress_get_hbi(int site)
void __iomem *vexpress_get_24mhz_clock_base(void)
{
- return vexpress_sysreg_base + SYS_24MHZ;
-}
-
-
-struct vexpress_sysreg_config_func {
- struct list_head list;
- struct regmap *regmap;
- int num_templates;
- u32 template[0]; /* Keep this last */
-};
-
-static int vexpress_sysreg_config_exec(struct vexpress_sysreg_config_func *func,
- int index, bool write, u32 *data)
-{
- u32 command, status;
- int tries;
- long timeout;
-
- if (WARN_ON(!vexpress_sysreg_base))
- return -ENOENT;
-
- if (WARN_ON(index > func->num_templates))
- return -EINVAL;
-
- command = readl(vexpress_sysreg_base + SYS_CFGCTRL);
- if (WARN_ON(command & SYS_CFGCTRL_START))
- return -EBUSY;
-
- command = func->template[index];
- command |= SYS_CFGCTRL_START;
- command |= write ? SYS_CFGCTRL_WRITE : 0;
-
- /* Use a canary for reads */
- if (!write)
- *data = 0xdeadbeef;
-
- dev_dbg(vexpress_sysreg_dev, "command %x, data %x\n",
- command, *data);
- writel(*data, vexpress_sysreg_base + SYS_CFGDATA);
- writel(0, vexpress_sysreg_base + SYS_CFGSTAT);
- writel(command, vexpress_sysreg_base + SYS_CFGCTRL);
- mb();
-
- /* The operation can take ages... Go to sleep, 100us initially */
- tries = 100;
- timeout = 100;
- do {
- set_current_state(TASK_INTERRUPTIBLE);
- schedule_timeout(usecs_to_jiffies(timeout));
- if (signal_pending(current))
- return -EINTR;
-
- status = readl(vexpress_sysreg_base + SYS_CFGSTAT);
- if (status & SYS_CFGSTAT_ERR)
- return -EFAULT;
-
- if (timeout > 20)
- timeout -= 20;
- } while (--tries && !(status & SYS_CFGSTAT_COMPLETE));
- if (WARN_ON_ONCE(!tries))
- return -ETIMEDOUT;
-
- if (!write) {
- *data = readl(vexpress_sysreg_base + SYS_CFGDATA);
- dev_dbg(vexpress_sysreg_dev, "func %p, read data %x\n",
- func, *data);
- }
-
- return 0;
-}
-
-static int vexpress_sysreg_config_read(void *context, unsigned int index,
- unsigned int *val)
-{
- struct vexpress_sysreg_config_func *func = context;
-
- return vexpress_sysreg_config_exec(func, index, false, val);
-}
-
-static int vexpress_sysreg_config_write(void *context, unsigned int index,
- unsigned int val)
-{
- struct vexpress_sysreg_config_func *func = context;
-
- return vexpress_sysreg_config_exec(func, index, true, &val);
-}
-
-struct regmap_config vexpress_sysreg_regmap_config = {
- .lock = vexpress_config_lock,
- .unlock = vexpress_config_unlock,
- .reg_bits = 32,
- .val_bits = 32,
- .reg_read = vexpress_sysreg_config_read,
- .reg_write = vexpress_sysreg_config_write,
- .reg_format_endian = REGMAP_ENDIAN_LITTLE,
- .val_format_endian = REGMAP_ENDIAN_LITTLE,
-};
-
-static struct regmap *vexpress_sysreg_config_regmap_init(struct device *dev,
- void *context)
-{
- struct platform_device *pdev = to_platform_device(dev);
- struct vexpress_sysreg_config_func *func;
- struct property *prop;
- const __be32 *val = NULL;
- __be32 energy_quirk[4];
- int num;
- u32 site, position, dcc;
- int err;
- int i;
-
- if (dev->of_node) {
- err = vexpress_config_get_topo(dev->of_node, &site, &position,
- &dcc);
- if (err)
- return ERR_PTR(err);
-
- prop = of_find_property(dev->of_node,
- "arm,vexpress-sysreg,func", NULL);
- if (!prop)
- return ERR_PTR(-EINVAL);
-
- num = prop->length / sizeof(u32) / 2;
- val = prop->value;
- } else {
- if (pdev->num_resources != 1 ||
- pdev->resource[0].flags != IORESOURCE_BUS)
- return ERR_PTR(-EFAULT);
-
- site = pdev->resource[0].start;
- if (site == VEXPRESS_SITE_MASTER)
- site = vexpress_sysreg_get_master();
- position = 0;
- dcc = 0;
- num = 1;
- }
-
- /*
- * "arm,vexpress-energy" function used to be described
- * by its first device only, now it requires both
- */
- if (num == 1 && of_device_is_compatible(dev->of_node,
- "arm,vexpress-energy")) {
- num = 2;
- energy_quirk[0] = *val;
- energy_quirk[2] = *val++;
- energy_quirk[1] = *val;
- energy_quirk[3] = cpu_to_be32(be32_to_cpup(val) + 1);
- val = energy_quirk;
- }
-
- func = kzalloc(sizeof(*func) + sizeof(*func->template) * num,
- GFP_KERNEL);
- if (!func)
- return NULL;
-
- func->num_templates = num;
-
- for (i = 0; i < num; i++) {
- u32 function, device;
-
- if (dev->of_node) {
- function = be32_to_cpup(val++);
- device = be32_to_cpup(val++);
- } else {
- function = pdev->resource[0].end;
- device = pdev->id;
- }
-
- dev_dbg(dev, "func %p: %u/%u/%u/%u/%u\n",
- func, site, position, dcc,
- function, device);
-
- func->template[i] = SYS_CFGCTRL_DCC(dcc);
- func->template[i] |= SYS_CFGCTRL_SITE(site);
- func->template[i] |= SYS_CFGCTRL_POSITION(position);
- func->template[i] |= SYS_CFGCTRL_FUNC(function);
- func->template[i] |= SYS_CFGCTRL_DEVICE(device);
- }
-
- vexpress_sysreg_regmap_config.max_register = num - 1;
-
- func->regmap = regmap_init(dev, NULL, func,
- &vexpress_sysreg_regmap_config);
-
- if (IS_ERR(func->regmap))
- kfree(func);
- else
- list_add(&func->list, &vexpress_sysreg_config_funcs);
-
- return func->regmap;
-}
-
-static void vexpress_sysreg_config_regmap_exit(struct regmap *regmap,
- void *context)
-{
- struct vexpress_sysreg_config_func *func, *tmp;
-
- regmap_exit(regmap);
-
- list_for_each_entry_safe(func, tmp, &vexpress_sysreg_config_funcs,
- list) {
- if (func->regmap == regmap) {
- list_del(&vexpress_sysreg_config_funcs);
- kfree(func);
- break;
- }
- }
-}
-
-static struct vexpress_config_bridge_ops vexpress_sysreg_config_bridge_ops = {
- .regmap_init = vexpress_sysreg_config_regmap_init,
- .regmap_exit = vexpress_sysreg_config_regmap_exit,
-};
-
-int vexpress_sysreg_config_device_register(struct platform_device *pdev)
-{
- pdev->dev.parent = vexpress_sysreg_config_bridge;
-
- return platform_device_register(pdev);
+ return vexpress_sysreg_base() + SYS_24MHZ;
}
void __init vexpress_sysreg_early_init(void __iomem *base)
{
- vexpress_sysreg_base = base;
- vexpress_config_set_master(vexpress_sysreg_get_master());
-}
-
-void __init vexpress_sysreg_of_early_init(void)
-{
- struct device_node *node;
-
- if (vexpress_sysreg_base)
- return;
-
- node = of_find_compatible_node(NULL, NULL, "arm,vexpress-sysreg");
- if (WARN_ON(!node))
- return;
-
- vexpress_sysreg_base = of_iomap(node, 0);
- if (WARN_ON(!vexpress_sysreg_base))
- return;
+ __vexpress_sysreg_base = base;
vexpress_config_set_master(vexpress_sysreg_get_master());
}
-#ifdef CONFIG_GPIOLIB
-
-#define VEXPRESS_SYSREG_GPIO(_name, _reg, _value) \
- [VEXPRESS_GPIO_##_name] = { \
- .reg = _reg, \
- .value = _reg##_##_value, \
- }
+/* The sysreg block is just a random collection of various functions... */
-static struct vexpress_sysreg_gpio {
- unsigned long reg;
- u32 value;
-} vexpress_sysreg_gpios[] = {
- VEXPRESS_SYSREG_GPIO(MMC_CARDIN, SYS_MCI, CARDIN),
- VEXPRESS_SYSREG_GPIO(MMC_WPROT, SYS_MCI, WPROT),
- VEXPRESS_SYSREG_GPIO(FLASH_WPn, SYS_FLASH, WPn),
- VEXPRESS_SYSREG_GPIO(LED0, SYS_LED, LED(0)),
- VEXPRESS_SYSREG_GPIO(LED1, SYS_LED, LED(1)),
- VEXPRESS_SYSREG_GPIO(LED2, SYS_LED, LED(2)),
- VEXPRESS_SYSREG_GPIO(LED3, SYS_LED, LED(3)),
- VEXPRESS_SYSREG_GPIO(LED4, SYS_LED, LED(4)),
- VEXPRESS_SYSREG_GPIO(LED5, SYS_LED, LED(5)),
- VEXPRESS_SYSREG_GPIO(LED6, SYS_LED, LED(6)),
- VEXPRESS_SYSREG_GPIO(LED7, SYS_LED, LED(7)),
+static struct bgpio_pdata vexpress_sysreg_sys_led_pdata = {
+ .base = -1,
+ .ngpio = 8,
};
-static int vexpress_sysreg_gpio_direction_input(struct gpio_chip *chip,
- unsigned offset)
-{
- return 0;
-}
-
-static int vexpress_sysreg_gpio_get(struct gpio_chip *chip,
- unsigned offset)
-{
- struct vexpress_sysreg_gpio *gpio = &vexpress_sysreg_gpios[offset];
- u32 reg_value = readl(vexpress_sysreg_base + gpio->reg);
-
- return !!(reg_value & gpio->value);
-}
-
-static void vexpress_sysreg_gpio_set(struct gpio_chip *chip,
- unsigned offset, int value)
-{
- struct vexpress_sysreg_gpio *gpio = &vexpress_sysreg_gpios[offset];
- u32 reg_value = readl(vexpress_sysreg_base + gpio->reg);
-
- if (value)
- reg_value |= gpio->value;
- else
- reg_value &= ~gpio->value;
-
- writel(reg_value, vexpress_sysreg_base + gpio->reg);
-}
-
-static int vexpress_sysreg_gpio_direction_output(struct gpio_chip *chip,
- unsigned offset, int value)
-{
- vexpress_sysreg_gpio_set(chip, offset, value);
-
- return 0;
-}
-
-static struct gpio_chip vexpress_sysreg_gpio_chip = {
- .label = "vexpress-sysreg",
- .direction_input = vexpress_sysreg_gpio_direction_input,
- .direction_output = vexpress_sysreg_gpio_direction_output,
- .get = vexpress_sysreg_gpio_get,
- .set = vexpress_sysreg_gpio_set,
- .ngpio = ARRAY_SIZE(vexpress_sysreg_gpios),
- .base = 0,
+static struct bgpio_pdata vexpress_sysreg_sys_mci_pdata = {
+ .base = -1,
+ .ngpio = 2,
};
-
-#define VEXPRESS_SYSREG_GREEN_LED(_name, _default_trigger, _gpio) \
- { \
- .name = "v2m:green:"_name, \
- .default_trigger = _default_trigger, \
- .gpio = VEXPRESS_GPIO_##_gpio, \
- }
-
-struct gpio_led vexpress_sysreg_leds[] = {
- VEXPRESS_SYSREG_GREEN_LED("user1", "heartbeat", LED0),
- VEXPRESS_SYSREG_GREEN_LED("user2", "mmc0", LED1),
- VEXPRESS_SYSREG_GREEN_LED("user3", "cpu0", LED2),
- VEXPRESS_SYSREG_GREEN_LED("user4", "cpu1", LED3),
- VEXPRESS_SYSREG_GREEN_LED("user5", "cpu2", LED4),
- VEXPRESS_SYSREG_GREEN_LED("user6", "cpu3", LED5),
- VEXPRESS_SYSREG_GREEN_LED("user7", "cpu4", LED6),
- VEXPRESS_SYSREG_GREEN_LED("user8", "cpu5", LED7),
+static struct bgpio_pdata vexpress_sysreg_sys_flash_pdata = {
+ .base = -1,
+ .ngpio = 1,
};
-struct gpio_led_platform_data vexpress_sysreg_leds_pdata = {
- .num_leds = ARRAY_SIZE(vexpress_sysreg_leds),
- .leds = vexpress_sysreg_leds,
+static struct mfd_cell vexpress_sysreg_cells[] = {
+ {
+ .name = "syscon",
+ .num_resources = 1,
+ .resources = (struct resource []) {
+ DEFINE_RES_MEM(SYS_ID, 0x4),
+ },
+ }, {
+ .name = "basic-mmio-gpio",
+ .of_compatible = "arm,vexpress-sysreg,sys_led",
+ .num_resources = 1,
+ .resources = (struct resource []) {
+ DEFINE_RES_MEM_NAMED(SYS_LED, 0x4, "dat"),
+ },
+ .platform_data = &vexpress_sysreg_sys_led_pdata,
+ .pdata_size = sizeof(vexpress_sysreg_sys_led_pdata),
+ }, {
+ .name = "basic-mmio-gpio",
+ .of_compatible = "arm,vexpress-sysreg,sys_mci",
+ .num_resources = 1,
+ .resources = (struct resource []) {
+ DEFINE_RES_MEM_NAMED(SYS_MCI, 0x4, "dat"),
+ },
+ .platform_data = &vexpress_sysreg_sys_mci_pdata,
+ .pdata_size = sizeof(vexpress_sysreg_sys_mci_pdata),
+ }, {
+ .name = "basic-mmio-gpio",
+ .of_compatible = "arm,vexpress-sysreg,sys_flash",
+ .num_resources = 1,
+ .resources = (struct resource []) {
+ DEFINE_RES_MEM_NAMED(SYS_FLASH, 0x4, "dat"),
+ },
+ .platform_data = &vexpress_sysreg_sys_flash_pdata,
+ .pdata_size = sizeof(vexpress_sysreg_sys_flash_pdata),
+ }, {
+ .name = "syscon",
+ .num_resources = 1,
+ .resources = (struct resource []) {
+ DEFINE_RES_MEM(SYS_MISC, 0x4),
+ },
+ }, {
+ .name = "syscon",
+ .num_resources = 1,
+ .resources = (struct resource []) {
+ DEFINE_RES_MEM(SYS_PROCID0, 0x8),
+ },
+ }, {
+ .name = "vexpress-syscfg",
+ .num_resources = 1,
+ .resources = (struct resource []) {
+ DEFINE_RES_MEM(SYS_CFGDATA, 0xc),
+ },
+ }
};
-#endif
-
-
-static ssize_t vexpress_sysreg_sys_id_show(struct device *dev,
- struct device_attribute *attr, char *buf)
-{
- return sprintf(buf, "0x%08x\n", readl(vexpress_sysreg_base + SYS_ID));
-}
-
-DEVICE_ATTR(sys_id, S_IRUGO, vexpress_sysreg_sys_id_show, NULL);
-
static int vexpress_sysreg_probe(struct platform_device *pdev)
{
- int err;
- struct resource *res = platform_get_resource(pdev,
- IORESOURCE_MEM, 0);
-
- if (!devm_request_mem_region(&pdev->dev, res->start,
- resource_size(res), pdev->name)) {
- dev_err(&pdev->dev, "Failed to request memory region!\n");
- return -EBUSY;
- }
+ struct resource *mem;
+ void __iomem *base;
+ struct bgpio_chip *mmc_gpio_chip;
- if (!vexpress_sysreg_base)
- vexpress_sysreg_base = devm_ioremap(&pdev->dev, res->start,
- resource_size(res));
+ mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ if (!mem)
+ return -EINVAL;
- if (!vexpress_sysreg_base) {
- dev_err(&pdev->dev, "Failed to obtain base address!\n");
- return -EFAULT;
- }
+ base = devm_ioremap(&pdev->dev, mem->start, resource_size(mem));
+ if (!base)
+ return -ENOMEM;
vexpress_config_set_master(vexpress_sysreg_get_master());
- vexpress_sysreg_dev = &pdev->dev;
-
-#ifdef CONFIG_GPIOLIB
- vexpress_sysreg_gpio_chip.dev = &pdev->dev;
- err = gpiochip_add(&vexpress_sysreg_gpio_chip);
- if (err) {
- dev_err(&pdev->dev, "Failed to register GPIO chip! (%d)\n",
- err);
- return err;
- }
- platform_device_register_data(vexpress_sysreg_dev, "leds-gpio",
- PLATFORM_DEVID_AUTO, &vexpress_sysreg_leds_pdata,
- sizeof(vexpress_sysreg_leds_pdata));
-#endif
-
- vexpress_sysreg_config_bridge = vexpress_config_bridge_register(
- &pdev->dev, &vexpress_sysreg_config_bridge_ops, NULL);
- WARN_ON(!vexpress_sysreg_config_bridge);
-
- device_create_file(vexpress_sysreg_dev, &dev_attr_sys_id);
-
- return 0;
+ /*
+ * Duplicated SYS_MCI pseudo-GPIO controller for compatibility with
+ * older trees using sysreg node for MMC control lines.
+ */
+ mmc_gpio_chip = devm_kzalloc(&pdev->dev, sizeof(*mmc_gpio_chip),
+ GFP_KERNEL);
+ if (!mmc_gpio_chip)
+ return -ENOMEM;
+ bgpio_init(mmc_gpio_chip, &pdev->dev, 0x4, base + SYS_MCI,
+ NULL, NULL, NULL, NULL, 0);
+ mmc_gpio_chip->gc.ngpio = 2;
+ gpiochip_add(&mmc_gpio_chip->gc);
+
+ return mfd_add_devices(&pdev->dev, PLATFORM_DEVID_AUTO,
+ vexpress_sysreg_cells,
+ ARRAY_SIZE(vexpress_sysreg_cells), mem, 0, NULL);
}
static const struct of_device_id vexpress_sysreg_match[] = {
diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig
index 6cb388e..28d9228 100644
--- a/drivers/misc/Kconfig
+++ b/drivers/misc/Kconfig
@@ -515,6 +515,15 @@ config SRAM
the genalloc API. It is supposed to be used for small on-chip SRAM
areas found on many SoCs.
+config VEXPRESS_SYSCFG
+ bool "Versatile Express System Configuration driver"
+ depends on VEXPRESS_CONFIG
+ default y
+ help
+ ARM Ltd. Versatile Express uses specialised platform configuration
+ bus. System Configuration interface is one of the possible means
+ of generating transactions on this bus.
+
source "drivers/misc/c2port/Kconfig"
source "drivers/misc/eeprom/Kconfig"
source "drivers/misc/cb710/Kconfig"
diff --git a/drivers/misc/Makefile b/drivers/misc/Makefile
index 99b9424..427ae5e 100644
--- a/drivers/misc/Makefile
+++ b/drivers/misc/Makefile
@@ -54,3 +54,4 @@ obj-$(CONFIG_LATTICE_ECP3_CONFIG) += lattice-ecp3-config.o
obj-$(CONFIG_SRAM) += sram.o
obj-y += mic/
obj-$(CONFIG_GENWQE) += genwqe/
+obj-$(CONFIG_VEXPRESS_SYSCFG) += vexpress-syscfg.o
diff --git a/drivers/misc/vexpress-syscfg.c b/drivers/misc/vexpress-syscfg.c
new file mode 100644
index 0000000..4d661ef
--- /dev/null
+++ b/drivers/misc/vexpress-syscfg.c
@@ -0,0 +1,320 @@
+/*
+ * 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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * Copyright (C) 2014 ARM Limited
+ */
+
+#include <linux/delay.h>
+#include <linux/err.h>
+#include <linux/io.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+#include <linux/sched.h>
+#include <linux/slab.h>
+#include <linux/syscore_ops.h>
+#include <linux/vexpress.h>
+
+
+#define SYS_CFGDATA 0x0
+
+#define SYS_CFGCTRL 0x4
+#define SYS_CFGCTRL_START (1 << 31)
+#define SYS_CFGCTRL_WRITE (1 << 30)
+#define SYS_CFGCTRL_DCC(n) (((n) & 0xf) << 26)
+#define SYS_CFGCTRL_FUNC(n) (((n) & 0x3f) << 20)
+#define SYS_CFGCTRL_SITE(n) (((n) & 0x3) << 16)
+#define SYS_CFGCTRL_POSITION(n) (((n) & 0xf) << 12)
+#define SYS_CFGCTRL_DEVICE(n) (((n) & 0xfff) << 0)
+
+#define SYS_CFGSTAT 0x8
+#define SYS_CFGSTAT_ERR (1 << 1)
+#define SYS_CFGSTAT_COMPLETE (1 << 0)
+
+
+struct vexpress_syscfg {
+ struct device *dev;
+ void __iomem *base;
+ struct list_head funcs;
+};
+
+struct vexpress_syscfg_func {
+ struct list_head list;
+ struct vexpress_syscfg *syscfg;
+ struct regmap *regmap;
+ int num_templates;
+ u32 template[0]; /* Keep it last! */
+};
+
+
+static int vexpress_syscfg_exec(struct vexpress_syscfg_func *func,
+ int index, bool write, u32 *data)
+{
+ struct vexpress_syscfg *syscfg = func->syscfg;
+ u32 command, status;
+ int tries;
+ long timeout;
+
+ if (WARN_ON(index > func->num_templates))
+ return -EINVAL;
+
+ command = readl(syscfg->base + SYS_CFGCTRL);
+ if (WARN_ON(command & SYS_CFGCTRL_START))
+ return -EBUSY;
+
+ command = func->template[index];
+ command |= SYS_CFGCTRL_START;
+ command |= write ? SYS_CFGCTRL_WRITE : 0;
+
+ /* Use a canary for reads */
+ if (!write)
+ *data = 0xdeadbeef;
+
+ dev_dbg(syscfg->dev, "func %p, command %x, data %x\n",
+ func, command, *data);
+ writel(*data, syscfg->base + SYS_CFGDATA);
+ writel(0, syscfg->base + SYS_CFGSTAT);
+ writel(command, syscfg->base + SYS_CFGCTRL);
+ mb();
+
+ /* The operation can take ages... Go to sleep, 100us initially */
+ tries = 100;
+ timeout = 100;
+ do {
+ set_current_state(TASK_INTERRUPTIBLE);
+ schedule_timeout(usecs_to_jiffies(timeout));
+ if (signal_pending(current))
+ return -EINTR;
+
+ status = readl(syscfg->base + SYS_CFGSTAT);
+ if (status & SYS_CFGSTAT_ERR)
+ return -EFAULT;
+
+ if (timeout > 20)
+ timeout -= 20;
+ } while (--tries && !(status & SYS_CFGSTAT_COMPLETE));
+ if (WARN_ON_ONCE(!tries))
+ return -ETIMEDOUT;
+
+ if (!write) {
+ *data = readl(syscfg->base + SYS_CFGDATA);
+ dev_dbg(syscfg->dev, "func %p, read data %x\n", func, *data);
+ }
+
+ return 0;
+}
+
+static int vexpress_syscfg_read(void *context, unsigned int index,
+ unsigned int *val)
+{
+ struct vexpress_syscfg_func *func = context;
+
+ return vexpress_syscfg_exec(func, index, false, val);
+}
+
+static int vexpress_syscfg_write(void *context, unsigned int index,
+ unsigned int val)
+{
+ struct vexpress_syscfg_func *func = context;
+
+ return vexpress_syscfg_exec(func, index, true, &val);
+}
+
+struct regmap_config vexpress_syscfg_regmap_config = {
+ .lock = vexpress_config_lock,
+ .unlock = vexpress_config_unlock,
+ .reg_bits = 32,
+ .val_bits = 32,
+ .reg_read = vexpress_syscfg_read,
+ .reg_write = vexpress_syscfg_write,
+ .reg_format_endian = REGMAP_ENDIAN_LITTLE,
+ .val_format_endian = REGMAP_ENDIAN_LITTLE,
+};
+
+
+static struct regmap *vexpress_syscfg_regmap_init(struct device *dev,
+ void *context)
+{
+ struct platform_device *pdev = to_platform_device(dev);
+ struct vexpress_syscfg *syscfg = context;
+ struct vexpress_syscfg_func *func;
+ struct property *prop;
+ const __be32 *val = NULL;
+ __be32 energy_quirk[4];
+ int num;
+ u32 site, position, dcc;
+ int i;
+
+ if (dev->of_node) {
+ int err = vexpress_config_get_topo(dev->of_node, &site,
+ &position, &dcc);
+
+ if (err)
+ return ERR_PTR(err);
+
+ prop = of_find_property(dev->of_node,
+ "arm,vexpress-sysreg,func", NULL);
+ if (!prop)
+ return ERR_PTR(-EINVAL);
+
+ num = prop->length / sizeof(u32) / 2;
+ val = prop->value;
+ } else {
+ if (pdev->num_resources != 1 ||
+ pdev->resource[0].flags != IORESOURCE_BUS)
+ return ERR_PTR(-EFAULT);
+
+ site = pdev->resource[0].start;
+ if (site == VEXPRESS_SITE_MASTER)
+ site = vexpress_config_get_master();
+ position = 0;
+ dcc = 0;
+ num = 1;
+ }
+
+ /*
+ * "arm,vexpress-energy" function used to be described
+ * by its first device only, now it requires both
+ */
+ if (num == 1 && of_device_is_compatible(dev->of_node,
+ "arm,vexpress-energy")) {
+ num = 2;
+ energy_quirk[0] = *val;
+ energy_quirk[2] = *val++;
+ energy_quirk[1] = *val;
+ energy_quirk[3] = cpu_to_be32(be32_to_cpup(val) + 1);
+ val = energy_quirk;
+ }
+
+ func = kzalloc(sizeof(*func) + sizeof(*func->template) * num,
+ GFP_KERNEL);
+ if (!func)
+ return NULL;
+
+ func->syscfg = syscfg;
+ func->num_templates = num;
+
+ for (i = 0; i < num; i++) {
+ u32 function, device;
+
+ if (dev->of_node) {
+ function = be32_to_cpup(val++);
+ device = be32_to_cpup(val++);
+ } else {
+ function = pdev->resource[0].end;
+ device = pdev->id;
+ }
+
+ dev_dbg(dev, "func %p: %u/%u/%u/%u/%u\n",
+ func, site, position, dcc,
+ function, device);
+
+ func->template[i] = SYS_CFGCTRL_DCC(dcc);
+ func->template[i] |= SYS_CFGCTRL_SITE(site);
+ func->template[i] |= SYS_CFGCTRL_POSITION(position);
+ func->template[i] |= SYS_CFGCTRL_FUNC(function);
+ func->template[i] |= SYS_CFGCTRL_DEVICE(device);
+ }
+
+ vexpress_syscfg_regmap_config.max_register = num - 1;
+
+ func->regmap = regmap_init(dev, NULL, func,
+ &vexpress_syscfg_regmap_config);
+
+ if (IS_ERR(func->regmap))
+ kfree(func);
+ else
+ list_add(&func->list, &syscfg->funcs);
+
+ return func->regmap;
+}
+
+static void vexpress_syscfg_regmap_exit(struct regmap *regmap, void *context)
+{
+ struct vexpress_syscfg *syscfg = context;
+ struct vexpress_syscfg_func *func, *tmp;
+
+ regmap_exit(regmap);
+
+ list_for_each_entry_safe(func, tmp, &syscfg->funcs, list) {
+ if (func->regmap == regmap) {
+ list_del(&syscfg->funcs);
+ kfree(func);
+ break;
+ }
+ }
+}
+
+static struct vexpress_config_bridge_ops vexpress_syscfg_bridge_ops = {
+ .regmap_init = vexpress_syscfg_regmap_init,
+ .regmap_exit = vexpress_syscfg_regmap_exit,
+};
+
+
+/* Non-DT hack, to be gone... */
+static struct device *vexpress_syscfg_bridge;
+
+int vexpress_syscfg_device_register(struct platform_device *pdev)
+{
+ pdev->dev.parent = vexpress_syscfg_bridge;
+
+ return platform_device_register(pdev);
+}
+
+
+int vexpress_syscfg_probe(struct platform_device *pdev)
+{
+ struct vexpress_syscfg *syscfg;
+ struct resource *res;
+ struct device *bridge;
+
+ syscfg = devm_kzalloc(&pdev->dev, sizeof(*syscfg), GFP_KERNEL);
+ if (!syscfg)
+ return -ENOMEM;
+ syscfg->dev = &pdev->dev;
+ INIT_LIST_HEAD(&syscfg->funcs);
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ if (!devm_request_mem_region(&pdev->dev, res->start,
+ resource_size(res), pdev->name))
+ return -EBUSY;
+
+ syscfg->base = devm_ioremap(&pdev->dev, res->start, resource_size(res));
+ if (!syscfg->base)
+ return -EFAULT;
+
+ /* Must use dev.parent (MFD), as that's where DT phandle points at... */
+ bridge = vexpress_config_bridge_register(pdev->dev.parent,
+ &vexpress_syscfg_bridge_ops, syscfg);
+ if (IS_ERR(bridge))
+ return PTR_ERR(bridge);
+
+ /* Non-DT case */
+ if (!pdev->dev.of_node)
+ vexpress_syscfg_bridge = bridge;
+
+ return 0;
+}
+
+static const struct platform_device_id vexpress_syscfg_id_table[] = {
+ { "vexpress-syscfg", },
+ {},
+};
+
+static struct platform_driver vexpress_syscfg_driver = {
+ .driver.name = "vexpress-syscfg",
+ .id_table = vexpress_syscfg_id_table,
+ .probe = vexpress_syscfg_probe,
+};
+
+static int __init vexpress_syscfg_init(void)
+{
+ return platform_driver_register(&vexpress_syscfg_driver);
+}
+core_initcall(vexpress_syscfg_init);
diff --git a/include/linux/vexpress.h b/include/linux/vexpress.h
index ae4d2a1..0aee1b9 100644
--- a/include/linux/vexpress.h
+++ b/include/linux/vexpress.h
@@ -24,18 +24,6 @@
#define VEXPRESS_SITE_DB2 2
#define VEXPRESS_SITE_MASTER 0xf
-#define VEXPRESS_GPIO_MMC_CARDIN 0
-#define VEXPRESS_GPIO_MMC_WPROT 1
-#define VEXPRESS_GPIO_FLASH_WPn 2
-#define VEXPRESS_GPIO_LED0 3
-#define VEXPRESS_GPIO_LED1 4
-#define VEXPRESS_GPIO_LED2 5
-#define VEXPRESS_GPIO_LED3 6
-#define VEXPRESS_GPIO_LED4 7
-#define VEXPRESS_GPIO_LED5 8
-#define VEXPRESS_GPIO_LED6 9
-#define VEXPRESS_GPIO_LED7 10
-
#define VEXPRESS_RES_FUNC(_site, _func) \
{ \
.start = (_site), \
@@ -70,14 +58,14 @@ struct regmap *devm_regmap_init_vexpress_config(struct device *dev);
/* Platform control */
+unsigned int vexpress_get_mci_cardin(struct device *dev);
u32 vexpress_get_procid(int site);
u32 vexpress_get_hbi(int site);
void *vexpress_get_24mhz_clock_base(void);
void vexpress_flags_set(u32 data);
void vexpress_sysreg_early_init(void __iomem *base);
-void vexpress_sysreg_of_early_init(void);
-int vexpress_sysreg_config_device_register(struct platform_device *pdev);
+int vexpress_syscfg_device_register(struct platform_device *pdev);
/* Clocks */
--
1.8.3.2
^ permalink raw reply related
* [PATCH 2/3] mfd: vexpress: Convert custom func API to regmap
From: Pawel Moll @ 2014-02-11 16:53 UTC (permalink / raw)
To: linux-kernel, linux-arm-kernel, devicetree, lm-sensors, arm
Cc: Rob Herring, Mark Rutland, Ian Campbell, Kumar Gala,
Greg Kroah-Hartman, Mike Turquette, Jean Delvare, Guenter Roeck,
Samuel Ortiz, Lee Jones, Arnd Bergmann, Grant Likely,
Dmitry Eremin-Solenikov, David Woodhouse, Liam Girdwood,
Mark Brown, Pawel Moll
In-Reply-To: <1392137610-27842-1-git-send-email-pawel.moll@arm.com>
Components of the Versatile Express platform (configuration
microcontrollers on motherboard and daughterboards in particular)
talk to each other over a custom configuration bus. They
provide miscellaneous functions (from clock generator control
to energy sensors) which are represented as platform devices
(and Device Tree nodes). The transactions on the bus can
be generated by different "bridges" in the system, some
of which are universal for the whole platform (for the price
of high transfer latencies), others restricted to a subsystem
(but much faster).
Until now drivers for such functions were using custom "func"
API, which is being replaced in this patch by regmap calls.
This required:
* a rework (and move to drivers/bus directory, as suggested
by Samuel and Arnd) of the config bus core, which is much
simpler now and uses device model infrastructure (class)
to keep track of the bridges; non-DT case (soon to be
retired anyway) is simply covered by a special device
registration function
* the new config-bus driver also takes over device population,
so there is no need for special matching table for
of_platform_populate nor "simple-bus" hack in the arm64
model dtsi file (relevant bindings documentation has
been updated); this allows all the vexpress devices
fit into normal device model, making it possible
to remove plenty of early inits and other hacks in
the near future
* adaptation of the syscfg bridge implementation in the
sysreg driver, again making it much simpler; there is
a special case of the "energy" function spanning two
registers, where they should be both defined in the tree
now, but backward compatibility is maintained in the code
* modification of the relevant drivers:
* hwmon - just a straight-forward API change
* regulator - API change plus error handling
simplification
* power/reset driver - API change, but as devm_regmap*()
can't be called when the system is dying, it must
be requested at driver probe time
* osc clock driver - this one required larger rework
in order to turn in into a standard platform driver
(and this a good thing on its own)
Signed-off-by: Pawel Moll <pawel.moll@arm.com>
---
.../devicetree/bindings/arm/vexpress-sysreg.txt | 43 ++-
Documentation/devicetree/bindings/arm/vexpress.txt | 15 +-
arch/arm/boot/dts/vexpress-v2p-ca15_a7.dts | 5 +-
arch/arm/mach-vexpress/ct-ca9x4.c | 10 +-
arch/arm/mach-vexpress/v2m.c | 18 +-
arch/arm64/boot/dts/rtsm_ve-motherboard.dtsi | 2 +-
drivers/bus/Kconfig | 9 +
drivers/bus/Makefile | 2 +
drivers/bus/vexpress-config.c | 202 +++++++++++
drivers/clk/versatile/clk-vexpress-osc.c | 94 +++--
drivers/hwmon/vexpress.c | 15 +-
drivers/mfd/Kconfig | 7 -
drivers/mfd/Makefile | 2 +-
drivers/mfd/vexpress-config.c | 288 ---------------
drivers/mfd/vexpress-sysreg.c | 395 +++++++++++----------
drivers/power/reset/vexpress-poweroff.c | 13 +-
drivers/regulator/vexpress.c | 50 +--
include/linux/vexpress.h | 79 +----
18 files changed, 568 insertions(+), 681 deletions(-)
create mode 100644 drivers/bus/vexpress-config.c
delete mode 100644 drivers/mfd/vexpress-config.c
diff --git a/Documentation/devicetree/bindings/arm/vexpress-sysreg.txt b/Documentation/devicetree/bindings/arm/vexpress-sysreg.txt
index 5580e9c..57b423f 100644
--- a/Documentation/devicetree/bindings/arm/vexpress-sysreg.txt
+++ b/Documentation/devicetree/bindings/arm/vexpress-sysreg.txt
@@ -27,24 +27,45 @@ Example:
This block also can also act a bridge to the platform's configuration
bus via "system control" interface, addressing devices with site number,
position in the board stack, config controller, function and device
-numbers - see motherboard's TRM for more details.
-
-The node describing a config device must refer to the sysreg node via
-"arm,vexpress,config-bridge" phandle (can be also defined in the node's
-parent) and relies on the board topology properties - see main vexpress
-node documentation for more details. It must also define the following
-property:
-- arm,vexpress-sysreg,func : must contain two cells:
- - first cell defines function number (eg. 1 for clock generator,
- 2 for voltage regulators etc.)
- - device number (eg. osc 0, osc 1 etc.)
+numbers - see motherboard's TRM for more details. All configuration
+controller accessible via this interface must reference the sysreg
+node via "arm,vexpress,config-bridge" phandle and define appropriate
+topology properties - see main vexpress node documentation for more
+details. Each child of such node describes one function and must
+define the following properties:
+- compatible value : must be one of (corresponding to the TRM):
+ "arm,vexpress-amp"
+ "arm,vexpress-dvimode"
+ "arm,vexpress-energy"
+ "arm,vexpress-muxfpga"
+ "arm,vexpress-osc"
+ "arm,vexpress-power"
+ "arm,vexpress-reboot"
+ "arm,vexpress-reset"
+ "arm,vexpress-scc"
+ "arm,vexpress-shutdown"
+ "arm,vexpress-temp"
+ "arm,vexpress-volt"
+- arm,vexpress-sysreg,func : must contain a set of two cells long groups:
+ - first cell of each group defines the function number
+ (eg. 1 for clock generator, 2 for voltage regulators etc.)
+ - second cell of each group defines device number (eg. osc 0,
+ osc 1 etc.)
+ - some functions (eg. energy meter, with its 64 bit long counter)
+ are using more than one function/device number pair
Example:
mcc {
+ compatible = "arm,vexpress,config-bus";
arm,vexpress,config-bridge = <&v2m_sysreg>;
osc@0 {
compatible = "arm,vexpress-osc";
arm,vexpress-sysreg,func = <1 0>;
};
+
+ energy@0 {
+ compatible = "arm,vexpress-energy";
+ arm,vexpress-sysreg,func = <13 0>, <13 1>;
+ };
};
diff --git a/Documentation/devicetree/bindings/arm/vexpress.txt b/Documentation/devicetree/bindings/arm/vexpress.txt
index ae49161..39844cd 100644
--- a/Documentation/devicetree/bindings/arm/vexpress.txt
+++ b/Documentation/devicetree/bindings/arm/vexpress.txt
@@ -80,12 +80,17 @@ but also control clock generators, voltage regulators, gather
environmental data like temperature, power consumption etc. Even
the video output switch (FPGA) is controlled that way.
-Nodes describing devices controlled by this infrastructure should
-point at the bridge device node:
+The controllers are not mapped into normal memory address space
+and must be accessed through bridges - other devices capable
+of generating transactions on the configuration bus.
+
+The nodes describing configuration controllers must define
+the following properties:
+- compatible value:
+ compatible = "arm,vexpress,config-bus";
- bridge phandle:
arm,vexpress,config-bridge = <phandle>;
-This property can be also defined in a parent node (eg. for a DCC)
-and is effective for all children.
+and children describing available functions.
Platform topology
@@ -197,7 +202,7 @@ Example of a VE tile description (simplified)
};
dcc {
- compatible = "simple-bus";
+ compatible = "arm,vexpress,config-bus";
arm,vexpress,config-bridge = <&v2m_sysreg>;
osc@0 {
diff --git a/arch/arm/boot/dts/vexpress-v2p-ca15_a7.dts b/arch/arm/boot/dts/vexpress-v2p-ca15_a7.dts
index 15f98cb..a25c262 100644
--- a/arch/arm/boot/dts/vexpress-v2p-ca15_a7.dts
+++ b/arch/arm/boot/dts/vexpress-v2p-ca15_a7.dts
@@ -312,6 +312,7 @@
arm,vexpress-sysreg,func = <12 0>;
label = "A15 Pcore";
};
+
power@1 {
/* Total power for the three A7 cores */
compatible = "arm,vexpress-power";
@@ -322,14 +323,14 @@
energy@0 {
/* Total energy for the two A15 cores */
compatible = "arm,vexpress-energy";
- arm,vexpress-sysreg,func = <13 0>;
+ arm,vexpress-sysreg,func = <13 0>, <13 1>;
label = "A15 Jcore";
};
energy@2 {
/* Total energy for the three A7 cores */
compatible = "arm,vexpress-energy";
- arm,vexpress-sysreg,func = <13 2>;
+ arm,vexpress-sysreg,func = <13 2>, <13 3>;
label = "A7 Jcore";
};
};
diff --git a/arch/arm/mach-vexpress/ct-ca9x4.c b/arch/arm/mach-vexpress/ct-ca9x4.c
index 6f34497..35e394a 100644
--- a/arch/arm/mach-vexpress/ct-ca9x4.c
+++ b/arch/arm/mach-vexpress/ct-ca9x4.c
@@ -128,6 +128,10 @@ static struct platform_device pmu_device = {
.resource = pmu_resources,
};
+static struct clk_lookup osc1_lookup = {
+ .dev_id = "ct:clcd",
+};
+
static struct platform_device osc1_device = {
.name = "vexpress-osc",
.id = 1,
@@ -135,6 +139,7 @@ static struct platform_device osc1_device = {
.resource = (struct resource []) {
VEXPRESS_RES_FUNC(0xf, 1),
},
+ .dev.platform_data = &osc1_lookup,
};
static void __init ct_ca9x4_init(void)
@@ -155,10 +160,7 @@ static void __init ct_ca9x4_init(void)
amba_device_register(ct_ca9x4_amba_devs[i], &iomem_resource);
platform_device_register(&pmu_device);
- platform_device_register(&osc1_device);
-
- WARN_ON(clk_register_clkdev(vexpress_osc_setup(&osc1_device.dev),
- NULL, "ct:clcd"));
+ vexpress_sysreg_config_device_register(&osc1_device);
}
#ifdef CONFIG_SMP
diff --git a/arch/arm/mach-vexpress/v2m.c b/arch/arm/mach-vexpress/v2m.c
index 4f8b8cb..ac95220 100644
--- a/arch/arm/mach-vexpress/v2m.c
+++ b/arch/arm/mach-vexpress/v2m.c
@@ -340,11 +340,6 @@ static void __init v2m_init(void)
regulator_register_fixed(0, v2m_eth_supplies,
ARRAY_SIZE(v2m_eth_supplies));
- platform_device_register(&v2m_muxfpga_device);
- platform_device_register(&v2m_shutdown_device);
- platform_device_register(&v2m_reboot_device);
- platform_device_register(&v2m_dvimode_device);
-
platform_device_register(&v2m_sysreg_device);
platform_device_register(&v2m_pcie_i2c_device);
platform_device_register(&v2m_ddc_i2c_device);
@@ -356,6 +351,11 @@ static void __init v2m_init(void)
for (i = 0; i < ARRAY_SIZE(v2m_amba_devs); i++)
amba_device_register(v2m_amba_devs[i], &iomem_resource);
+ vexpress_sysreg_config_device_register(&v2m_muxfpga_device);
+ vexpress_sysreg_config_device_register(&v2m_shutdown_device);
+ vexpress_sysreg_config_device_register(&v2m_reboot_device);
+ vexpress_sysreg_config_device_register(&v2m_dvimode_device);
+
ct_desc->init_tile();
}
@@ -423,17 +423,11 @@ void __init v2m_dt_init_early(void)
versatile_sched_clock_init(vexpress_get_24mhz_clock_base(), 24000000);
}
-static const struct of_device_id v2m_dt_bus_match[] __initconst = {
- { .compatible = "simple-bus", },
- { .compatible = "arm,amba-bus", },
- { .compatible = "arm,vexpress,config-bus", },
- {}
-};
static void __init v2m_dt_init(void)
{
l2x0_of_init(0x00400000, 0xfe0fffff);
- of_platform_populate(NULL, v2m_dt_bus_match, NULL, NULL);
+ of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL);
}
static const char * const v2m_dt_match[] __initconst = {
diff --git a/arch/arm64/boot/dts/rtsm_ve-motherboard.dtsi b/arch/arm64/boot/dts/rtsm_ve-motherboard.dtsi
index 2f2ecd2..ac2cb24 100644
--- a/arch/arm64/boot/dts/rtsm_ve-motherboard.dtsi
+++ b/arch/arm64/boot/dts/rtsm_ve-motherboard.dtsi
@@ -200,7 +200,7 @@
};
mcc {
- compatible = "arm,vexpress,config-bus", "simple-bus";
+ compatible = "arm,vexpress,config-bus";
arm,vexpress,config-bridge = <&v2m_sysreg>;
v2m_oscclk1: osc@1 {
diff --git a/drivers/bus/Kconfig b/drivers/bus/Kconfig
index 552373c..f24e79d 100644
--- a/drivers/bus/Kconfig
+++ b/drivers/bus/Kconfig
@@ -41,4 +41,13 @@ config ARM_CCI
help
Driver supporting the CCI cache coherent interconnect for ARM
platforms.
+
+config VEXPRESS_CONFIG
+ bool "Versatile Express configuration bus"
+ default y if ARCH_VEXPRESS
+ depends on ARM || ARM64
+ select REGMAP
+ help
+ Platform configuration infrastructure for the ARM Ltd.
+ Versatile Express.
endmenu
diff --git a/drivers/bus/Makefile b/drivers/bus/Makefile
index 8947bdd..f095aa7 100644
--- a/drivers/bus/Makefile
+++ b/drivers/bus/Makefile
@@ -10,3 +10,5 @@ obj-$(CONFIG_OMAP_OCP2SCP) += omap-ocp2scp.o
obj-$(CONFIG_OMAP_INTERCONNECT) += omap_l3_smx.o omap_l3_noc.o
# CCI cache coherent interconnect for ARM platforms
obj-$(CONFIG_ARM_CCI) += arm-cci.o
+
+obj-$(CONFIG_VEXPRESS_CONFIG) += vexpress-config.o
diff --git a/drivers/bus/vexpress-config.c b/drivers/bus/vexpress-config.c
new file mode 100644
index 0000000..27a07df
--- /dev/null
+++ b/drivers/bus/vexpress-config.c
@@ -0,0 +1,202 @@
+/*
+ * 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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * Copyright (C) 2014 ARM Limited
+ */
+
+#include <linux/err.h>
+#include <linux/init.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/vexpress.h>
+
+
+struct vexpress_config_bridge {
+ struct vexpress_config_bridge_ops *ops;
+ void *context;
+};
+
+
+static DEFINE_MUTEX(vexpress_config_mutex);
+static struct class *vexpress_config_class;
+static u32 vexpress_config_site_master = VEXPRESS_SITE_MASTER;
+
+
+void vexpress_config_set_master(u32 site)
+{
+ vexpress_config_site_master = site;
+}
+
+u32 vexpress_config_get_master(void)
+{
+ return vexpress_config_site_master;
+}
+
+void vexpress_config_lock(void *arg)
+{
+ mutex_lock(&vexpress_config_mutex);
+}
+
+void vexpress_config_unlock(void *arg)
+{
+ mutex_unlock(&vexpress_config_mutex);
+}
+
+
+static void vexpress_config_find_prop(struct device_node *node,
+ const char *name, u32 *val)
+{
+ /* Default value */
+ *val = 0;
+
+ of_node_get(node);
+ while (node) {
+ if (of_property_read_u32(node, name, val) == 0) {
+ of_node_put(node);
+ return;
+ }
+ node = of_get_next_parent(node);
+ }
+}
+
+int vexpress_config_get_topo(struct device_node *node, u32 *site,
+ u32 *position, u32 *dcc)
+{
+ vexpress_config_find_prop(node, "arm,vexpress,site", site);
+ if (*site == VEXPRESS_SITE_MASTER)
+ *site = vexpress_config_site_master;
+ if (WARN_ON(vexpress_config_site_master == VEXPRESS_SITE_MASTER))
+ return -EINVAL;
+ vexpress_config_find_prop(node, "arm,vexpress,position", position);
+ vexpress_config_find_prop(node, "arm,vexpress,dcc", dcc);
+
+ return 0;
+}
+
+
+static void vexpress_config_devres_release(struct device *dev, void *res)
+{
+ struct vexpress_config_bridge *bridge = dev_get_drvdata(dev->parent);
+ struct regmap *regmap = res;
+
+ bridge->ops->regmap_exit(regmap, bridge->context);
+}
+
+struct regmap *devm_regmap_init_vexpress_config(struct device *dev)
+{
+ struct vexpress_config_bridge *bridge;
+ struct regmap *regmap;
+ struct regmap **res;
+
+ if (WARN_ON(dev->parent->class != vexpress_config_class))
+ return ERR_PTR(-ENODEV);
+
+ bridge = dev_get_drvdata(dev->parent);
+ if (WARN_ON(!bridge))
+ return ERR_PTR(-EINVAL);
+
+ res = devres_alloc(vexpress_config_devres_release, sizeof(*res),
+ GFP_KERNEL);
+ if (!res)
+ return ERR_PTR(-ENOMEM);
+
+ regmap = bridge->ops->regmap_init(dev, bridge->context);
+ if (IS_ERR(regmap)) {
+ devres_free(res);
+ return regmap;
+ }
+
+ *res = regmap;
+ devres_add(dev, res);
+
+ return regmap;
+}
+
+
+struct device *vexpress_config_bridge_register(struct device *parent,
+ struct vexpress_config_bridge_ops *ops, void *context)
+{
+ struct device *dev;
+ struct vexpress_config_bridge *bridge;
+
+ if (!vexpress_config_class) {
+ vexpress_config_class = class_create(THIS_MODULE,
+ "vexpress-config");
+ if (IS_ERR(vexpress_config_class))
+ return (void *)vexpress_config_class;
+ }
+
+ dev = device_create(vexpress_config_class, parent, 0,
+ NULL, "%s.bridge", dev_name(parent));
+
+ if (IS_ERR(dev))
+ return dev;
+
+ bridge = devm_kmalloc(dev, sizeof(*bridge), GFP_KERNEL);
+ if (!bridge) {
+ put_device(dev);
+ device_unregister(dev);
+ return ERR_PTR(-ENOMEM);
+ }
+ bridge->ops = ops;
+ bridge->context = context;
+
+ dev_set_drvdata(dev, bridge);
+
+ dev_dbg(parent, "Registered bridge '%s', parent node %p\n",
+ dev_name(dev), parent->of_node);
+
+ return dev;
+}
+
+
+static int vexpress_config_node_match(struct device *dev, const void *data)
+{
+ const struct device_node *node = data;
+
+ dev_dbg(dev, "Parent node %p, looking for %p\n",
+ dev->parent->of_node, node);
+
+ return dev->parent->of_node == node;
+}
+
+static int vexpress_config_populate(struct device_node *node)
+{
+ struct device_node *bridge;
+ struct device *parent;
+
+ bridge = of_parse_phandle(node, "arm,vexpress,config-bridge", 0);
+ if (!bridge)
+ return -EINVAL;
+
+ parent = class_find_device(vexpress_config_class, NULL, bridge,
+ vexpress_config_node_match);
+ if (WARN_ON(!parent))
+ return -ENODEV;
+
+ return of_platform_populate(node, NULL, NULL, parent);
+}
+
+static int __init vexpress_config_init(void)
+{
+ int err = 0;
+ struct device_node *node;
+
+ /* Need the config devices early, before the "normal" devices... */
+ for_each_compatible_node(node, NULL, "arm,vexpress,config-bus") {
+ err = vexpress_config_populate(node);
+ if (err)
+ break;
+ }
+
+ return err;
+}
+postcore_initcall(vexpress_config_init);
+
diff --git a/drivers/clk/versatile/clk-vexpress-osc.c b/drivers/clk/versatile/clk-vexpress-osc.c
index 2dc8b41..529a59c 100644
--- a/drivers/clk/versatile/clk-vexpress-osc.c
+++ b/drivers/clk/versatile/clk-vexpress-osc.c
@@ -11,8 +11,6 @@
* Copyright (C) 2012 ARM Limited
*/
-#define pr_fmt(fmt) "vexpress-osc: " fmt
-
#include <linux/clkdev.h>
#include <linux/clk-provider.h>
#include <linux/err.h>
@@ -22,7 +20,7 @@
#include <linux/vexpress.h>
struct vexpress_osc {
- struct vexpress_config_func *func;
+ struct regmap *reg;
struct clk_hw hw;
unsigned long rate_min;
unsigned long rate_max;
@@ -36,7 +34,7 @@ static unsigned long vexpress_osc_recalc_rate(struct clk_hw *hw,
struct vexpress_osc *osc = to_vexpress_osc(hw);
u32 rate;
- vexpress_config_read(osc->func, 0, &rate);
+ regmap_read(osc->reg, 0, &rate);
return rate;
}
@@ -60,7 +58,7 @@ static int vexpress_osc_set_rate(struct clk_hw *hw, unsigned long rate,
{
struct vexpress_osc *osc = to_vexpress_osc(hw);
- return vexpress_config_write(osc->func, 0, rate);
+ return regmap_write(osc->reg, 0, rate);
}
static struct clk_ops vexpress_osc_ops = {
@@ -70,56 +68,31 @@ static struct clk_ops vexpress_osc_ops = {
};
-struct clk * __init vexpress_osc_setup(struct device *dev)
-{
- struct clk_init_data init;
- struct vexpress_osc *osc = kzalloc(sizeof(*osc), GFP_KERNEL);
-
- if (!osc)
- return NULL;
-
- osc->func = vexpress_config_func_get_by_dev(dev);
- if (!osc->func) {
- kfree(osc);
- return NULL;
- }
-
- init.name = dev_name(dev);
- init.ops = &vexpress_osc_ops;
- init.flags = CLK_IS_ROOT;
- init.num_parents = 0;
- osc->hw.init = &init;
-
- return clk_register(NULL, &osc->hw);
-}
-
-void __init vexpress_osc_of_setup(struct device_node *node)
+static int vexpress_osc_probe(struct platform_device *pdev)
{
+ struct clk_lookup *cl = pdev->dev.platform_data; /* Non-DT lookup */
struct clk_init_data init;
struct vexpress_osc *osc;
struct clk *clk;
u32 range[2];
- osc = kzalloc(sizeof(*osc), GFP_KERNEL);
+ osc = devm_kzalloc(&pdev->dev, sizeof(*osc), GFP_KERNEL);
if (!osc)
- goto error;
+ return -ENOMEM;
- osc->func = vexpress_config_func_get_by_node(node);
- if (!osc->func) {
- pr_err("Failed to obtain config func for node '%s'!\n",
- node->full_name);
- goto error;
- }
+ osc->reg = devm_regmap_init_vexpress_config(&pdev->dev);
+ if (IS_ERR(osc->reg))
+ return PTR_ERR(osc->reg);
- if (of_property_read_u32_array(node, "freq-range", range,
+ if (of_property_read_u32_array(pdev->dev.of_node, "freq-range", range,
ARRAY_SIZE(range)) == 0) {
osc->rate_min = range[0];
osc->rate_max = range[1];
}
- of_property_read_string(node, "clock-output-names", &init.name);
- if (!init.name)
- init.name = node->full_name;
+ if (of_property_read_string(pdev->dev.of_node, "clock-output-names",
+ &init.name) != 0)
+ init.name = dev_name(&pdev->dev);
init.ops = &vexpress_osc_ops;
init.flags = CLK_IS_ROOT;
@@ -128,20 +101,37 @@ void __init vexpress_osc_of_setup(struct device_node *node)
osc->hw.init = &init;
clk = clk_register(NULL, &osc->hw);
- if (IS_ERR(clk)) {
- pr_err("Failed to register clock '%s'!\n", init.name);
- goto error;
+ if (IS_ERR(clk))
+ return PTR_ERR(clk);
+
+ of_clk_add_provider(pdev->dev.of_node, of_clk_src_simple_get, clk);
+
+ /* Only happens for non-DT cases */
+ if (cl) {
+ cl->clk = clk;
+ clkdev_add(cl);
}
- of_clk_add_provider(node, of_clk_src_simple_get, clk);
+ dev_dbg(&pdev->dev, "Registered clock '%s'\n", init.name);
- pr_debug("Registered clock '%s'\n", init.name);
+ return 0;
+}
- return;
+static struct of_device_id vexpress_osc_of_match[] = {
+ { .compatible = "arm,vexpress-osc", },
+ {}
+};
-error:
- if (osc->func)
- vexpress_config_func_put(osc->func);
- kfree(osc);
+static struct platform_driver vexpress_osc_driver = {
+ .driver = {
+ .name = "vexpress-osc",
+ .of_match_table = vexpress_osc_of_match,
+ },
+ .probe = vexpress_osc_probe,
+};
+
+static int __init vexpress_osc_init(void)
+{
+ return platform_driver_register(&vexpress_osc_driver);
}
-CLK_OF_DECLARE(vexpress_soc, "arm,vexpress-osc", vexpress_osc_of_setup);
+core_initcall(vexpress_osc_init);
diff --git a/drivers/hwmon/vexpress.c b/drivers/hwmon/vexpress.c
index d867e6b..d8a6113 100644
--- a/drivers/hwmon/vexpress.c
+++ b/drivers/hwmon/vexpress.c
@@ -26,7 +26,7 @@
struct vexpress_hwmon_data {
struct device *hwmon_dev;
- struct vexpress_config_func *func;
+ struct regmap *reg;
};
static ssize_t vexpress_hwmon_name_show(struct device *dev,
@@ -56,7 +56,7 @@ static ssize_t vexpress_hwmon_u32_show(struct device *dev,
int err;
u32 value;
- err = vexpress_config_read(data->func, 0, &value);
+ err = regmap_read(data->reg, 0, &value);
if (err)
return err;
@@ -71,11 +71,11 @@ static ssize_t vexpress_hwmon_u64_show(struct device *dev,
int err;
u32 value_hi, value_lo;
- err = vexpress_config_read(data->func, 0, &value_lo);
+ err = regmap_read(data->reg, 0, &value_lo);
if (err)
return err;
- err = vexpress_config_read(data->func, 1, &value_hi);
+ err = regmap_read(data->reg, 1, &value_hi);
if (err)
return err;
@@ -175,8 +175,8 @@ static int vexpress_hwmon_probe(struct platform_device *pdev)
if (!match)
return -ENODEV;
- data->func = vexpress_config_func_get_by_dev(&pdev->dev);
- if (!data->func)
+ data->reg = devm_regmap_init_vexpress_config(&pdev->dev);
+ if (!data->reg)
return -ENODEV;
err = sysfs_create_group(&pdev->dev.kobj, match->data);
@@ -193,7 +193,6 @@ static int vexpress_hwmon_probe(struct platform_device *pdev)
error:
sysfs_remove_group(&pdev->dev.kobj, match->data);
- vexpress_config_func_put(data->func);
return err;
}
@@ -207,8 +206,6 @@ static int vexpress_hwmon_remove(struct platform_device *pdev)
match = of_match_device(vexpress_hwmon_of_match, &pdev->dev);
sysfs_remove_group(&pdev->dev.kobj, match->data);
- vexpress_config_func_put(data->func);
-
return 0;
}
diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig
index 49bb445..08657fa 100644
--- a/drivers/mfd/Kconfig
+++ b/drivers/mfd/Kconfig
@@ -1219,10 +1219,3 @@ config MCP_UCB1200_TS
depends on MCP_UCB1200 && INPUT
endmenu
-
-config VEXPRESS_CONFIG
- bool "ARM Versatile Express platform infrastructure"
- depends on ARM || ARM64
- help
- Platform configuration infrastructure for the ARM Ltd.
- Versatile Express.
diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile
index 5aea5ef..816b258 100644
--- a/drivers/mfd/Makefile
+++ b/drivers/mfd/Makefile
@@ -161,7 +161,7 @@ obj-$(CONFIG_MFD_RC5T583) += rc5t583.o rc5t583-irq.o
obj-$(CONFIG_MFD_SEC_CORE) += sec-core.o sec-irq.o
obj-$(CONFIG_MFD_SYSCON) += syscon.o
obj-$(CONFIG_MFD_LM3533) += lm3533-core.o lm3533-ctrlbank.o
-obj-$(CONFIG_VEXPRESS_CONFIG) += vexpress-config.o vexpress-sysreg.o
+obj-$(CONFIG_VEXPRESS_CONFIG) += vexpress-sysreg.o
obj-$(CONFIG_MFD_RETU) += retu-mfd.o
obj-$(CONFIG_MFD_AS3711) += as3711.o
obj-$(CONFIG_MFD_AS3722) += as3722.o
diff --git a/drivers/mfd/vexpress-config.c b/drivers/mfd/vexpress-config.c
deleted file mode 100644
index 84ce6b9..0000000
--- a/drivers/mfd/vexpress-config.c
+++ /dev/null
@@ -1,288 +0,0 @@
-/*
- * 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.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * Copyright (C) 2012 ARM Limited
- */
-
-#define pr_fmt(fmt) "vexpress-config: " fmt
-
-#include <linux/bitops.h>
-#include <linux/completion.h>
-#include <linux/export.h>
-#include <linux/init.h>
-#include <linux/list.h>
-#include <linux/of.h>
-#include <linux/of_device.h>
-#include <linux/slab.h>
-#include <linux/string.h>
-#include <linux/vexpress.h>
-
-
-#define VEXPRESS_CONFIG_MAX_BRIDGES 2
-
-struct vexpress_config_bridge {
- struct device_node *node;
- struct vexpress_config_bridge_info *info;
- struct list_head transactions;
- spinlock_t transactions_lock;
-} vexpress_config_bridges[VEXPRESS_CONFIG_MAX_BRIDGES];
-
-static DECLARE_BITMAP(vexpress_config_bridges_map,
- ARRAY_SIZE(vexpress_config_bridges));
-static DEFINE_MUTEX(vexpress_config_bridges_mutex);
-
-struct vexpress_config_bridge *vexpress_config_bridge_register(
- struct device_node *node,
- struct vexpress_config_bridge_info *info)
-{
- struct vexpress_config_bridge *bridge;
- int i;
-
- pr_debug("Registering bridge '%s'\n", info->name);
-
- mutex_lock(&vexpress_config_bridges_mutex);
- i = find_first_zero_bit(vexpress_config_bridges_map,
- ARRAY_SIZE(vexpress_config_bridges));
- if (i >= ARRAY_SIZE(vexpress_config_bridges)) {
- pr_err("Can't register more bridges!\n");
- mutex_unlock(&vexpress_config_bridges_mutex);
- return NULL;
- }
- __set_bit(i, vexpress_config_bridges_map);
- bridge = &vexpress_config_bridges[i];
-
- bridge->node = node;
- bridge->info = info;
- INIT_LIST_HEAD(&bridge->transactions);
- spin_lock_init(&bridge->transactions_lock);
-
- mutex_unlock(&vexpress_config_bridges_mutex);
-
- return bridge;
-}
-EXPORT_SYMBOL(vexpress_config_bridge_register);
-
-void vexpress_config_bridge_unregister(struct vexpress_config_bridge *bridge)
-{
- struct vexpress_config_bridge __bridge = *bridge;
- int i;
-
- mutex_lock(&vexpress_config_bridges_mutex);
- for (i = 0; i < ARRAY_SIZE(vexpress_config_bridges); i++)
- if (&vexpress_config_bridges[i] == bridge)
- __clear_bit(i, vexpress_config_bridges_map);
- mutex_unlock(&vexpress_config_bridges_mutex);
-
- WARN_ON(!list_empty(&__bridge.transactions));
- while (!list_empty(&__bridge.transactions))
- cpu_relax();
-}
-EXPORT_SYMBOL(vexpress_config_bridge_unregister);
-
-
-struct vexpress_config_func {
- struct vexpress_config_bridge *bridge;
- void *func;
-};
-
-struct vexpress_config_func *__vexpress_config_func_get(struct device *dev,
- struct device_node *node)
-{
- struct device_node *bridge_node;
- struct vexpress_config_func *func;
- int i;
-
- if (WARN_ON(dev && node && dev->of_node != node))
- return NULL;
- if (dev && !node)
- node = dev->of_node;
-
- func = kzalloc(sizeof(*func), GFP_KERNEL);
- if (!func)
- return NULL;
-
- bridge_node = of_node_get(node);
- while (bridge_node) {
- const __be32 *prop = of_get_property(bridge_node,
- "arm,vexpress,config-bridge", NULL);
-
- if (prop) {
- bridge_node = of_find_node_by_phandle(
- be32_to_cpup(prop));
- break;
- }
-
- bridge_node = of_get_next_parent(bridge_node);
- }
-
- mutex_lock(&vexpress_config_bridges_mutex);
- for (i = 0; i < ARRAY_SIZE(vexpress_config_bridges); i++) {
- struct vexpress_config_bridge *bridge =
- &vexpress_config_bridges[i];
-
- if (test_bit(i, vexpress_config_bridges_map) &&
- bridge->node == bridge_node) {
- func->bridge = bridge;
- func->func = bridge->info->func_get(dev, node);
- break;
- }
- }
- mutex_unlock(&vexpress_config_bridges_mutex);
-
- if (!func->func) {
- of_node_put(node);
- kfree(func);
- return NULL;
- }
-
- return func;
-}
-EXPORT_SYMBOL(__vexpress_config_func_get);
-
-void vexpress_config_func_put(struct vexpress_config_func *func)
-{
- func->bridge->info->func_put(func->func);
- of_node_put(func->bridge->node);
- kfree(func);
-}
-EXPORT_SYMBOL(vexpress_config_func_put);
-
-struct vexpress_config_trans {
- struct vexpress_config_func *func;
- int offset;
- bool write;
- u32 *data;
- int status;
- struct completion completion;
- struct list_head list;
-};
-
-static void vexpress_config_dump_trans(const char *what,
- struct vexpress_config_trans *trans)
-{
- pr_debug("%s %s trans %p func 0x%p offset %d data 0x%x status %d\n",
- what, trans->write ? "write" : "read", trans,
- trans->func->func, trans->offset,
- trans->data ? *trans->data : 0, trans->status);
-}
-
-static int vexpress_config_schedule(struct vexpress_config_trans *trans)
-{
- int status;
- struct vexpress_config_bridge *bridge = trans->func->bridge;
- unsigned long flags;
-
- init_completion(&trans->completion);
- trans->status = -EFAULT;
-
- spin_lock_irqsave(&bridge->transactions_lock, flags);
-
- if (list_empty(&bridge->transactions)) {
- vexpress_config_dump_trans("Executing", trans);
- status = bridge->info->func_exec(trans->func->func,
- trans->offset, trans->write, trans->data);
- } else {
- vexpress_config_dump_trans("Queuing", trans);
- status = VEXPRESS_CONFIG_STATUS_WAIT;
- }
-
- switch (status) {
- case VEXPRESS_CONFIG_STATUS_DONE:
- vexpress_config_dump_trans("Finished", trans);
- trans->status = status;
- break;
- case VEXPRESS_CONFIG_STATUS_WAIT:
- list_add_tail(&trans->list, &bridge->transactions);
- break;
- }
-
- spin_unlock_irqrestore(&bridge->transactions_lock, flags);
-
- return status;
-}
-
-void vexpress_config_complete(struct vexpress_config_bridge *bridge,
- int status)
-{
- struct vexpress_config_trans *trans;
- unsigned long flags;
- const char *message = "Completed";
-
- spin_lock_irqsave(&bridge->transactions_lock, flags);
-
- trans = list_first_entry(&bridge->transactions,
- struct vexpress_config_trans, list);
- trans->status = status;
-
- do {
- vexpress_config_dump_trans(message, trans);
- list_del(&trans->list);
- complete(&trans->completion);
-
- if (list_empty(&bridge->transactions))
- break;
-
- trans = list_first_entry(&bridge->transactions,
- struct vexpress_config_trans, list);
- vexpress_config_dump_trans("Executing pending", trans);
- trans->status = bridge->info->func_exec(trans->func->func,
- trans->offset, trans->write, trans->data);
- message = "Finished pending";
- } while (trans->status == VEXPRESS_CONFIG_STATUS_DONE);
-
- spin_unlock_irqrestore(&bridge->transactions_lock, flags);
-}
-EXPORT_SYMBOL(vexpress_config_complete);
-
-int vexpress_config_wait(struct vexpress_config_trans *trans)
-{
- wait_for_completion(&trans->completion);
-
- return trans->status;
-}
-EXPORT_SYMBOL(vexpress_config_wait);
-
-int vexpress_config_read(struct vexpress_config_func *func, int offset,
- u32 *data)
-{
- struct vexpress_config_trans trans = {
- .func = func,
- .offset = offset,
- .write = false,
- .data = data,
- .status = 0,
- };
- int status = vexpress_config_schedule(&trans);
-
- if (status == VEXPRESS_CONFIG_STATUS_WAIT)
- status = vexpress_config_wait(&trans);
-
- return status;
-}
-EXPORT_SYMBOL(vexpress_config_read);
-
-int vexpress_config_write(struct vexpress_config_func *func, int offset,
- u32 data)
-{
- struct vexpress_config_trans trans = {
- .func = func,
- .offset = offset,
- .write = true,
- .data = &data,
- .status = 0,
- };
- int status = vexpress_config_schedule(&trans);
-
- if (status == VEXPRESS_CONFIG_STATUS_WAIT)
- status = vexpress_config_wait(&trans);
-
- return status;
-}
-EXPORT_SYMBOL(vexpress_config_write);
diff --git a/drivers/mfd/vexpress-sysreg.c b/drivers/mfd/vexpress-sysreg.c
index 981bef4..b4138a7 100644
--- a/drivers/mfd/vexpress-sysreg.c
+++ b/drivers/mfd/vexpress-sysreg.c
@@ -16,8 +16,10 @@
#include <linux/io.h>
#include <linux/leds.h>
#include <linux/of_address.h>
+#include <linux/of_platform.h>
#include <linux/platform_device.h>
#include <linux/regulator/driver.h>
+#include <linux/sched.h>
#include <linux/slab.h>
#include <linux/stat.h>
#include <linux/timer.h>
@@ -72,9 +74,18 @@
static void __iomem *vexpress_sysreg_base;
static struct device *vexpress_sysreg_dev;
-static int vexpress_master_site;
+static LIST_HEAD(vexpress_sysreg_config_funcs);
+static struct device *vexpress_sysreg_config_bridge;
+static int vexpress_sysreg_get_master(void)
+{
+ if (readl(vexpress_sysreg_base + SYS_MISC) & SYS_MISC_MASTERSITE)
+ return VEXPRESS_SITE_DB2;
+
+ return VEXPRESS_SITE_DB1;
+}
+
void vexpress_flags_set(u32 data)
{
writel(~0, vexpress_sysreg_base + SYS_FLAGSCLR);
@@ -84,7 +95,7 @@ void vexpress_flags_set(u32 data)
u32 vexpress_get_procid(int site)
{
if (site == VEXPRESS_SITE_MASTER)
- site = vexpress_master_site;
+ site = vexpress_sysreg_get_master();
return readl(vexpress_sysreg_base + (site == VEXPRESS_SITE_DB1 ?
SYS_PROCID0 : SYS_PROCID1));
@@ -114,130 +125,33 @@ void __iomem *vexpress_get_24mhz_clock_base(void)
}
-static void vexpress_sysreg_find_prop(struct device_node *node,
- const char *name, u32 *val)
-{
- of_node_get(node);
- while (node) {
- if (of_property_read_u32(node, name, val) == 0) {
- of_node_put(node);
- return;
- }
- node = of_get_next_parent(node);
- }
-}
-
-unsigned __vexpress_get_site(struct device *dev, struct device_node *node)
-{
- u32 site = 0;
-
- WARN_ON(dev && node && dev->of_node != node);
- if (dev && !node)
- node = dev->of_node;
-
- if (node) {
- vexpress_sysreg_find_prop(node, "arm,vexpress,site", &site);
- } else if (dev && dev->bus == &platform_bus_type) {
- struct platform_device *pdev = to_platform_device(dev);
-
- if (pdev->num_resources == 1 &&
- pdev->resource[0].flags == IORESOURCE_BUS)
- site = pdev->resource[0].start;
- } else if (dev && strncmp(dev_name(dev), "ct:", 3) == 0) {
- site = VEXPRESS_SITE_MASTER;
- }
-
- if (site == VEXPRESS_SITE_MASTER)
- site = vexpress_master_site;
-
- return site;
-}
-
-
struct vexpress_sysreg_config_func {
- u32 template;
- u32 device;
+ struct list_head list;
+ struct regmap *regmap;
+ int num_templates;
+ u32 template[0]; /* Keep this last */
};
-static struct vexpress_config_bridge *vexpress_sysreg_config_bridge;
-static struct timer_list vexpress_sysreg_config_timer;
-static u32 *vexpress_sysreg_config_data;
-static int vexpress_sysreg_config_tries;
-
-static void *vexpress_sysreg_config_func_get(struct device *dev,
- struct device_node *node)
+static int vexpress_sysreg_config_exec(struct vexpress_sysreg_config_func *func,
+ int index, bool write, u32 *data)
{
- struct vexpress_sysreg_config_func *config_func;
- u32 site;
- u32 position = 0;
- u32 dcc = 0;
- u32 func_device[2];
- int err = -EFAULT;
-
- if (node) {
- of_node_get(node);
- vexpress_sysreg_find_prop(node, "arm,vexpress,site", &site);
- vexpress_sysreg_find_prop(node, "arm,vexpress,position",
- &position);
- vexpress_sysreg_find_prop(node, "arm,vexpress,dcc", &dcc);
- err = of_property_read_u32_array(node,
- "arm,vexpress-sysreg,func", func_device,
- ARRAY_SIZE(func_device));
- of_node_put(node);
- } else if (dev && dev->bus == &platform_bus_type) {
- struct platform_device *pdev = to_platform_device(dev);
-
- if (pdev->num_resources == 1 &&
- pdev->resource[0].flags == IORESOURCE_BUS) {
- site = pdev->resource[0].start;
- func_device[0] = pdev->resource[0].end;
- func_device[1] = pdev->id;
- err = 0;
- }
- }
- if (err)
- return NULL;
-
- config_func = kzalloc(sizeof(*config_func), GFP_KERNEL);
- if (!config_func)
- return NULL;
-
- config_func->template = SYS_CFGCTRL_DCC(dcc);
- config_func->template |= SYS_CFGCTRL_FUNC(func_device[0]);
- config_func->template |= SYS_CFGCTRL_SITE(site == VEXPRESS_SITE_MASTER ?
- vexpress_master_site : site);
- config_func->template |= SYS_CFGCTRL_POSITION(position);
- config_func->device |= func_device[1];
-
- dev_dbg(vexpress_sysreg_dev, "func 0x%p = 0x%x, %d\n", config_func,
- config_func->template, config_func->device);
-
- return config_func;
-}
-
-static void vexpress_sysreg_config_func_put(void *func)
-{
- kfree(func);
-}
-
-static int vexpress_sysreg_config_func_exec(void *func, int offset,
- bool write, u32 *data)
-{
- int status;
- struct vexpress_sysreg_config_func *config_func = func;
- u32 command;
+ u32 command, status;
+ int tries;
+ long timeout;
if (WARN_ON(!vexpress_sysreg_base))
return -ENOENT;
+ if (WARN_ON(index > func->num_templates))
+ return -EINVAL;
+
command = readl(vexpress_sysreg_base + SYS_CFGCTRL);
if (WARN_ON(command & SYS_CFGCTRL_START))
return -EBUSY;
- command = SYS_CFGCTRL_START;
+ command = func->template[index];
+ command |= SYS_CFGCTRL_START;
command |= write ? SYS_CFGCTRL_WRITE : 0;
- command |= config_func->template;
- command |= SYS_CFGCTRL_DEVICE(config_func->device + offset);
/* Use a canary for reads */
if (!write)
@@ -250,90 +164,190 @@ static int vexpress_sysreg_config_func_exec(void *func, int offset,
writel(command, vexpress_sysreg_base + SYS_CFGCTRL);
mb();
- if (vexpress_sysreg_dev) {
- /* Schedule completion check */
- if (!write)
- vexpress_sysreg_config_data = data;
- vexpress_sysreg_config_tries = 100;
- mod_timer(&vexpress_sysreg_config_timer,
- jiffies + usecs_to_jiffies(100));
- status = VEXPRESS_CONFIG_STATUS_WAIT;
- } else {
- /* Early execution, no timer available, have to spin */
- u32 cfgstat;
+ /* The operation can take ages... Go to sleep, 100us initially */
+ tries = 100;
+ timeout = 100;
+ do {
+ set_current_state(TASK_INTERRUPTIBLE);
+ schedule_timeout(usecs_to_jiffies(timeout));
+ if (signal_pending(current))
+ return -EINTR;
+
+ status = readl(vexpress_sysreg_base + SYS_CFGSTAT);
+ if (status & SYS_CFGSTAT_ERR)
+ return -EFAULT;
+
+ if (timeout > 20)
+ timeout -= 20;
+ } while (--tries && !(status & SYS_CFGSTAT_COMPLETE));
+ if (WARN_ON_ONCE(!tries))
+ return -ETIMEDOUT;
+
+ if (!write) {
+ *data = readl(vexpress_sysreg_base + SYS_CFGDATA);
+ dev_dbg(vexpress_sysreg_dev, "func %p, read data %x\n",
+ func, *data);
+ }
- do {
- cpu_relax();
- cfgstat = readl(vexpress_sysreg_base + SYS_CFGSTAT);
- } while (!cfgstat);
+ return 0;
+}
- if (!write && (cfgstat & SYS_CFGSTAT_COMPLETE))
- *data = readl(vexpress_sysreg_base + SYS_CFGDATA);
- status = VEXPRESS_CONFIG_STATUS_DONE;
+static int vexpress_sysreg_config_read(void *context, unsigned int index,
+ unsigned int *val)
+{
+ struct vexpress_sysreg_config_func *func = context;
- if (cfgstat & SYS_CFGSTAT_ERR)
- status = -EINVAL;
- }
+ return vexpress_sysreg_config_exec(func, index, false, val);
+}
- return status;
+static int vexpress_sysreg_config_write(void *context, unsigned int index,
+ unsigned int val)
+{
+ struct vexpress_sysreg_config_func *func = context;
+
+ return vexpress_sysreg_config_exec(func, index, true, &val);
}
-struct vexpress_config_bridge_info vexpress_sysreg_config_bridge_info = {
- .name = "vexpress-sysreg",
- .func_get = vexpress_sysreg_config_func_get,
- .func_put = vexpress_sysreg_config_func_put,
- .func_exec = vexpress_sysreg_config_func_exec,
+struct regmap_config vexpress_sysreg_regmap_config = {
+ .lock = vexpress_config_lock,
+ .unlock = vexpress_config_unlock,
+ .reg_bits = 32,
+ .val_bits = 32,
+ .reg_read = vexpress_sysreg_config_read,
+ .reg_write = vexpress_sysreg_config_write,
+ .reg_format_endian = REGMAP_ENDIAN_LITTLE,
+ .val_format_endian = REGMAP_ENDIAN_LITTLE,
};
-static void vexpress_sysreg_config_complete(unsigned long data)
+static struct regmap *vexpress_sysreg_config_regmap_init(struct device *dev,
+ void *context)
{
- int status = VEXPRESS_CONFIG_STATUS_DONE;
- u32 cfgstat = readl(vexpress_sysreg_base + SYS_CFGSTAT);
-
- if (cfgstat & SYS_CFGSTAT_ERR)
- status = -EINVAL;
- if (!vexpress_sysreg_config_tries--)
- status = -ETIMEDOUT;
-
- if (status < 0) {
- dev_err(vexpress_sysreg_dev, "error %d\n", status);
- } else if (!(cfgstat & SYS_CFGSTAT_COMPLETE)) {
- mod_timer(&vexpress_sysreg_config_timer,
- jiffies + usecs_to_jiffies(50));
- return;
+ struct platform_device *pdev = to_platform_device(dev);
+ struct vexpress_sysreg_config_func *func;
+ struct property *prop;
+ const __be32 *val = NULL;
+ __be32 energy_quirk[4];
+ int num;
+ u32 site, position, dcc;
+ int err;
+ int i;
+
+ if (dev->of_node) {
+ err = vexpress_config_get_topo(dev->of_node, &site, &position,
+ &dcc);
+ if (err)
+ return ERR_PTR(err);
+
+ prop = of_find_property(dev->of_node,
+ "arm,vexpress-sysreg,func", NULL);
+ if (!prop)
+ return ERR_PTR(-EINVAL);
+
+ num = prop->length / sizeof(u32) / 2;
+ val = prop->value;
+ } else {
+ if (pdev->num_resources != 1 ||
+ pdev->resource[0].flags != IORESOURCE_BUS)
+ return ERR_PTR(-EFAULT);
+
+ site = pdev->resource[0].start;
+ if (site == VEXPRESS_SITE_MASTER)
+ site = vexpress_sysreg_get_master();
+ position = 0;
+ dcc = 0;
+ num = 1;
}
- if (vexpress_sysreg_config_data) {
- *vexpress_sysreg_config_data = readl(vexpress_sysreg_base +
- SYS_CFGDATA);
- dev_dbg(vexpress_sysreg_dev, "read data %x\n",
- *vexpress_sysreg_config_data);
- vexpress_sysreg_config_data = NULL;
+ /*
+ * "arm,vexpress-energy" function used to be described
+ * by its first device only, now it requires both
+ */
+ if (num == 1 && of_device_is_compatible(dev->of_node,
+ "arm,vexpress-energy")) {
+ num = 2;
+ energy_quirk[0] = *val;
+ energy_quirk[2] = *val++;
+ energy_quirk[1] = *val;
+ energy_quirk[3] = cpu_to_be32(be32_to_cpup(val) + 1);
+ val = energy_quirk;
}
- vexpress_config_complete(vexpress_sysreg_config_bridge, status);
-}
+ func = kzalloc(sizeof(*func) + sizeof(*func->template) * num,
+ GFP_KERNEL);
+ if (!func)
+ return NULL;
+ func->num_templates = num;
-void vexpress_sysreg_setup(struct device_node *node)
-{
- if (WARN_ON(!vexpress_sysreg_base))
- return;
+ for (i = 0; i < num; i++) {
+ u32 function, device;
- if (readl(vexpress_sysreg_base + SYS_MISC) & SYS_MISC_MASTERSITE)
- vexpress_master_site = VEXPRESS_SITE_DB2;
+ if (dev->of_node) {
+ function = be32_to_cpup(val++);
+ device = be32_to_cpup(val++);
+ } else {
+ function = pdev->resource[0].end;
+ device = pdev->id;
+ }
+
+ dev_dbg(dev, "func %p: %u/%u/%u/%u/%u\n",
+ func, site, position, dcc,
+ function, device);
+
+ func->template[i] = SYS_CFGCTRL_DCC(dcc);
+ func->template[i] |= SYS_CFGCTRL_SITE(site);
+ func->template[i] |= SYS_CFGCTRL_POSITION(position);
+ func->template[i] |= SYS_CFGCTRL_FUNC(function);
+ func->template[i] |= SYS_CFGCTRL_DEVICE(device);
+ }
+
+ vexpress_sysreg_regmap_config.max_register = num - 1;
+
+ func->regmap = regmap_init(dev, NULL, func,
+ &vexpress_sysreg_regmap_config);
+
+ if (IS_ERR(func->regmap))
+ kfree(func);
else
- vexpress_master_site = VEXPRESS_SITE_DB1;
+ list_add(&func->list, &vexpress_sysreg_config_funcs);
- vexpress_sysreg_config_bridge = vexpress_config_bridge_register(
- node, &vexpress_sysreg_config_bridge_info);
- WARN_ON(!vexpress_sysreg_config_bridge);
+ return func->regmap;
+}
+
+static void vexpress_sysreg_config_regmap_exit(struct regmap *regmap,
+ void *context)
+{
+ struct vexpress_sysreg_config_func *func, *tmp;
+
+ regmap_exit(regmap);
+
+ list_for_each_entry_safe(func, tmp, &vexpress_sysreg_config_funcs,
+ list) {
+ if (func->regmap == regmap) {
+ list_del(&vexpress_sysreg_config_funcs);
+ kfree(func);
+ break;
+ }
+ }
+}
+
+static struct vexpress_config_bridge_ops vexpress_sysreg_config_bridge_ops = {
+ .regmap_init = vexpress_sysreg_config_regmap_init,
+ .regmap_exit = vexpress_sysreg_config_regmap_exit,
+};
+
+int vexpress_sysreg_config_device_register(struct platform_device *pdev)
+{
+ pdev->dev.parent = vexpress_sysreg_config_bridge;
+
+ return platform_device_register(pdev);
}
+
void __init vexpress_sysreg_early_init(void __iomem *base)
{
vexpress_sysreg_base = base;
- vexpress_sysreg_setup(NULL);
+ vexpress_config_set_master(vexpress_sysreg_get_master());
}
void __init vexpress_sysreg_of_early_init(void)
@@ -344,10 +358,14 @@ void __init vexpress_sysreg_of_early_init(void)
return;
node = of_find_compatible_node(NULL, NULL, "arm,vexpress-sysreg");
- if (node) {
- vexpress_sysreg_base = of_iomap(node, 0);
- vexpress_sysreg_setup(node);
- }
+ if (WARN_ON(!node))
+ return;
+
+ vexpress_sysreg_base = of_iomap(node, 0);
+ if (WARN_ON(!vexpress_sysreg_base))
+ return;
+
+ vexpress_config_set_master(vexpress_sysreg_get_master());
}
@@ -470,28 +488,22 @@ static int vexpress_sysreg_probe(struct platform_device *pdev)
return -EBUSY;
}
- if (!vexpress_sysreg_base) {
+ if (!vexpress_sysreg_base)
vexpress_sysreg_base = devm_ioremap(&pdev->dev, res->start,
resource_size(res));
- vexpress_sysreg_setup(pdev->dev.of_node);
- }
if (!vexpress_sysreg_base) {
dev_err(&pdev->dev, "Failed to obtain base address!\n");
return -EFAULT;
}
- setup_timer(&vexpress_sysreg_config_timer,
- vexpress_sysreg_config_complete, 0);
-
+ vexpress_config_set_master(vexpress_sysreg_get_master());
vexpress_sysreg_dev = &pdev->dev;
#ifdef CONFIG_GPIOLIB
vexpress_sysreg_gpio_chip.dev = &pdev->dev;
err = gpiochip_add(&vexpress_sysreg_gpio_chip);
if (err) {
- vexpress_config_bridge_unregister(
- vexpress_sysreg_config_bridge);
dev_err(&pdev->dev, "Failed to register GPIO chip! (%d)\n",
err);
return err;
@@ -502,6 +514,10 @@ static int vexpress_sysreg_probe(struct platform_device *pdev)
sizeof(vexpress_sysreg_leds_pdata));
#endif
+ vexpress_sysreg_config_bridge = vexpress_config_bridge_register(
+ &pdev->dev, &vexpress_sysreg_config_bridge_ops, NULL);
+ WARN_ON(!vexpress_sysreg_config_bridge);
+
device_create_file(vexpress_sysreg_dev, &dev_attr_sys_id);
return 0;
@@ -522,7 +538,12 @@ static struct platform_driver vexpress_sysreg_driver = {
static int __init vexpress_sysreg_init(void)
{
- vexpress_sysreg_of_early_init();
+ struct device_node *node;
+
+ /* Need the sysreg early, before any other device... */
+ for_each_matching_node(node, vexpress_sysreg_match)
+ of_platform_device_create(node, NULL, NULL);
+
return platform_driver_register(&vexpress_sysreg_driver);
}
core_initcall(vexpress_sysreg_init);
diff --git a/drivers/power/reset/vexpress-poweroff.c b/drivers/power/reset/vexpress-poweroff.c
index 476aa49..37e7799 100644
--- a/drivers/power/reset/vexpress-poweroff.c
+++ b/drivers/power/reset/vexpress-poweroff.c
@@ -23,13 +23,12 @@
static void vexpress_reset_do(struct device *dev, const char *what)
{
int err = -ENOENT;
- struct vexpress_config_func *func =
- vexpress_config_func_get_by_dev(dev);
+ struct regmap *reg = dev_get_drvdata(dev);
- if (func) {
+ if (reg) {
unsigned long timeout;
- err = vexpress_config_write(func, 0, 0);
+ err = regmap_write(reg, 0, 0);
timeout = jiffies + HZ;
while (time_before(jiffies, timeout))
@@ -96,6 +95,7 @@ static int vexpress_reset_probe(struct platform_device *pdev)
enum vexpress_reset_func func;
const struct of_device_id *match =
of_match_device(vexpress_reset_of_match, &pdev->dev);
+ struct regmap *regmap;
if (match)
func = (enum vexpress_reset_func)match->data;
@@ -120,6 +120,11 @@ static int vexpress_reset_probe(struct platform_device *pdev)
break;
};
+ regmap = devm_regmap_init_vexpress_config(&pdev->dev);
+ if (IS_ERR(regmap))
+ return PTR_ERR(regmap);
+ dev_set_drvdata(&pdev->dev, regmap);
+
return 0;
}
diff --git a/drivers/regulator/vexpress.c b/drivers/regulator/vexpress.c
index f3ae28a..2863428 100644
--- a/drivers/regulator/vexpress.c
+++ b/drivers/regulator/vexpress.c
@@ -26,14 +26,14 @@
struct vexpress_regulator {
struct regulator_desc desc;
struct regulator_dev *regdev;
- struct vexpress_config_func *func;
+ struct regmap *regmap;
};
static int vexpress_regulator_get_voltage(struct regulator_dev *regdev)
{
struct vexpress_regulator *reg = rdev_get_drvdata(regdev);
u32 uV;
- int err = vexpress_config_read(reg->func, 0, &uV);
+ int err = regmap_read(reg->regmap, 0, &uV);
return err ? err : uV;
}
@@ -43,7 +43,7 @@ static int vexpress_regulator_set_voltage(struct regulator_dev *regdev,
{
struct vexpress_regulator *reg = rdev_get_drvdata(regdev);
- return vexpress_config_write(reg->func, 0, min_uV);
+ return regmap_write(reg->regmap, 0, min_uV);
}
static struct regulator_ops vexpress_regulator_ops_ro = {
@@ -57,22 +57,17 @@ static struct regulator_ops vexpress_regulator_ops = {
static int vexpress_regulator_probe(struct platform_device *pdev)
{
- int err;
struct vexpress_regulator *reg;
struct regulator_init_data *init_data;
struct regulator_config config = { };
reg = devm_kzalloc(&pdev->dev, sizeof(*reg), GFP_KERNEL);
- if (!reg) {
- err = -ENOMEM;
- goto error_kzalloc;
- }
+ if (!reg)
+ return -ENOMEM;
- reg->func = vexpress_config_func_get_by_dev(&pdev->dev);
- if (!reg->func) {
- err = -ENXIO;
- goto error_get_func;
- }
+ reg->regmap = devm_regmap_init_vexpress_config(&pdev->dev);
+ if (IS_ERR(reg->regmap))
+ return PTR_ERR(reg->regmap);
reg->desc.name = dev_name(&pdev->dev);
reg->desc.type = REGULATOR_VOLTAGE;
@@ -80,10 +75,8 @@ static int vexpress_regulator_probe(struct platform_device *pdev)
reg->desc.continuous_voltage_range = true;
init_data = of_get_regulator_init_data(&pdev->dev, pdev->dev.of_node);
- if (!init_data) {
- err = -EINVAL;
- goto error_get_regulator_init_data;
- }
+ if (!init_data)
+ return -EINVAL;
init_data->constraints.apply_uV = 0;
if (init_data->constraints.min_uV && init_data->constraints.max_uV)
@@ -97,30 +90,12 @@ static int vexpress_regulator_probe(struct platform_device *pdev)
config.of_node = pdev->dev.of_node;
reg->regdev = devm_regulator_register(&pdev->dev, ®->desc, &config);
- if (IS_ERR(reg->regdev)) {
- err = PTR_ERR(reg->regdev);
- goto error_regulator_register;
- }
+ if (IS_ERR(reg->regdev))
+ return PTR_ERR(reg->regdev);
platform_set_drvdata(pdev, reg);
return 0;
-
-error_regulator_register:
-error_get_regulator_init_data:
- vexpress_config_func_put(reg->func);
-error_get_func:
-error_kzalloc:
- return err;
-}
-
-static int vexpress_regulator_remove(struct platform_device *pdev)
-{
- struct vexpress_regulator *reg = platform_get_drvdata(pdev);
-
- vexpress_config_func_put(reg->func);
-
- return 0;
}
static struct of_device_id vexpress_regulator_of_match[] = {
@@ -130,7 +105,6 @@ static struct of_device_id vexpress_regulator_of_match[] = {
static struct platform_driver vexpress_regulator_driver = {
.probe = vexpress_regulator_probe,
- .remove = vexpress_regulator_remove,
.driver = {
.name = DRVNAME,
.owner = THIS_MODULE,
diff --git a/include/linux/vexpress.h b/include/linux/vexpress.h
index 617c01b..ae4d2a1 100644
--- a/include/linux/vexpress.h
+++ b/include/linux/vexpress.h
@@ -15,16 +15,15 @@
#define _LINUX_VEXPRESS_H
#include <linux/device.h>
+#include <linux/platform_device.h>
#include <linux/reboot.h>
+#include <linux/regmap.h>
#define VEXPRESS_SITE_MB 0
#define VEXPRESS_SITE_DB1 1
#define VEXPRESS_SITE_DB2 2
#define VEXPRESS_SITE_MASTER 0xf
-#define VEXPRESS_CONFIG_STATUS_DONE 0
-#define VEXPRESS_CONFIG_STATUS_WAIT 1
-
#define VEXPRESS_GPIO_MMC_CARDIN 0
#define VEXPRESS_GPIO_MMC_WPROT 1
#define VEXPRESS_GPIO_FLASH_WPn 2
@@ -44,63 +43,30 @@
.flags = IORESOURCE_BUS, \
}
-/* Config bridge API */
+/* Config infrastructure */
-/**
- * struct vexpress_config_bridge_info - description of the platform
- * configuration infrastructure bridge.
- *
- * @name: Bridge name
- *
- * @func_get: Obtains pointer to a configuration function for a given
- * device or a Device Tree node, to be used with @func_put
- * and @func_exec. The node pointer should take precedence
- * over device pointer when both are passed.
- *
- * @func_put: Tells the bridge that the function will not be used any
- * more, so all allocated resources can be released.
- *
- * @func_exec: Executes a configuration function read or write operation.
- * The offset selects a 32 bit word of the value accessed.
- * Must return VEXPRESS_CONFIG_STATUS_DONE when operation
- * is finished immediately, VEXPRESS_CONFIG_STATUS_WAIT when
- * will be completed in some time or negative value in case
- * of error.
- */
-struct vexpress_config_bridge_info {
- const char *name;
- void *(*func_get)(struct device *dev, struct device_node *node);
- void (*func_put)(void *func);
- int (*func_exec)(void *func, int offset, bool write, u32 *data);
-};
+void vexpress_config_set_master(u32 site);
+u32 vexpress_config_get_master(void);
-struct vexpress_config_bridge;
+void vexpress_config_lock(void *arg);
+void vexpress_config_unlock(void *arg);
-struct vexpress_config_bridge *vexpress_config_bridge_register(
- struct device_node *node,
- struct vexpress_config_bridge_info *info);
-void vexpress_config_bridge_unregister(struct vexpress_config_bridge *bridge);
+int vexpress_config_get_topo(struct device_node *node, u32 *site,
+ u32 *position, u32 *dcc);
-void vexpress_config_complete(struct vexpress_config_bridge *bridge,
- int status);
+/* Config bridge API */
-/* Config function API */
+struct vexpress_config_bridge_ops {
+ struct regmap * (*regmap_init)(struct device *dev, void *context);
+ void (*regmap_exit)(struct regmap *regmap, void *context);
+};
-struct vexpress_config_func;
+struct device *vexpress_config_bridge_register(struct device *parent,
+ struct vexpress_config_bridge_ops *ops, void *context);
-struct vexpress_config_func *__vexpress_config_func_get(struct device *dev,
- struct device_node *node);
-#define vexpress_config_func_get_by_dev(dev) \
- __vexpress_config_func_get(dev, NULL)
-#define vexpress_config_func_get_by_node(node) \
- __vexpress_config_func_get(NULL, node)
-void vexpress_config_func_put(struct vexpress_config_func *func);
+/* Config regmap API */
-/* Both may sleep! */
-int vexpress_config_read(struct vexpress_config_func *func, int offset,
- u32 *data);
-int vexpress_config_write(struct vexpress_config_func *func, int offset,
- u32 data);
+struct regmap *devm_regmap_init_vexpress_config(struct device *dev);
/* Platform control */
@@ -109,19 +75,12 @@ u32 vexpress_get_hbi(int site);
void *vexpress_get_24mhz_clock_base(void);
void vexpress_flags_set(u32 data);
-#define vexpress_get_site_by_node(node) __vexpress_get_site(NULL, node)
-#define vexpress_get_site_by_dev(dev) __vexpress_get_site(dev, NULL)
-unsigned __vexpress_get_site(struct device *dev, struct device_node *node);
-
void vexpress_sysreg_early_init(void __iomem *base);
void vexpress_sysreg_of_early_init(void);
+int vexpress_sysreg_config_device_register(struct platform_device *pdev);
/* Clocks */
-struct clk *vexpress_osc_setup(struct device *dev);
-void vexpress_osc_of_setup(struct device_node *node);
-
void vexpress_clk_init(void __iomem *sp810_base);
-void vexpress_clk_of_init(void);
#endif
--
1.8.3.2
^ permalink raw reply related
* [PATCH 1/3] driver core & of: Mark of_nodes of added device as populated
From: Pawel Moll @ 2014-02-11 16:53 UTC (permalink / raw)
To: linux-kernel, linux-arm-kernel, devicetree, lm-sensors, arm
Cc: Rob Herring, Mark Rutland, Ian Campbell, Kumar Gala,
Greg Kroah-Hartman, Mike Turquette, Jean Delvare, Guenter Roeck,
Samuel Ortiz, Lee Jones, Arnd Bergmann, Grant Likely,
Dmitry Eremin-Solenikov, David Woodhouse, Liam Girdwood,
Mark Brown, Pawel Moll
In-Reply-To: <1392137610-27842-1-git-send-email-pawel.moll@arm.com>
In "Device Tree powered" systems, platform devices are usually
massively populated with of_platform_populate() call, executed
at some level of initcalls, either by generic architecture
or by platform-specific code.
There are situations though where certain devices must be
created (and bound with drivers) before all the others.
This presents small challenge in DT-driven systems, as
devices explicitly created in early code would be created
again by of_platform_populate().
This patch tries to solve that issue in a generic way,
adding a "populated" flag which is set in the device_node
structure when a device is being created in the core.
Later, of_platform_populate() skips such nodes (and
its children) in a similar way to the non-available ones.
Signed-off-by: Pawel Moll <pawel.moll@arm.com>
---
drivers/base/core.c | 4 ++++
drivers/of/device.c | 16 ++++++++++++++++
drivers/of/platform.c | 6 ++++--
include/linux/of.h | 6 ++++++
include/linux/of_device.h | 11 +++++++++++
5 files changed, 41 insertions(+), 2 deletions(-)
diff --git a/drivers/base/core.c b/drivers/base/core.c
index 2b56717..588c9a6 100644
--- a/drivers/base/core.c
+++ b/drivers/base/core.c
@@ -1088,6 +1088,8 @@ int device_add(struct device *dev)
class_intf->add_dev(dev, class_intf);
mutex_unlock(&dev->class->p->mutex);
}
+
+ of_device_populate(dev);
done:
put_device(dev);
return error;
@@ -1190,6 +1192,8 @@ void device_del(struct device *dev)
struct device *parent = dev->parent;
struct class_interface *class_intf;
+ of_device_depopulate(dev);
+
/* Notify clients of device removal. This call must come
* before dpm_sysfs_remove().
*/
diff --git a/drivers/of/device.c b/drivers/of/device.c
index dafb973..3b31144 100644
--- a/drivers/of/device.c
+++ b/drivers/of/device.c
@@ -190,3 +190,19 @@ int of_device_uevent_modalias(struct device *dev, struct kobj_uevent_env *env)
return 0;
}
+
+void of_device_populate(struct device *dev)
+{
+ if ((!dev) || (!dev->of_node))
+ return;
+
+ of_node_set_flag(dev->of_node, OF_POPULATED);
+}
+
+void of_device_depopulate(struct device *dev)
+{
+ if ((!dev) || (!dev->of_node))
+ return;
+
+ of_node_clear_flag(dev->of_node, OF_POPULATED);
+}
diff --git a/drivers/of/platform.c b/drivers/of/platform.c
index 404d1da..ad43ee0 100644
--- a/drivers/of/platform.c
+++ b/drivers/of/platform.c
@@ -204,7 +204,8 @@ static struct platform_device *of_platform_device_create_pdata(
{
struct platform_device *dev;
- if (!of_device_is_available(np))
+ if (!of_device_is_available(np) ||
+ of_node_check_flag(np, OF_POPULATED))
return NULL;
dev = of_device_alloc(np, bus_id, parent);
@@ -262,7 +263,8 @@ static struct amba_device *of_amba_device_create(struct device_node *node,
pr_debug("Creating amba device %s\n", node->full_name);
- if (!of_device_is_available(node))
+ if (!of_device_is_available(node) ||
+ of_node_check_flag(node, OF_POPULATED))
return NULL;
dev = amba_device_alloc(NULL, 0, 0);
diff --git a/include/linux/of.h b/include/linux/of.h
index 70c64ba..caf7b8a 100644
--- a/include/linux/of.h
+++ b/include/linux/of.h
@@ -114,6 +114,11 @@ static inline void of_node_set_flag(struct device_node *n, unsigned long flag)
set_bit(flag, &n->_flags);
}
+static inline void of_node_clear_flag(struct device_node *n, unsigned long flag)
+{
+ clear_bit(flag, &n->_flags);
+}
+
extern struct device_node *of_find_all_nodes(struct device_node *prev);
/*
@@ -156,6 +161,7 @@ static inline unsigned long of_read_ulong(const __be32 *cell, int size)
/* flag descriptions */
#define OF_DYNAMIC 1 /* node and properties were allocated via kmalloc */
#define OF_DETACHED 2 /* node has been detached from the device tree */
+#define OF_POPULATED 3 /* device already created for the node */
#define OF_IS_DYNAMIC(x) test_bit(OF_DYNAMIC, &x->_flags)
#define OF_MARK_DYNAMIC(x) set_bit(OF_DYNAMIC, &x->_flags)
diff --git a/include/linux/of_device.h b/include/linux/of_device.h
index 8d7dd67..513e598 100644
--- a/include/linux/of_device.h
+++ b/include/linux/of_device.h
@@ -44,6 +44,9 @@ static inline void of_device_node_put(struct device *dev)
of_node_put(dev->of_node);
}
+extern void of_device_populate(struct device *dev);
+extern void of_device_depopulate(struct device *dev);
+
static inline struct device_node *of_cpu_device_node_get(int cpu)
{
struct device *cpu_dev;
@@ -84,6 +87,14 @@ static inline const struct of_device_id *of_match_device(
return NULL;
}
+static inline void of_device_populate(struct device *dev)
+{
+}
+
+static inline void of_device_depopulate(struct device *dev)
+{
+}
+
static inline struct device_node *of_cpu_device_node_get(int cpu)
{
return NULL;
--
1.8.3.2
^ permalink raw reply related
* [PATCH 0/3] Versatile Express sysregs rework
From: Pawel Moll @ 2014-02-11 16:53 UTC (permalink / raw)
To: linux-kernel, linux-arm-kernel, devicetree, lm-sensors, arm
Cc: Rob Herring, Mark Rutland, Ian Campbell, Kumar Gala,
Greg Kroah-Hartman, Mike Turquette, Jean Delvare, Guenter Roeck,
Samuel Ortiz, Lee Jones, Arnd Bergmann, Grant Likely,
Dmitry Eremin-Solenikov, David Woodhouse, Liam Girdwood,
Mark Brown, Pawel Moll
It's over 6 month since I promised Samuel to rework the
not-really-MFD driver for Versatile Express sysregs. It's
also a while since I sent the RFC for the series, but
finally - it is here!
As suggested by Arnd back then, the VE configuration
infrastructure is now exposing standard regmap interface
instead of a custom one. As requested by Samuel, the sysreg
driver mainly consists of MFD cells definition now.
All this was possible thanks to the first patch, which
tries to address in a simple way an issue discussed
a number of times - a problem of early devices registration
in a "DT-powered" system. It simply makes it possible
to manually create devices for selected nodes at appropriate
init levels and guarantees that such devices will not
be created again during the massive of_platform_populate().
I think it would make sense to merge the whole series
through arm-soc tree so will appreciate opinions and/or
acks from respective maintainers.
Pawel Moll (3):
driver core & of: Mark of_nodes of added device as populated
mfd: vexpress: Convert custom func API to regmap
mfd: vexpress: Define the device as MFD cells
.../devicetree/bindings/arm/vexpress-sysreg.txt | 79 ++-
Documentation/devicetree/bindings/arm/vexpress.txt | 15 +-
arch/arm/boot/dts/vexpress-v2m-rs1.dtsi | 76 ++-
arch/arm/boot/dts/vexpress-v2m.dtsi | 76 ++-
arch/arm/boot/dts/vexpress-v2p-ca15_a7.dts | 5 +-
arch/arm/mach-vexpress/ct-ca9x4.c | 10 +-
arch/arm/mach-vexpress/v2m.c | 25 +-
arch/arm64/boot/dts/rtsm_ve-motherboard.dtsi | 2 +-
drivers/base/core.c | 4 +
drivers/bus/Kconfig | 9 +
drivers/bus/Makefile | 2 +
drivers/bus/vexpress-config.c | 202 ++++++++
drivers/clk/versatile/clk-vexpress-osc.c | 94 ++--
drivers/hwmon/vexpress.c | 15 +-
drivers/mfd/Kconfig | 15 +-
drivers/mfd/Makefile | 2 +-
drivers/mfd/vexpress-config.c | 288 -----------
drivers/mfd/vexpress-sysreg.c | 538 ++++++---------------
drivers/misc/Kconfig | 9 +
drivers/misc/Makefile | 1 +
drivers/misc/vexpress-syscfg.c | 320 ++++++++++++
drivers/of/device.c | 16 +
drivers/of/platform.c | 6 +-
drivers/power/reset/vexpress-poweroff.c | 13 +-
drivers/regulator/vexpress.c | 50 +-
include/linux/of.h | 6 +
include/linux/of_device.h | 11 +
include/linux/vexpress.h | 93 +---
28 files changed, 1059 insertions(+), 923 deletions(-)
create mode 100644 drivers/bus/vexpress-config.c
delete mode 100644 drivers/mfd/vexpress-config.c
create mode 100644 drivers/misc/vexpress-syscfg.c
--
1.8.3.2
^ permalink raw reply
* Re: [PATCH 4/8] ARM: mvebu: make use of of_find_matching_node_and_match
From: Jason Cooper @ 2014-02-11 16:53 UTC (permalink / raw)
To: Josh Cartwright
Cc: Andrew Lunn, Gregory Clement, Sebastian Hesselbarth,
devicetree-u79uwXL29TY76Z2rM5mHXA, Russell King,
linux-kernel-u79uwXL29TY76Z2rM5mHXA,
linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r
In-Reply-To: <1392135847-30791-5-git-send-email-joshc-sgV2jX0FEOL9JmXXK+q4OQ@public.gmane.org>
On Tue, Feb 11, 2014 at 10:24:02AM -0600, Josh Cartwright wrote:
> Instead of the of_find_matching_node()/of_match_node() pair, which requires two
> iterations through the match table, make use of of_find_matching_node_and_match(),
> which only iterates through the table once.
>
> While we're here, mark the of_system_controller table const.
>
> Signed-off-by: Josh Cartwright <joshc-sgV2jX0FEOL9JmXXK+q4OQ@public.gmane.org>
> ---
> arch/arm/mach-mvebu/system-controller.c | 9 ++++-----
> 1 file changed, 4 insertions(+), 5 deletions(-)
>
> diff --git a/arch/arm/mach-mvebu/system-controller.c b/arch/arm/mach-mvebu/system-controller.c
> index a7fb89a..e6e300a 100644
> --- a/arch/arm/mach-mvebu/system-controller.c
> +++ b/arch/arm/mach-mvebu/system-controller.c
> @@ -54,7 +54,7 @@ static const struct mvebu_system_controller orion_system_controller = {
> .system_soft_reset = 0x1,
> };
>
> -static struct of_device_id of_system_controller_table[] = {
> +static const struct of_device_id of_system_controller_table[] = {
> {
> .compatible = "marvell,orion-system-controller",
> .data = (void *) &orion_system_controller,
> @@ -90,13 +90,12 @@ void mvebu_restart(enum reboot_mode mode, const char *cmd)
>
> static int __init mvebu_system_controller_init(void)
> {
> + const struct of_device_id *match;
> struct device_node *np;
>
> - np = of_find_matching_node(NULL, of_system_controller_table);
> + np = of_find_matching_node_and_match(NULL, of_system_controller_table,
> + &match);
> if (np) {
> - const struct of_device_id *match =
> - of_match_node(of_system_controller_table, np);
> - BUG_ON(!match);
Gregory, is it ok to remove this? It was added with the original code
submission for mach-mvebu. mvebu_restart() will handle this
gracefully...
> system_controller_base = of_iomap(np, 0);
> mvebu_sc = (struct mvebu_system_controller *)match->data;
> of_node_put(np);
thx,
Jason.
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply
* Re: [PATCH] of: Turn of_match_node into a static inline when CONFIG_OF isn't set
From: Josh Cartwright @ 2014-02-11 16:48 UTC (permalink / raw)
To: Laurent Pinchart; +Cc: linux-kernel, devicetree, Grant Likely, Rob Herring
In-Reply-To: <1596542.hkJp71u3OJ@avalon>
On Tue, Feb 11, 2014 at 03:55:35PM +0100, Laurent Pinchart wrote:
> Hi Josh,
>
> On Tuesday 11 February 2014 08:41:08 Josh Cartwright wrote:
> > On Tue, Feb 11, 2014 at 01:36:51PM +0100, Laurent Pinchart wrote:
> > > when CONFIG_OF is disabled of_match_node is defined as a macro that
> > > evaluates to NULL. This breaks compilation of drivers that dereference
> > > the function's return value directly. Fix it by turning the macro into a
> > > static inline function that returns NULL.
> >
> > Just this past week I did the same thing, but noticed that it breaks the
> > following usecase:
> >
> > #ifdef CONFIG_OF
> > static const struct of_device_id foobar_matches[] = {
> > { .compatible = "foobar,whatsit", },
> > { },
> > };
> > #endif
> >
> > static int probeme(struct platform_device *pdev)
> > {
> > struct of_device_id *id;
> >
> > id = of_match_node(foobar_matches, pdev->dev.of_node);
> > if (id) {
> > /* ... */
> > }
> > return 0;
> > }
> >
> > When !CONFIG_OF and with your change, this will fail to build due to
> > foobar_matches being undefined.
>
> Good point. What would you think about
>
> #define of_match_node(_matches, _node) ((const struct of_device_id *)NULL)
I've just sent out a patchset that cleans up at least a couple of users
that directly do of_match_node(matches, np)->data using
of_find_matching_node_and_match. Not sure if that will fix the usage
you have in mind, though.
I am a bit weary about having an of_match_node() user that both directly
dereferences the result (i.e. of_match_node(matches, np)->data) _and_
builds when !CONFIG_OF; most likely due to a traumatic childhood event
where demons flew out my nose.
--
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum,
hosted by The Linux Foundation
^ permalink raw reply
* Re: [PATCH v2 1/2] ohci-platform: Change compatible string from usb-ohci to generic-ohci
From: Alan Stern @ 2014-02-11 16:43 UTC (permalink / raw)
To: Hans de Goede
Cc: Greg Kroah-Hartman, Roger Quadros, Tony Prisk, Florian Fainelli,
Maxime Ripard, Arnd Bergmann, linux-usb,
linux-sunxi-/JYPxA39Uh5TLH3MbocFFw,
linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r, devicetree
In-Reply-To: <1392136529-5060-2-git-send-email-hdegoede-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>
On Tue, 11 Feb 2014, Hans de Goede wrote:
> The initial versions of the devicetree enablement patches for ohci-platform
> used "ohci-platform" as compatible string. However this was disliked by various
> reviewers because the platform bus is a Linux invention and devicetree is
> supposed to be OS agnostic. After much discussion I gave up and went with
> the generic usb-ohci as requested.
>
> In retro-spect I should have chosen something different, the dts files for many
> existing boards already claim to be compatible with "usb-ohci", ie they have:
>
> compatible = "ti,ohci-omap3", "usb-ohci";
>
> In theory this should not be a problem since the "ti,ohci-omap3" entry takes
> presedence, but in practice using a conflicting compatible string is an issue,
> because it makes which driver gets used depend on driver registration order.
>
> This patch changes the compatible string claimed by ohci-platform to
> "generic-ohci", avoiding the driver registration / module loading ordering
> problems.
>
> Signed-off-by: Hans de Goede <hdegoede-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>
For both v2 patches:
Acked-by: Alan Stern <stern-nwvwT67g6+6dFdvTe/nMLpVzexx5G7lz@public.gmane.org>
^ permalink raw reply
* Re: [PATCH] phy-core: Don't allow building phy-core as a module
From: Andrew Lunn @ 2014-02-11 16:42 UTC (permalink / raw)
To: Hans de Goede
Cc: Kishon Vijay Abraham I, devicetree, Greg Kroah-Hartman,
linux-sunxi-/JYPxA39Uh5TLH3MbocFFw, Maxime Ripard,
linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r, Roger Quadros
In-Reply-To: <1392134631-32030-1-git-send-email-hdegoede-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>
On Tue, Feb 11, 2014 at 05:03:51PM +0100, Hans de Goede wrote:
> include/phy/phy.h has stub code in there for when building without the
> phy-core enabled. This is useful for generic drivers such as ahci-platform,
> ehci-platoform and ohci-platform which have support for driving an optional
> phy passed to them through the devicetree.
>
> Since on some boards this phy functionality is not needed, being able to
> disable the phy subsystem without needing a lot of #ifdef magic in the
> driver using it is quite useful.
>
> However this breaks when the module using the phy subsystem is build-in and
> the phy-core is not, which leads to the build failing with missing symbol
> errors in the linking stage of the zImage.
>
> Which leads to gems such as this being added to the Kconfig for achi_platform:
>
> depends on GENERIC_PHY || !GENERIC_PHY
>
> Rather then duplicating this code in a lot of places using the phy-core,
> I believe it is better to simply not allow the phy-core to be built as a
> module. The phy core is quite small and has no external dependencies, so
> always building it in when enabling it should not be an issue.
Hi Hans
I ran into the same problem with sata_mv. I ended up adding a select
GENERIC_PHY to force it to be built in.
So i agree with you to make it only built in.
Acked-by: Andrew Lunn <andrew-g2DYL2Zd6BY@public.gmane.org>
Andrew
^ permalink raw reply
* Re: [PATCH 4/8] ARM: mvebu: make use of of_find_matching_node_and_match
From: Thomas Petazzoni @ 2014-02-11 16:41 UTC (permalink / raw)
To: Josh Cartwright
Cc: Jason Cooper, Andrew Lunn, Gregory Clement, Sebastian Hesselbarth,
devicetree-u79uwXL29TY76Z2rM5mHXA, Russell King,
linux-kernel-u79uwXL29TY76Z2rM5mHXA,
linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r
In-Reply-To: <1392135847-30791-5-git-send-email-joshc-sgV2jX0FEOL9JmXXK+q4OQ@public.gmane.org>
Dear Josh Cartwright,
On Tue, 11 Feb 2014 10:24:02 -0600, Josh Cartwright wrote:
> Instead of the of_find_matching_node()/of_match_node() pair, which requires two
> iterations through the match table, make use of of_find_matching_node_and_match(),
> which only iterates through the table once.
>
> While we're here, mark the of_system_controller table const.
>
> Signed-off-by: Josh Cartwright <joshc-sgV2jX0FEOL9JmXXK+q4OQ@public.gmane.org>
> ---
> arch/arm/mach-mvebu/system-controller.c | 9 ++++-----
> 1 file changed, 4 insertions(+), 5 deletions(-)
Reviewed-by: Thomas Petazzoni <thomas.petazzoni-wi1+55ScJUtKEb57/3fJTNBPR1lH4CV8@public.gmane.org>
--
Thomas Petazzoni, CTO, Free Electrons
Embedded Linux, Kernel and Android engineering
http://free-electrons.com
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply
* Re: [PATCH 2/8] bus: mvebu-mbus: make use of of_find_matching_node_and_match
From: Jason Cooper @ 2014-02-11 16:39 UTC (permalink / raw)
To: Josh Cartwright
Cc: Andrew Lunn, Gregory Clement, Sebastian Hesselbarth,
linux-kernel-u79uwXL29TY76Z2rM5mHXA,
devicetree-u79uwXL29TY76Z2rM5mHXA,
linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r
In-Reply-To: <1392135847-30791-3-git-send-email-joshc-sgV2jX0FEOL9JmXXK+q4OQ@public.gmane.org>
On Tue, Feb 11, 2014 at 10:24:00AM -0600, Josh Cartwright wrote:
> Instead of the of_find_matching_node()/of_match_node() pair, which requires two
> iterations through the match table, make use of of_find_matching_node_and_match(),
> which only iterates through the table once.
>
> Signed-off-by: Josh Cartwright <joshc-sgV2jX0FEOL9JmXXK+q4OQ@public.gmane.org>
> ---
> drivers/bus/mvebu-mbus.c | 3 +--
> 1 file changed, 1 insertion(+), 2 deletions(-)
Acked-by: Jason Cooper <jason-NLaQJdtUoK4Be96aLqz0jA@public.gmane.org>
thx,
Jason.
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply
* Re: [RFC PATCH] [media]: of: move graph helpers from drivers/media/v4l2-core to drivers/of
From: Philipp Zabel @ 2014-02-11 16:36 UTC (permalink / raw)
To: Laurent Pinchart
Cc: Russell King - ARM Linux, Rob Herring, Mauro Carvalho Chehab,
Grant Likely, Rob Herring, Sylwester Nawrocki, Tomi Valkeinen,
Kyungmin Park, linux-kernel@vger.kernel.org,
linux-media@vger.kernel.org, devicetree@vger.kernel.org,
Philipp Zabel
In-Reply-To: <8648675.AIXYyYlgXy@avalon>
Am Dienstag, den 11.02.2014, 16:23 +0100 schrieb Laurent Pinchart:
> Hi Russell,
>
> On Tuesday 11 February 2014 14:52:48 Russell King - ARM Linux wrote:
> > On Tue, Feb 11, 2014 at 07:56:33AM -0600, Rob Herring wrote:
> > > On Tue, Feb 11, 2014 at 5:45 AM, Philipp Zabel wrote:
> > > > This allows to reuse the same parser code from outside the V4L2
> > > > framework, most importantly from display drivers. There have been
> > > > patches that duplicate the code (and I am going to send one of my own),
> > > > such as
> > > > http://lists.freedesktop.org/archives/dri-devel/2013-August/043308.html
> > > > and others that parse the same binding in a different way:
> > > > https://www.mail-archive.com/linux-omap@vger.kernel.org/msg100761.html
> > > >
> > > > I think that all common video interface parsing helpers should be moved
> > > > to a single place, outside of the specific subsystems, so that it can
> > > > be reused by all drivers.
> > >
> > > Perhaps that should be done rather than moving to drivers/of now and
> > > then again to somewhere else.
> >
> > Do you have a better suggestion where it should move to?
> >
> > drivers/gpu/drm - no, because v4l2 wants to use it
> > drivers/media/video - no, because DRM drivers want to use it
> > drivers/video - no, because v4l2 and drm drivers want to use it
>
> Just pointing out a missing location (which might be rejected due to similar
> concerns), there's also drivers/media, which isn't V4L-specific.
Since drivers/Makefile has media/ in obj-y, moving the graph helpers to
drivers/media should technically work.
> > Maybe drivers/of-graph/ ? Or maybe it's just as good a place to move it
> > into drivers/of ?
include/media/of_graph.h,
drivers/media/of_graph.c?
regards
Philipp
^ permalink raw reply
* [PATCH v2 2/2] ehci-platform: Change compatible string from usb-ehci to generic-ehci
From: Hans de Goede @ 2014-02-11 16:35 UTC (permalink / raw)
To: Greg Kroah-Hartman
Cc: Roger Quadros, Alan Stern, Tony Prisk, Florian Fainelli,
Maxime Ripard, Arnd Bergmann, linux-usb,
linux-sunxi-/JYPxA39Uh5TLH3MbocFFw,
linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r, devicetree,
Hans de Goede
In-Reply-To: <1392136529-5060-1-git-send-email-hdegoede-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>
The initial versions of the devicetree enablement patches for ehci-platform
used "ehci-platform" as compatible string. However this was disliked by various
reviewers because the platform bus is a Linux invention and devicetree is
supposed to be OS agnostic. After much discussion I gave up, added a:
"depends on !PPC_OF" to Kconfig to avoid a known conflict with PPC-OF platforms
and went with the generic usb-ehci as requested.
In retro-spect I should have chosen something different, the dts files for many
existing boards already claim to be compatible with "usb-ehci", ie they have:
compatible = "ti,ehci-omap", "usb-ehci";
In theory this should not be a problem since the "ti,ehci-omap" entry takes
presedence, but in practice using a conflicting compatible string is an issue,
because it makes which driver gets used depend on driver registration order.
This patch changes the compatible string claimed by ehci-platform to
"generic-ehci", avoiding the driver registration / module loading ordering
problems, and removes the "depends on !PPC_OF" workaround.
Signed-off-by: Hans de Goede <hdegoede-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>
---
Documentation/devicetree/bindings/usb/usb-ehci.txt | 4 ++--
drivers/usb/host/Kconfig | 1 -
drivers/usb/host/ehci-platform.c | 2 +-
3 files changed, 3 insertions(+), 4 deletions(-)
diff --git a/Documentation/devicetree/bindings/usb/usb-ehci.txt b/Documentation/devicetree/bindings/usb/usb-ehci.txt
index 2c1aeeb..ff151ec 100644
--- a/Documentation/devicetree/bindings/usb/usb-ehci.txt
+++ b/Documentation/devicetree/bindings/usb/usb-ehci.txt
@@ -1,7 +1,7 @@
USB EHCI controllers
Required properties:
- - compatible : should be "usb-ehci".
+ - compatible : should be "generic-ehci".
- reg : should contain at least address and length of the standard EHCI
register set for the device. Optional platform-dependent registers
(debug-port or other) can be also specified here, but only after
@@ -27,7 +27,7 @@ Example (Sequoia 440EPx):
Example (Allwinner sun4i A10 SoC):
ehci0: usb@01c14000 {
- compatible = "allwinner,sun4i-a10-ehci", "usb-ehci";
+ compatible = "allwinner,sun4i-a10-ehci", "generic-ehci";
reg = <0x01c14000 0x100>;
interrupts = <39>;
clocks = <&ahb_gates 1>;
diff --git a/drivers/usb/host/Kconfig b/drivers/usb/host/Kconfig
index e28cbe0..a9707da 100644
--- a/drivers/usb/host/Kconfig
+++ b/drivers/usb/host/Kconfig
@@ -255,7 +255,6 @@ config USB_EHCI_ATH79
config USB_EHCI_HCD_PLATFORM
tristate "Generic EHCI driver for a platform device"
- depends on !PPC_OF
default n
---help---
Adds an EHCI host driver for a generic platform device, which
diff --git a/drivers/usb/host/ehci-platform.c b/drivers/usb/host/ehci-platform.c
index 8fde649..1178730 100644
--- a/drivers/usb/host/ehci-platform.c
+++ b/drivers/usb/host/ehci-platform.c
@@ -333,7 +333,7 @@ static int ehci_platform_resume(struct device *dev)
static const struct of_device_id vt8500_ehci_ids[] = {
{ .compatible = "via,vt8500-ehci", },
{ .compatible = "wm,prizm-ehci", },
- { .compatible = "usb-ehci", },
+ { .compatible = "generic-ehci", },
{}
};
MODULE_DEVICE_TABLE(of, vt8500_ehci_ids);
--
1.8.5.3
^ permalink raw reply related
* [PATCH v2 1/2] ohci-platform: Change compatible string from usb-ohci to generic-ohci
From: Hans de Goede @ 2014-02-11 16:35 UTC (permalink / raw)
To: Greg Kroah-Hartman
Cc: Roger Quadros, Alan Stern, Tony Prisk, Florian Fainelli,
Maxime Ripard, Arnd Bergmann, linux-usb,
linux-sunxi-/JYPxA39Uh5TLH3MbocFFw,
linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r, devicetree,
Hans de Goede
In-Reply-To: <1392136529-5060-1-git-send-email-hdegoede-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>
The initial versions of the devicetree enablement patches for ohci-platform
used "ohci-platform" as compatible string. However this was disliked by various
reviewers because the platform bus is a Linux invention and devicetree is
supposed to be OS agnostic. After much discussion I gave up and went with
the generic usb-ohci as requested.
In retro-spect I should have chosen something different, the dts files for many
existing boards already claim to be compatible with "usb-ohci", ie they have:
compatible = "ti,ohci-omap3", "usb-ohci";
In theory this should not be a problem since the "ti,ohci-omap3" entry takes
presedence, but in practice using a conflicting compatible string is an issue,
because it makes which driver gets used depend on driver registration order.
This patch changes the compatible string claimed by ohci-platform to
"generic-ohci", avoiding the driver registration / module loading ordering
problems.
Signed-off-by: Hans de Goede <hdegoede-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>
---
Documentation/devicetree/bindings/usb/usb-ohci.txt | 4 ++--
drivers/usb/host/ohci-platform.c | 2 +-
2 files changed, 3 insertions(+), 3 deletions(-)
diff --git a/Documentation/devicetree/bindings/usb/usb-ohci.txt b/Documentation/devicetree/bindings/usb/usb-ohci.txt
index 6933b0c..45f67d9 100644
--- a/Documentation/devicetree/bindings/usb/usb-ohci.txt
+++ b/Documentation/devicetree/bindings/usb/usb-ohci.txt
@@ -1,7 +1,7 @@
USB OHCI controllers
Required properties:
-- compatible : "usb-ohci"
+- compatible : "generic-ohci"
- reg : ohci controller register range (address and length)
- interrupts : ohci controller interrupt
@@ -16,7 +16,7 @@ Optional properties:
Example:
ohci0: usb@01c14400 {
- compatible = "allwinner,sun4i-a10-ohci", "usb-ohci";
+ compatible = "allwinner,sun4i-a10-ohci", "generic-ohci";
reg = <0x01c14400 0x100>;
interrupts = <64>;
clocks = <&usb_clk 6>, <&ahb_gates 2>;
diff --git a/drivers/usb/host/ohci-platform.c b/drivers/usb/host/ohci-platform.c
index e2c28fd..b6ca0b2 100644
--- a/drivers/usb/host/ohci-platform.c
+++ b/drivers/usb/host/ohci-platform.c
@@ -319,7 +319,7 @@ static int ohci_platform_resume(struct device *dev)
#endif /* CONFIG_PM */
static const struct of_device_id ohci_platform_ids[] = {
- { .compatible = "usb-ohci", },
+ { .compatible = "generic-ohci", },
{ }
};
MODULE_DEVICE_TABLE(of, ohci_platform_ids);
--
1.8.5.3
^ permalink raw reply related
* [PATCH v2 0/2] ohci-/ehci-platform: Change compatible string to generic-?hci
From: Hans de Goede @ 2014-02-11 16:35 UTC (permalink / raw)
To: Greg Kroah-Hartman
Cc: Roger Quadros, Alan Stern, Tony Prisk, Florian Fainelli,
Maxime Ripard, Arnd Bergmann, linux-usb,
linux-sunxi-/JYPxA39Uh5TLH3MbocFFw,
linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r, devicetree
Hi Greg,
And here is v2 of my ohci-/ehci-platform fixes for the regression of USB
support on various ARM boards I caused in linux-next.
As expected some people still did not like the ?hci-platform compatible
string I went for in v1, hence this v2. The good news is it seems everyone
seems to be able to live with generic-?hci as compatible now, so it seems this
issue is finally settled.
Please add these 2 patches to your usb-next tree, as said in the cover-letter
of v1, I'm fine with you squashing these into the first 2 patches of my
original series, but if you want them separate to preserve history that is
fine too.
Thanks & Regards,
Hans
^ permalink raw reply
* Re: [RFC PATCH] [media]: of: move graph helpers from drivers/media/v4l2-core to drivers/of
From: Rob Herring @ 2014-02-11 16:30 UTC (permalink / raw)
To: Russell King - ARM Linux
Cc: Philipp Zabel, Mauro Carvalho Chehab, Grant Likely, Rob Herring,
Sylwester Nawrocki, Laurent Pinchart, Tomi Valkeinen,
Kyungmin Park, linux-kernel@vger.kernel.org,
linux-media@vger.kernel.org, devicetree@vger.kernel.org,
Philipp Zabel
In-Reply-To: <20140211145248.GI26684@n2100.arm.linux.org.uk>
On Tue, Feb 11, 2014 at 8:52 AM, Russell King - ARM Linux
<linux@arm.linux.org.uk> wrote:
> On Tue, Feb 11, 2014 at 07:56:33AM -0600, Rob Herring wrote:
>> On Tue, Feb 11, 2014 at 5:45 AM, Philipp Zabel <p.zabel@pengutronix.de> wrote:
>> > This allows to reuse the same parser code from outside the V4L2 framework,
>> > most importantly from display drivers. There have been patches that duplicate
>> > the code (and I am going to send one of my own), such as
>> > http://lists.freedesktop.org/archives/dri-devel/2013-August/043308.html
>> > and others that parse the same binding in a different way:
>> > https://www.mail-archive.com/linux-omap@vger.kernel.org/msg100761.html
>> >
>> > I think that all common video interface parsing helpers should be moved to a
>> > single place, outside of the specific subsystems, so that it can be reused
>> > by all drivers.
>>
>> Perhaps that should be done rather than moving to drivers/of now and
>> then again to somewhere else.
>
> Do you have a better suggestion where it should move to?
No.
> drivers/gpu/drm - no, because v4l2 wants to use it
> drivers/media/video - no, because DRM drivers want to use it
> drivers/video - no, because v4l2 and drm drivers want to use it
I don't believe it exists currently, so it would need to be created.
Perhaps adding a layer of directory to combine these. This patch alone
is not enough to really justify that, but if there's a lot more shared
code possible then it would be the right direction.
> Maybe drivers/of-graph/ ? Or maybe it's just as good a place to move it
> into drivers/of ?
I assume you weren't serious, but no for /of-graph. If a better place
can't be found/made, I'll take it.
Rob
^ permalink raw reply
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox