* Re: [PATCH v9 3/4] dtc: Plugin and fixup support
From: Pantelis Antoniou @ 2016-11-24 14:23 UTC (permalink / raw)
To: Phil Elwell
Cc: David Gibson, Jon Loeliger, Grant Likely, Frank Rowand,
Rob Herring, Jan Luebbe, Sascha Hauer, Simon Glass, Maxime Ripard,
Thomas Petazzoni, Boris Brezillon, Antoine Tenart, Stephen Boyd,
Devicetree Compiler, devicetree-u79uwXL29TY76Z2rM5mHXA
In-Reply-To: <2ad2929c-6e6a-4e31-0cca-cea2f11b14b1-FnsA7b+Nu9XbIbC87yuRow@public.gmane.org>
Hi Phil,
> On Nov 24, 2016, at 16:14 , Phil Elwell <phil-FnsA7b+Nu9XbIbC87yuRow@public.gmane.org> wrote:
>
> On 24/11/2016 13:58, Pantelis Antoniou wrote:
>> Hi Phil,
>>
>>> On Nov 24, 2016, at 15:49 , Phil Elwell <phil-FnsA7b+Nu9XbIbC87yuRow@public.gmane.org> wrote:
>>>
>>> On 24/11/2016 12:31, Pantelis Antoniou wrote:
>>>> This patch enable the generation of symbols & local fixup information
>>>> for trees compiled with the -@ (--symbols) option.
>>>>
>>>> Using this patch labels in the tree and their users emit information
>>>> in __symbols__ and __local_fixups__ nodes.
>>>>
>>>> The __fixups__ node make possible the dynamic resolution of phandle
>>>> references which are present in the plugin tree but lie in the
>>>> tree that are applying the overlay against.
>>>>
>>>> While there is a new magic number for dynamic device tree/overlays blobs
>>>> it is by default disabled. This is in order to give time for DT blob
>>>> methods to be updated.
>>>>
>>>> Signed-off-by: Pantelis Antoniou <pantelis.antoniou-OWPKS81ov/FWk0Htik3J/w@public.gmane.org>
>>>> Signed-off-by: Sascha Hauer <s.hauer-bIcnvbaLZ9MEGnE8C9+IrQ@public.gmane.org>
>>>> Signed-off-by: Jan Luebbe <jlu-bIcnvbaLZ9MEGnE8C9+IrQ@public.gmane.org>
>>> It's great to see this work about to come to fruition, but I have a
>>> reservation about this patch. Like previous versions, this
>>> implementation generates __fixups__, __local_fixups__ and __symbols__
>>> whenever the "-@" command line parameter is given; without it you get
>>> none. In my opinion, this logic causes the DTBs to be unnecessarily
>>> large with no obvious benefit.
>>>
>>> You can divide the compiled outputs from DTC into two categories - fully
>>> resolved DTBs (what I would call base DTBs), and overlays. Base DTBs
>>> should include __symbols__ to allow overlays to be applied, and it is
>>> right that this should be controlled by the "-@" flag, but since base
>>> DTBs are fully resolved I think there is no reason to include either
>>> __fixups__ or __local_fixups__. Therefore I think both kinds of fixups
>>> should only be omitted when the "/plugin/ " directive is used. This was
>>> the purpose of one of the patches I provided you with.
>>>
>> Yes, I’m quite aware of that. There is a reason for generating every
>> resolve node for the base tree. It contains information about the
>> dependencies of every hardware device due to phandle references.
>> We can utilize that to re-order the device probe order to eliminate
>> -EPROBE_DEFER cycles upon boot.
>>
>> It is important we get the core support in and then you can add extra
>> switches for every special platform case.
>>
>> What kind of problems do you have with larger device tree blobs?
>> I do carry a hashed phandle patch on my mainline tracking tree which
>> should help with larger DTBs.
> Early Raspberry Pi DT support used to load the DTBs to 0x100, Although
> the ARMv6/7 kernel starts at 0x8000, something (the decompressor?) would
> use the space between 0x4000 and the 0x8000, which gave us a practical
> limit of 16KB on the DTB size. This used to be sufficient for a base DTB
> and a few small overlays, but with the patch all Pi DTBs are over 16KB.
> The practical limit was overcome a long time ago, but it made me aware
> of the DTB contents, and there are may be some situations where it is
> desirable to reduce the footprint as much as possible.
>
I see now why you care about this. If you can regenerate your patch against
what I’ve posted I’d be happy to carry it along.
But DTBs are getting pretty large even without the extra fixup nodes. It is
not uncommon to see them at a few hundred KBs now.
> I would have thought that all DTBs already contain enough dependency
> information in the form of the phandles themselves. One of the first
> things the kernel does is to unflatten the DTB, and that is the obvious
> point to resolve the phandles and generate the necessary dependencies.
> Can you explain how both __fixups__ and __local_fixups__ aid this
> process? Ideally they wouldn't duplicate any information already in the
> tree, since then you have to cope with the possibility of malformed DTBs
> where the two don't actually match.
No, the DTBs by themselves do not contain enough information to build the
probe dependency graph, because phandles are simply converted to 32 bit
cell values on compile.
For instance take a case of one node using the other:
foo_label: foo { };
bar { use = <&foo_label>; };
A standard compile would generate a bar node as bar { use = <1>; };
While using the -@ switch you’d get a local ref that says that there is
a phandle cell value at offset 0 of bar/use property. Looking up the
phandle value you can see that this property references the foo node.
So when building the probe order graph the foo node should be probed
before bar.
>
> Phil
Regards
— Pantelis
--
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 V3 2/2] pinctrl: tegra: Add driver to configure voltage and power of io pads
From: Laxman Dewangan @ 2016-11-24 14:19 UTC (permalink / raw)
To: Linus Walleij, Mark Brown
Cc: Rob Herring, Stephen Warren, thierry.reding@gmail.com,
Mark Rutland, Alexandre Courbot, linux-gpio@vger.kernel.org,
devicetree@vger.kernel.org, linux-tegra@vger.kernel.org,
linux-kernel@vger.kernel.org, Joe Perches, Jon Hunter
In-Reply-To: <CACRpkdbp8_eR7PLoaX4AJbhcx_tYQjcS5U_hR3EU7b4dar3ckg@mail.gmail.com>
On Thursday 24 November 2016 07:41 PM, Linus Walleij wrote:
> On Wed, Nov 23, 2016 at 12:42 PM, Laxman Dewangan <ldewangan@nvidia.com> wrote:
>
>> Here, we need the regulator handle which can support the other regulator
>> APIs.
>>
>> In some of platforms, we do not use some of the io-pins and on this case, we
>> do not connect the IO rail supply for these pins. So this is like a hardware
>> optional.
>>
>> If the IO pins are used then it need to have the proper regulator handle.
>> Missing regulator handle on DT will be like that IO pads are not used.
> OK I buy that argument, unless Mark (Brown) has comments.
>
BTW, I resolved this in different way in V4 which I sent today, if
regulator_get() succeed for dummy then regulator_get_voltage() failed
and if it failed then assume that it is dummy and just ignore the
further handling based on regulator.
So when we really need the configuration based on voltage, we must
supply the regulator handle.
^ permalink raw reply
* Re: [PATCH RESEND 2/2] gpio: axp209: add pinctrl support
From: Linus Walleij @ 2016-11-24 14:17 UTC (permalink / raw)
To: Quentin Schulz
Cc: Alexandre Courbot, Rob Herring, Mark Rutland, Chen-Yu Tsai,
Maxime Ripard, linux-gpio-u79uwXL29TY76Z2rM5mHXA@public.gmane.org,
devicetree-u79uwXL29TY76Z2rM5mHXA@public.gmane.org,
linux-kernel-u79uwXL29TY76Z2rM5mHXA@public.gmane.org,
linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r@public.gmane.org
In-Reply-To: <20161123141151.25315-3-quentin.schulz-wi1+55ScJUtKEb57/3fJTNBPR1lH4CV8@public.gmane.org>
On Wed, Nov 23, 2016 at 3:11 PM, Quentin Schulz
<quentin.schulz-wi1+55ScJUtKEb57/3fJTNBPR1lH4CV8@public.gmane.org> wrote:
> The GPIOs present in the AXP209 PMIC have multiple functions. They
> typically allow a pin to be used as GPIO input or output and can also be
> used as ADC or regulator for example.[1]
>
> This adds the possibility to use all functions of the GPIOs present in
> the AXP209 PMIC thanks to pinctrl subsystem.
>
> [1] see registers 90H, 92H and 93H at
> http://dl.linux-sunxi.org/AXP/AXP209_Datasheet_v1.0en.pdf
>
> Signed-off-by: Quentin Schulz <quentin.schulz-wi1+55ScJUtKEb57/3fJTNBPR1lH4CV8@public.gmane.org>
I need Maxime's review on this patch.
> .../devicetree/bindings/gpio/gpio-axp209.txt | 28 +-
Also move the bindings to pinctrl/pinctrl-axp209.txt
> drivers/gpio/gpio-axp209.c | 551 ++++++++++++++++++---
Combined drivers should be in drivers/pinctrl/*.
Make a separate patch moving the driver to
drivers/pinctrl/pinctrl-axp209.c (remember -M to git format-patch)
augment Kconfig and Makefile in both subsystems and make
these patches on top of that.
I will deal with cross-merging the result between the GPIO
and pin control trees.
Yours,
Linus Walleij
--
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 v9 3/4] dtc: Plugin and fixup support
From: Phil Elwell @ 2016-11-24 14:14 UTC (permalink / raw)
To: Pantelis Antoniou
Cc: David Gibson, Jon Loeliger, Grant Likely, Frank Rowand,
Rob Herring, Jan Luebbe, Sascha Hauer, Simon Glass, Maxime Ripard,
Thomas Petazzoni, Boris Brezillon, Antoine Tenart, Stephen Boyd,
Devicetree Compiler, devicetree-u79uwXL29TY76Z2rM5mHXA
In-Reply-To: <B341AF38-45C5-4954-B1E4-B89DED923929-OWPKS81ov/FWk0Htik3J/w@public.gmane.org>
On 24/11/2016 13:58, Pantelis Antoniou wrote:
> Hi Phil,
>
>> On Nov 24, 2016, at 15:49 , Phil Elwell <phil-FnsA7b+Nu9XbIbC87yuRow@public.gmane.org> wrote:
>>
>> On 24/11/2016 12:31, Pantelis Antoniou wrote:
>>> This patch enable the generation of symbols & local fixup information
>>> for trees compiled with the -@ (--symbols) option.
>>>
>>> Using this patch labels in the tree and their users emit information
>>> in __symbols__ and __local_fixups__ nodes.
>>>
>>> The __fixups__ node make possible the dynamic resolution of phandle
>>> references which are present in the plugin tree but lie in the
>>> tree that are applying the overlay against.
>>>
>>> While there is a new magic number for dynamic device tree/overlays blobs
>>> it is by default disabled. This is in order to give time for DT blob
>>> methods to be updated.
>>>
>>> Signed-off-by: Pantelis Antoniou <pantelis.antoniou-OWPKS81ov/FWk0Htik3J/w@public.gmane.org>
>>> Signed-off-by: Sascha Hauer <s.hauer-bIcnvbaLZ9MEGnE8C9+IrQ@public.gmane.org>
>>> Signed-off-by: Jan Luebbe <jlu-bIcnvbaLZ9MEGnE8C9+IrQ@public.gmane.org>
>> It's great to see this work about to come to fruition, but I have a
>> reservation about this patch. Like previous versions, this
>> implementation generates __fixups__, __local_fixups__ and __symbols__
>> whenever the "-@" command line parameter is given; without it you get
>> none. In my opinion, this logic causes the DTBs to be unnecessarily
>> large with no obvious benefit.
>>
>> You can divide the compiled outputs from DTC into two categories - fully
>> resolved DTBs (what I would call base DTBs), and overlays. Base DTBs
>> should include __symbols__ to allow overlays to be applied, and it is
>> right that this should be controlled by the "-@" flag, but since base
>> DTBs are fully resolved I think there is no reason to include either
>> __fixups__ or __local_fixups__. Therefore I think both kinds of fixups
>> should only be omitted when the "/plugin/ " directive is used. This was
>> the purpose of one of the patches I provided you with.
>>
> Yes, I’m quite aware of that. There is a reason for generating every
> resolve node for the base tree. It contains information about the
> dependencies of every hardware device due to phandle references.
> We can utilize that to re-order the device probe order to eliminate
> -EPROBE_DEFER cycles upon boot.
>
> It is important we get the core support in and then you can add extra
> switches for every special platform case.
>
> What kind of problems do you have with larger device tree blobs?
> I do carry a hashed phandle patch on my mainline tracking tree which
> should help with larger DTBs.
Early Raspberry Pi DT support used to load the DTBs to 0x100, Although
the ARMv6/7 kernel starts at 0x8000, something (the decompressor?) would
use the space between 0x4000 and the 0x8000, which gave us a practical
limit of 16KB on the DTB size. This used to be sufficient for a base DTB
and a few small overlays, but with the patch all Pi DTBs are over 16KB.
The practical limit was overcome a long time ago, but it made me aware
of the DTB contents, and there are may be some situations where it is
desirable to reduce the footprint as much as possible.
I would have thought that all DTBs already contain enough dependency
information in the form of the phandles themselves. One of the first
things the kernel does is to unflatten the DTB, and that is the obvious
point to resolve the phandles and generate the necessary dependencies.
Can you explain how both __fixups__ and __local_fixups__ aid this
process? Ideally they wouldn't duplicate any information already in the
tree, since then you have to cope with the possibility of malformed DTBs
where the two don't actually match.
Phil
^ permalink raw reply
* Re: [PATCH RESEND 1/2] gpio: axp209: use correct register for GPIO input status
From: Linus Walleij @ 2016-11-24 14:13 UTC (permalink / raw)
To: Quentin Schulz
Cc: Alexandre Courbot, Rob Herring, Mark Rutland, Chen-Yu Tsai,
Maxime Ripard, linux-gpio-u79uwXL29TY76Z2rM5mHXA@public.gmane.org,
devicetree-u79uwXL29TY76Z2rM5mHXA@public.gmane.org,
linux-kernel-u79uwXL29TY76Z2rM5mHXA@public.gmane.org,
linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r@public.gmane.org
In-Reply-To: <20161123141151.25315-2-quentin.schulz-wi1+55ScJUtKEb57/3fJTNBPR1lH4CV8@public.gmane.org>
On Wed, Nov 23, 2016 at 3:11 PM, Quentin Schulz
<quentin.schulz-wi1+55ScJUtKEb57/3fJTNBPR1lH4CV8@public.gmane.org> wrote:
> The GPIO input status was read from control register
> (AXP20X_GPIO[210]_CTRL) instead of status register (AXP20X_GPIO20_SS).
>
> Signed-off-by: Quentin Schulz <quentin.schulz-wi1+55ScJUtKEb57/3fJTNBPR1lH4CV8@public.gmane.org>
Patch applied.
Yours,
Linus Walleij
--
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 V3 2/2] pinctrl: tegra: Add driver to configure voltage and power of io pads
From: Linus Walleij @ 2016-11-24 14:11 UTC (permalink / raw)
To: Laxman Dewangan, Mark Brown
Cc: Rob Herring, Stephen Warren, thierry.reding@gmail.com,
Mark Rutland, Alexandre Courbot, linux-gpio@vger.kernel.org,
devicetree@vger.kernel.org, linux-tegra@vger.kernel.org,
linux-kernel@vger.kernel.org, Joe Perches, Jon Hunter
In-Reply-To: <583580AD.60803@nvidia.com>
On Wed, Nov 23, 2016 at 12:42 PM, Laxman Dewangan <ldewangan@nvidia.com> wrote:
> Here, we need the regulator handle which can support the other regulator
> APIs.
>
> In some of platforms, we do not use some of the io-pins and on this case, we
> do not connect the IO rail supply for these pins. So this is like a hardware
> optional.
>
> If the IO pins are used then it need to have the proper regulator handle.
> Missing regulator handle on DT will be like that IO pads are not used.
OK I buy that argument, unless Mark (Brown) has comments.
Yours,
Linus Walleij
^ permalink raw reply
* Re: [PATCH 2/3] pinctrl: New driver for TI DA8XX/OMAP-L138/AM18XX pinconf
From: Linus Walleij @ 2016-11-24 14:05 UTC (permalink / raw)
To: David Lechner
Cc: Mark Rutland, devicetree@vger.kernel.org, Axel Haslam,
Kevin Hilman, Sekhar Nori, linux-kernel@vger.kernel.org,
linux-gpio@vger.kernel.org, Rob Herring, Alexandre Bailon,
Bartosz Gołaszewski, linux-arm-kernel@lists.infradead.org
In-Reply-To: <1479871767-20160-3-git-send-email-david@lechnology.com>
On Wed, Nov 23, 2016 at 4:29 AM, David Lechner <david@lechnology.com> wrote:
> This adds a new driver for pinconf on TI DA8XX/OMAP-L138/AM18XX. These
> SoCs have a separate controller for controlling pullup/pulldown groups.
>
> Signed-off-by: David Lechner <david@lechnology.com>
Nice and clean driver, resend with the minor fixes pointed out
by Sekhar and I'll merge it.
Yours,
Linus Walleij
^ permalink raw reply
* Re: [PATCH 1/3] devicetree: bindings: pinctrl: Add binding for ti,da850-pupd
From: Linus Walleij @ 2016-11-24 14:04 UTC (permalink / raw)
To: David Lechner
Cc: Rob Herring, Mark Rutland, Sekhar Nori, Kevin Hilman,
linux-gpio@vger.kernel.org, devicetree@vger.kernel.org,
linux-kernel@vger.kernel.org,
linux-arm-kernel@lists.infradead.org, Axel Haslam,
Alexandre Bailon, Bartosz Gołaszewski
In-Reply-To: <1479871767-20160-2-git-send-email-david@lechnology.com>
On Wed, Nov 23, 2016 at 4:29 AM, David Lechner <david@lechnology.com> wrote:
> Device-tree bindings for TI DA8XX/OMAP-L138/AM18XX pullup/pulldown
> pinconf controller.
>
> Signed-off-by: David Lechner <david@lechnology.com>
Looks good to me.
Yours,
Linus Walleij
^ permalink raw reply
* Re: [PATCH v9 3/4] dtc: Plugin and fixup support
From: Pantelis Antoniou @ 2016-11-24 13:58 UTC (permalink / raw)
To: Phil Elwell
Cc: David Gibson, Jon Loeliger, Grant Likely, Frank Rowand,
Rob Herring, Jan Luebbe, Sascha Hauer, Simon Glass, Maxime Ripard,
Thomas Petazzoni, Boris Brezillon, Antoine Tenart, Stephen Boyd,
Devicetree Compiler, devicetree-u79uwXL29TY76Z2rM5mHXA
In-Reply-To: <dab7f38a-89c3-adbc-07a5-8ef8669ded42-FnsA7b+Nu9XbIbC87yuRow@public.gmane.org>
Hi Phil,
> On Nov 24, 2016, at 15:49 , Phil Elwell <phil-FnsA7b+Nu9XbIbC87yuRow@public.gmane.org> wrote:
>
> On 24/11/2016 12:31, Pantelis Antoniou wrote:
>> This patch enable the generation of symbols & local fixup information
>> for trees compiled with the -@ (--symbols) option.
>>
>> Using this patch labels in the tree and their users emit information
>> in __symbols__ and __local_fixups__ nodes.
>>
>> The __fixups__ node make possible the dynamic resolution of phandle
>> references which are present in the plugin tree but lie in the
>> tree that are applying the overlay against.
>>
>> While there is a new magic number for dynamic device tree/overlays blobs
>> it is by default disabled. This is in order to give time for DT blob
>> methods to be updated.
>>
>> Signed-off-by: Pantelis Antoniou <pantelis.antoniou-OWPKS81ov/FWk0Htik3J/w@public.gmane.org>
>> Signed-off-by: Sascha Hauer <s.hauer-bIcnvbaLZ9MEGnE8C9+IrQ@public.gmane.org>
>> Signed-off-by: Jan Luebbe <jlu-bIcnvbaLZ9MEGnE8C9+IrQ@public.gmane.org>
> It's great to see this work about to come to fruition, but I have a
> reservation about this patch. Like previous versions, this
> implementation generates __fixups__, __local_fixups__ and __symbols__
> whenever the "-@" command line parameter is given; without it you get
> none. In my opinion, this logic causes the DTBs to be unnecessarily
> large with no obvious benefit.
>
> You can divide the compiled outputs from DTC into two categories - fully
> resolved DTBs (what I would call base DTBs), and overlays. Base DTBs
> should include __symbols__ to allow overlays to be applied, and it is
> right that this should be controlled by the "-@" flag, but since base
> DTBs are fully resolved I think there is no reason to include either
> __fixups__ or __local_fixups__. Therefore I think both kinds of fixups
> should only be omitted when the "/plugin/ " directive is used. This was
> the purpose of one of the patches I provided you with.
>
Yes, I’m quite aware of that. There is a reason for generating every
resolve node for the base tree. It contains information about the
dependencies of every hardware device due to phandle references.
We can utilize that to re-order the device probe order to eliminate
-EPROBE_DEFER cycles upon boot.
It is important we get the core support in and then you can add extra
switches for every special platform case.
What kind of problems do you have with larger device tree blobs?
I do carry a hashed phandle patch on my mainline tracking tree which
should help with larger DTBs.
> Phil Elwell, Raspberry Pi
Regards
— Pantelis
--
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 v9 3/4] dtc: Plugin and fixup support
From: Phil Elwell @ 2016-11-24 13:49 UTC (permalink / raw)
To: Pantelis Antoniou, David Gibson
Cc: Jon Loeliger, Grant Likely, Frank Rowand, Rob Herring, Jan Luebbe,
Sascha Hauer, Simon Glass, Maxime Ripard, Thomas Petazzoni,
Boris Brezillon, Antoine Tenart, Stephen Boyd,
Devicetree Compiler, devicetree-u79uwXL29TY76Z2rM5mHXA
In-Reply-To: <1479990693-14260-4-git-send-email-pantelis.antoniou-OWPKS81ov/FWk0Htik3J/w@public.gmane.org>
On 24/11/2016 12:31, Pantelis Antoniou wrote:
> This patch enable the generation of symbols & local fixup information
> for trees compiled with the -@ (--symbols) option.
>
> Using this patch labels in the tree and their users emit information
> in __symbols__ and __local_fixups__ nodes.
>
> The __fixups__ node make possible the dynamic resolution of phandle
> references which are present in the plugin tree but lie in the
> tree that are applying the overlay against.
>
> While there is a new magic number for dynamic device tree/overlays blobs
> it is by default disabled. This is in order to give time for DT blob
> methods to be updated.
>
> Signed-off-by: Pantelis Antoniou <pantelis.antoniou-OWPKS81ov/FWk0Htik3J/w@public.gmane.org>
> Signed-off-by: Sascha Hauer <s.hauer-bIcnvbaLZ9MEGnE8C9+IrQ@public.gmane.org>
> Signed-off-by: Jan Luebbe <jlu-bIcnvbaLZ9MEGnE8C9+IrQ@public.gmane.org>
It's great to see this work about to come to fruition, but I have a
reservation about this patch. Like previous versions, this
implementation generates __fixups__, __local_fixups__ and __symbols__
whenever the "-@" command line parameter is given; without it you get
none. In my opinion, this logic causes the DTBs to be unnecessarily
large with no obvious benefit.
You can divide the compiled outputs from DTC into two categories - fully
resolved DTBs (what I would call base DTBs), and overlays. Base DTBs
should include __symbols__ to allow overlays to be applied, and it is
right that this should be controlled by the "-@" flag, but since base
DTBs are fully resolved I think there is no reason to include either
__fixups__ or __local_fixups__. Therefore I think both kinds of fixups
should only be omitted when the "/plugin/ " directive is used. This was
the purpose of one of the patches I provided you with.
Phil Elwell, Raspberry Pi
^ permalink raw reply
* Re: [PATCH 7/10] mmc: sdhci-xenon: Add support to PHYs of Marvell Xenon SDHC
From: Ziji Hu @ 2016-11-24 13:34 UTC (permalink / raw)
To: Ulf Hansson, Gregory CLEMENT
Cc: Adrian Hunter, linux-mmc-u79uwXL29TY76Z2rM5mHXA@public.gmane.org,
Jason Cooper, Andrew Lunn, Sebastian Hesselbarth, Rob Herring,
devicetree-u79uwXL29TY76Z2rM5mHXA@public.gmane.org,
Thomas Petazzoni,
linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r@public.gmane.org,
Jimmy Xu, Jisheng Zhang, Nadav Haklai, Ryan Gao, Doug Jones,
Victor Gu, Wei(SOCP) Liu, Wilson Ding, Romain Perier
In-Reply-To: <CAPDyKFpkcoVMKbVOwjX1WDyNgc1vvUX60D6XRX6=YHGvkvHvnA-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>
Hi Ulf,
Thanks a lot for the review.
On 2016/11/24 19:37, Ulf Hansson wrote:
> On 31 October 2016 at 12:09, Gregory CLEMENT
> <gregory.clement-wi1+55ScJUtKEb57/3fJTNBPR1lH4CV8@public.gmane.org> wrote:
>> From: Ziji Hu <huziji-eYqpPyKDWXRBDgjK7y7TUQ@public.gmane.org>
>>
>> Marvell Xenon eMMC/SD/SDIO Host Controller contains PHY.
>> Three types of PHYs are supported.
>>
>> Add support to multiple types of PHYs init and configuration.
>> Add register definitions of PHYs.
>>
>> Signed-off-by: Hu Ziji <huziji-eYqpPyKDWXRBDgjK7y7TUQ@public.gmane.org>
>> Signed-off-by: Gregory CLEMENT <gregory.clement-wi1+55ScJUtKEb57/3fJTNBPR1lH4CV8@public.gmane.org>
>> ---
>> MAINTAINERS | 2 +-
>> drivers/mmc/host/Makefile | 2 +-
>> drivers/mmc/host/sdhci-xenon-phy.c | 1181 +++++++++++++++++++++++++++++-
>> drivers/mmc/host/sdhci-xenon-phy.h | 157 ++++-
>> drivers/mmc/host/sdhci-xenon.c | 4 +-
>> drivers/mmc/host/sdhci-xenon.h | 17 +-
>> 6 files changed, 1361 insertions(+), 2 deletions(-)
>> create mode 100644 drivers/mmc/host/sdhci-xenon-phy.c
>> create mode 100644 drivers/mmc/host/sdhci-xenon-phy.h
>
> Can you please consider to split this up somehow!? It would make it
> easier to review...
>
Sure. I will try to split them into smaller pieces.
> Anyway, allow me to provide some initial feedback, particularly around
> those things that Adrian and you requested for my input.
>
> [...]
>
>>
>> +
>> +static int __xenon_emmc_delay_adj_test(struct mmc_card *card)
>> +{
>> + int err;
>> + u8 *ext_csd = NULL;
>> +
>> + err = mmc_get_ext_csd(card, &ext_csd);
>> + kfree(ext_csd);
>
> Why do you read the ext csd here?
>
I would like to simply introduce the PHY setting of our SDHC.
The target of the PHY setting is to achieve a perfect sampling
point for transfers, during card initialization.
For HS200/HS400/SDR104 whose SDCLK is more than 50MHz, SDHC HW
will search for this sampling point with DLL's help.
For other speed mode whose SDLCK is less than or equals to 50MHz,
SW has to scan the PHY delay line to find out this perfect sampling
point. Our driver sends a command to verify a sampling point
in current environment.
As result, our SDHC driver has to implement the functionality to
send commands and check the results, in host layer.
If directly calling mmc_wait_for_cmd() is improper, could you please
give us some suggestions?
For eMMC, CMD8 is used to test current sampling point set in PHY.
>> +
>> + return err;
>> +}
>> +
>> +static int __xenon_sdio_delay_adj_test(struct mmc_card *card)
>> +{
>> + struct mmc_command cmd = {0};
>> + int err;
>> +
>> + cmd.opcode = SD_IO_RW_DIRECT;
>> + cmd.flags = MMC_RSP_R5 | MMC_CMD_AC;
>> +
>> + err = mmc_wait_for_cmd(card->host, &cmd, 0);
>> + if (err)
>> + return err;
>> +
>> + if (cmd.resp[0] & R5_ERROR)
>> + return -EIO;
>> + if (cmd.resp[0] & R5_FUNCTION_NUMBER)
>> + return -EINVAL;
>> + if (cmd.resp[0] & R5_OUT_OF_RANGE)
>> + return -ERANGE;
>> + return 0;
>
> No thanks! MMC/SD/SDIO protocol code belongs in the core.
>
For SDIO, SD_IO_RW_DIRECT command is sent to test current sampling point
in PHY.
Please help provide some suggestion to implement the command transfer.
>> +}
>> +
>> +static int __xenon_sd_delay_adj_test(struct mmc_card *card)
>> +{
>> + struct mmc_command cmd = {0};
>> + int err;
>> +
>> + cmd.opcode = MMC_SEND_STATUS;
>> + cmd.arg = card->rca << 16;
>> + cmd.flags = MMC_RSP_R1 | MMC_CMD_AC;
>> +
>> + err = mmc_wait_for_cmd(card->host, &cmd, 0);
>> + return err;
>
> No thanks! MMC/SD/SDIO protocol code belongs in the core.
>
>> +}
>> +
>
> [...]
>
>> +int xenon_phy_adj(struct sdhci_host *host, struct mmc_ios *ios)
>> +{
>> + struct mmc_host *mmc = host->mmc;
>> + struct mmc_card *card;
>> + int ret = 0;
>> + struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
>> + struct sdhci_xenon_priv *priv = sdhci_pltfm_priv(pltfm_host);
>> +
>> + if (!host->clock) {
>> + priv->clock = 0;
>> + return 0;
>> + }
>> +
>> + /*
>> + * The timing, frequency or bus width is changed,
>> + * better to set eMMC PHY based on current setting
>> + * and adjust Xenon SDHC delay.
>> + */
>> + if ((host->clock == priv->clock) &&
>> + (ios->bus_width == priv->bus_width) &&
>> + (ios->timing == priv->timing))
>> + return 0;
>> +
>> + xenon_phy_set(host, ios->timing);
>> +
>> + /* Update the record */
>> + priv->bus_width = ios->bus_width;
>> + /* Temp stage from HS200 to HS400 */
>> + if (((priv->timing == MMC_TIMING_MMC_HS200) &&
>> + (ios->timing == MMC_TIMING_MMC_HS)) ||
>> + ((ios->timing == MMC_TIMING_MMC_HS) &&
>> + (priv->clock > host->clock))) {
>> + priv->timing = ios->timing;
>> + priv->clock = host->clock;
>> + return 0;
>> + }
>> + /*
>> + * Skip temp stages from HS400 t0 HS200:
>> + * from 200MHz to 52MHz in HS400
>> + * from HS400 to HS DDR in 52MHz
>> + * from HS DDR to HS in 52MHz
>> + * from HS to HS200 in 52MHz
>> + */
>> + if (((priv->timing == MMC_TIMING_MMC_HS400) &&
>> + ((host->clock == MMC_HIGH_52_MAX_DTR) ||
>> + (ios->timing == MMC_TIMING_MMC_DDR52))) ||
>> + ((priv->timing == MMC_TIMING_MMC_DDR52) &&
>> + (ios->timing == MMC_TIMING_MMC_HS)) ||
>> + ((ios->timing == MMC_TIMING_MMC_HS200) &&
>> + (ios->clock == MMC_HIGH_52_MAX_DTR))) {
>> + priv->timing = ios->timing;
>> + priv->clock = host->clock;
>> + return 0;
>> + }
>> + priv->timing = ios->timing;
>> + priv->clock = host->clock;
>> +
>> + /* Legacy mode is a special case */
>> + if (ios->timing == MMC_TIMING_LEGACY)
>> + return 0;
>> +
>> + if (mmc->card)
>> + card = mmc->card;
>> + else
>> + /*
>> + * Only valid during initialization
>> + * before mmc->card is set
>> + */
>> + card = priv->card_candidate;
>> + if (unlikely(!card)) {
>> + dev_warn(mmc_dev(mmc), "card is not present\n");
>> + return -EINVAL;
>> + }
>
> That your host need to hold a copy of the card pointer, tells me that
> something is not really correct.
>
> I might be wrong, if this turns out to be a special case, but I doubt
> it. Although, if it *is* a special such case, we shall most likely try
> to extend the the mmc core layer instead of adding all these hacks in
> your host driver.
>
This card pointer copies the temporary structure mmc_card
used in mmc_init_card(), mmc_sd_init_card() and mmc_sdio_init_card().
Since we call mmc_wait_for_cmd() to send test commands, we need a copy
of that temporary mmc_card here in our host driver.
During PHY setting in card initialization, mmc_host->card is not updated
yet with that temporary mmc_card. Thus we are not able to directly use
mmc_host->card. Instead, this card pointer is introduced to enable
mmc_wait_for_cmd().
If we can improve our host driver to send test commands without mmc_card,
this card pointer can be removed.
Could you please share your opinion please?
> [...]
>
> Another suggestion of a general improvement; could you perhaps try to
> add some brief information about what goes on in function headers.
> Perhaps that could help to more easily understand things.
>
Sorry about any inconvenience. Most of the functions here are our host specific.
It is really difficult to understand them without proper comment.
I will add more information.
Thank you.
Best regards,
Hu Ziji
> Kind regards
> Uffe
>
--
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 6/10] mmc: sdhci-xenon: Add Marvell Xenon SDHC core functionality
From: Ulf Hansson @ 2016-11-24 13:34 UTC (permalink / raw)
To: Ziji Hu, Adrian Hunter
Cc: Gregory CLEMENT, linux-mmc@vger.kernel.org, Jason Cooper,
Andrew Lunn, Sebastian Hesselbarth, Rob Herring,
devicetree@vger.kernel.org, Thomas Petazzoni,
linux-arm-kernel@lists.infradead.org, Jimmy Xu, Jisheng Zhang,
Nadav Haklai, Ryan Gao, Doug Jones, Victor Gu, Wei(SOCP) Liu,
Wilson Ding, Romain Perier
In-Reply-To: <dd230463-04f6-df31-7056-1a185eb6cfc7@marvell.com>
On 24 November 2016 at 13:41, Ziji Hu <huziji@marvell.com> wrote:
> Hi Ulf,
>
> On 2016/11/24 18:43, Ulf Hansson wrote:
>> On 31 October 2016 at 12:09, Gregory CLEMENT
>> <gregory.clement@free-electrons.com> wrote:
>>> From: Ziji Hu <huziji@marvell.com>
>>>
> <snip>
>>> +static int xenon_emmc_signal_voltage_switch(struct mmc_host *mmc,
>>> + struct mmc_ios *ios)
>>> +{
>>> + unsigned char voltage = ios->signal_voltage;
>>> +
>>> + if ((voltage == MMC_SIGNAL_VOLTAGE_330) ||
>>> + (voltage == MMC_SIGNAL_VOLTAGE_180))
>>> + return __emmc_signal_voltage_switch(mmc, voltage);
>>> +
>>> + dev_err(mmc_dev(mmc), "Unsupported signal voltage: %d\n",
>>> + voltage);
>>> + return -EINVAL;
>>
>> This wrapper function seems unnessarry. It only adds a dev_err(), so
>> then might as well do that in __emmc_signal_voltage_switch().
>>
> Sure. Will merge it back to __emmc_signal_voltage_switch().
>
>>> +}
>>> +
>>> +static int xenon_start_signal_voltage_switch(struct mmc_host *mmc,
>>> + struct mmc_ios *ios)
>>> +{
>>> + struct sdhci_host *host = mmc_priv(mmc);
>>> + struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
>>> + struct sdhci_xenon_priv *priv = sdhci_pltfm_priv(pltfm_host);
>>> +
>>> + /*
>>> + * Before SD/SDIO set signal voltage, SD bus clock should be
>>> + * disabled. However, sdhci_set_clock will also disable the Internal
>>> + * clock in mmc_set_signal_voltage().
>>
>> If that's the case then that is wrong in the generic sdhci code.
>> What's the reason why it can't be fixed there instead of having this
>> workaround?
>>
> In my very own opinion, SD Spec doesn't specify whether SDCLK should be
> enabled or not during power setting.
> Enabling SDCLK might be a special condition only required by our SDHC.
> I try to avoid breaking other vendors' SDHC functionality
> if their SDHCs require SDCLK disabled.
> Thus I prefer to keep it inside our SDHC driver.
I let Adrian comment on this.
For sure we should avoid breaking other sdhci variant, but on the
other hand *if* the generic code is wrong we should fix it!
>
>>> + * If Internal clock is disabled, the 3.3V/1.8V bit can not be updated.
>>> + * Thus here manually enable internal clock.
>>> + *
>>> + * After switch completes, it is unnecessary to disable internal clock,
>>> + * since keeping internal clock active obeys SD spec.
>>> + */
>>> + enable_xenon_internal_clk(host);
>>> +
>>> + if (priv->emmc_slot)
>>> + return xenon_emmc_signal_voltage_switch(mmc, ios);
>>> +
>>> + return sdhci_start_signal_voltage_switch(mmc, ios);
>>> +}
>>> +
>>> +/*
>>> + * After determining which slot is used for SDIO,
>>> + * some additional task is required.
>>> + */
>>> +static void xenon_init_card(struct mmc_host *mmc, struct mmc_card *card)
>>> +{
>>> + struct sdhci_host *host = mmc_priv(mmc);
>>> + u32 reg;
>>> + u8 slot_idx;
>>> + struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
>>> + struct sdhci_xenon_priv *priv = sdhci_pltfm_priv(pltfm_host);
>>> +
>>> + /* Link the card for delay adjustment */
>>> + priv->card_candidate = card;
>>> + /* Set tuning functionality of this slot */
>>> + xenon_slot_tuning_setup(host);
>>
>> This looks weird. I assume this can be done as a part of the regular
>> tuning seqeunce!?
>>
> It is our SDHC specific preparation prior to tuning, rather than a
> standard step in spec.
> Thus I leave it inside our driver.
My point is that this isn't the purpose of ->init_card(). thus you are
abusing it.
Try to make it work in another way, please. I think you can.
>
>>> +
>>> + slot_idx = priv->slot_idx;
>>> + if (!mmc_card_sdio(card)) {
>>> + /* Clear SDIO Card Inserted indication */
>>
>> Why do you need this?
>>
>> If you need to reset this, I think it's better to do it from
>> ->set_ios() at MMC_POWER_OFF.
>>
> This field indicates SDIO card and controls async interrupt feature
> of SDIO in our SDHC.
> This async interrupt feature is enabled when SDIO card is inserted.
> It should be disabled if SD card is inserted instead.
What do you mean by SDIO async interupts? Are you talking about SDIO
irqs on DAT1 line?
Those is supposed to be enabled when someone explicitly requests them,
not when the card is inserted.
In other words when an SDIO func driver have called sdio_claim_irq().
Moreover, we have ->enable_sdio_irq() ops that deals with this.
[...]
>>> +
>>> + /*
>>> + * Xenon Specific property:
>>> + * emmc: explicitly indicate whether this slot is for eMMC
>>> + * slotno: the index of slot. Refer to SDHC_SYS_CFG_INFO register
>>> + * tun-count: the interval between re-tuning
>>> + * PHY type: "sdhc phy", "emmc phy 5.0" or "emmc phy 5.1"
>>> + */
>>> + if (of_property_read_bool(np, "marvell,xenon-emmc"))
>>> + priv->emmc_slot = true;
>>
>> So, you need this because of the eMMC voltage switch behaviour, right?
>>
>> Then I would rather like to describe this a generic DT bindings for
>> the eMMC voltage level support. There have acutally been some earlier
>> discussions for this, but we haven't yet made some changes.
>>
>> I think what is missing is a mmc-ddr-3_3v DT binding, which when set,
>> allows the host driver to accept I/O voltage switches to 3.3V. If not
>> supported the ->start_signal_voltage_switch() ops may return -EINVAL.
>> This would inform the mmc core to move on to the next supported
>> voltage level. There might be some minor additional changes to the mmc
>> card initialization sequence, but those should be simple.
>>
>> I can help out to look into this, unless you want to do it yourself of course!?
>>
> Yes. One of the reasons is to provide eMMC specific voltage setting.
> But in my very own opinion, it should be irrelevant to voltage level.
> The eMMC voltage setting on our SDHC is different from SD/SDIO voltage switch.
> It will become more complex with different SOC implementation details.
Got it. Although I think we can cope with that fine just by using the
different SD/eMMC speed modes settings defined in DT (or from the
SDHCI caps register)
> Unfortunately, MMC driver cannot determine the card type yet when eMMC voltage
> setting should be executed.
> Thus an flag is required here to tell driver to execute eMMC voltage setting.
>
> Besides, additional eMMC specific settings might be implemented in future, besides
> voltage setting. Most of them should be completed before MMC driver recognizes the
> card type. Thus I have to keep this flag to indicate current SDHC is for eMMC.
I doubt you will need a generic "eMMC" flag, but let's see when we go forward.
Currently it's clear you don't need such a flag, so I will submit a
change adding a DT binding for "mmc-ddr-3_3v" then we can take it from
there, to see if it suits your needs.
[...]
Kind regards
Uffe
^ permalink raw reply
* Re: [PATCH 0/2] OF phandle nexus support + GPIO nexus
From: Pantelis Antoniou @ 2016-11-24 12:47 UTC (permalink / raw)
To: Stephen Boyd
Cc: devicetree, Linus Walleij, linux-kernel, linux-gpio, Rob Herring,
Mark Brown, Frank Rowand, linux-arm-kernel
In-Reply-To: <20161124102529.20212-1-stephen.boyd@linaro.org>
Hi Stephen,
> On Nov 24, 2016, at 12:25 , Stephen Boyd <stephen.boyd@linaro.org> wrote:
>
> This is one small chunk of work related to DT overlays for expansion
> boards. It would be good to have a way to expose #<list>-cells types of
> providers through a connector in a standard way. So we introduce a way
> to make "nexus" nodes for these types of properties to remap the consumer
> number space to the other side of the connector's number space. It's
> basically a copy of the interrupt nexus implementation, but without
> the address space matching design and interrupt-parent walking.
>
> The first patch implements a generic method to do this, and the second patch
> adds a unit test for it. The third patch is more of an example than anything
> else. It shows how we would modify frameworks to use the new API.
>
Excellent. It was about time this happened.
> Stephen Boyd (3):
> of: Support parsing phandle argument lists through a nexus node
> of: unittest: Add phandle remapping test
> gpio: Support gpio nexus dt bindings
>
> drivers/gpio/gpiolib-of.c | 5 +-
> drivers/of/base.c | 146 ++++++++++++++++++++++++++++
> drivers/of/unittest-data/testcases.dts | 11 +++
> drivers/of/unittest-data/tests-phandle.dtsi | 24 +++++
> drivers/of/unittest.c | 124 +++++++++++++++++++++++
> include/linux/of.h | 14 +++
> 6 files changed, 322 insertions(+), 2 deletions(-)
>
> --
> 2.10.0.297.gf6727b0
>
Comments inline…
Regards
— Pantelis
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply
* Re: [PATCH v3 4/7] clk: qcom: ipq4019: Added all the frequencies for apps cpu
From: Abhishek Sahu @ 2016-11-24 12:46 UTC (permalink / raw)
To: Stephen Boyd
Cc: andy.gross, david.brown, robh+dt, pawel.moll, mark.rutland,
ijc+devicetree, mturquette, galak, pradeepb, mmcclint, varada,
sricharan, architt, ntelkar, linux-arm-msm, linux-soc, linux-clk,
linux-kernel, devicetree
In-Reply-To: <20161102012450.GD16026@codeaurora.org>
On 2016-11-02 06:54, Stephen Boyd wrote:
> On 09/21, Abhishek Sahu wrote:
>> The APPS CPU clock does not contain all the frequencies in its
>> frequency table so this patch adds the same.
>>
>> Signed-off-by: Abhishek Sahu <absahu@codeaurora.org>
>> ---
>> drivers/clk/qcom/gcc-ipq4019.c | 12 +++++++++++-
>> 1 file changed, 11 insertions(+), 1 deletion(-)
>>
>> diff --git a/drivers/clk/qcom/gcc-ipq4019.c
>> b/drivers/clk/qcom/gcc-ipq4019.c
>> index 211c68c..160e0cf 100644
>> --- a/drivers/clk/qcom/gcc-ipq4019.c
>> +++ b/drivers/clk/qcom/gcc-ipq4019.c
>> @@ -565,10 +565,20 @@ static struct clk_rcg2 sdcc1_apps_clk_src = {
>> };
>>
>> static const struct freq_tbl ftbl_gcc_apps_clk[] = {
>> - F(48000000, P_XO, 1, 0, 0),
>> + F(48000000, P_XO, 1, 0, 0),
>> F(200000000, P_FEPLL200, 1, 0, 0),
>> + F(380000000, P_DDRPLLAPSS, 1, 0, 0),
>> + F(409000000, P_DDRPLLAPSS, 1, 0, 0),
>> + F(444000000, P_DDRPLLAPSS, 1, 0, 0),
>> + F(484000000, P_DDRPLLAPSS, 1, 0, 0),
>> F(500000000, P_FEPLL500, 1, 0, 0),
>> + F(507000000, P_DDRPLLAPSS, 1, 0, 0),
>> + F(532000000, P_DDRPLLAPSS, 1, 0, 0),
>> + F(560000000, P_DDRPLLAPSS, 1, 0, 0),
>> + F(592000000, P_DDRPLLAPSS, 1, 0, 0),
>> F(626000000, P_DDRPLLAPSS, 1, 0, 0),
>> + F(666000000, P_DDRPLLAPSS, 1, 0, 0),
>> + F(710000000, P_DDRPLLAPSS, 1, 0, 0),
>> { }
>> };
>
> Can't we have the determine_rate callback know the speeds of the
> "fixed" PLLs and use those first if the rate hits exactly? And
> then if that doesn't happen go try ddrpllapps and set the rate on
> it? I'm hoping we can get rid of this frequency table.
This clock is being registered with QCOM clk_rcg2 operations which
already has determine_rate callback based on this frequency table.
Currently all the frequencies are being generated without HID
divider but in future, we can have some frequency which will use
dividers also.
--
Abhishek Sahu
^ permalink raw reply
* Re: [PATCH 6/10] mmc: sdhci-xenon: Add Marvell Xenon SDHC core functionality
From: Ziji Hu @ 2016-11-24 12:41 UTC (permalink / raw)
To: Ulf Hansson, Gregory CLEMENT
Cc: Adrian Hunter, linux-mmc@vger.kernel.org, Jason Cooper,
Andrew Lunn, Sebastian Hesselbarth, Rob Herring,
devicetree@vger.kernel.org, Thomas Petazzoni,
linux-arm-kernel@lists.infradead.org, Jimmy Xu, Jisheng Zhang,
Nadav Haklai, Ryan Gao, Doug Jones, Victor Gu, Wei(SOCP) Liu,
Wilson Ding, Romain Perier
In-Reply-To: <CAPDyKFpqPSqiEi=0UW5LoZmy+y-KHm9nbcGKBSy3RzchdLU9cA@mail.gmail.com>
Hi Ulf,
On 2016/11/24 18:43, Ulf Hansson wrote:
> On 31 October 2016 at 12:09, Gregory CLEMENT
> <gregory.clement@free-electrons.com> wrote:
>> From: Ziji Hu <huziji@marvell.com>
>>
<snip>
>> +static int xenon_emmc_signal_voltage_switch(struct mmc_host *mmc,
>> + struct mmc_ios *ios)
>> +{
>> + unsigned char voltage = ios->signal_voltage;
>> +
>> + if ((voltage == MMC_SIGNAL_VOLTAGE_330) ||
>> + (voltage == MMC_SIGNAL_VOLTAGE_180))
>> + return __emmc_signal_voltage_switch(mmc, voltage);
>> +
>> + dev_err(mmc_dev(mmc), "Unsupported signal voltage: %d\n",
>> + voltage);
>> + return -EINVAL;
>
> This wrapper function seems unnessarry. It only adds a dev_err(), so
> then might as well do that in __emmc_signal_voltage_switch().
>
Sure. Will merge it back to __emmc_signal_voltage_switch().
>> +}
>> +
>> +static int xenon_start_signal_voltage_switch(struct mmc_host *mmc,
>> + struct mmc_ios *ios)
>> +{
>> + struct sdhci_host *host = mmc_priv(mmc);
>> + struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
>> + struct sdhci_xenon_priv *priv = sdhci_pltfm_priv(pltfm_host);
>> +
>> + /*
>> + * Before SD/SDIO set signal voltage, SD bus clock should be
>> + * disabled. However, sdhci_set_clock will also disable the Internal
>> + * clock in mmc_set_signal_voltage().
>
> If that's the case then that is wrong in the generic sdhci code.
> What's the reason why it can't be fixed there instead of having this
> workaround?
>
In my very own opinion, SD Spec doesn't specify whether SDCLK should be
enabled or not during power setting.
Enabling SDCLK might be a special condition only required by our SDHC.
I try to avoid breaking other vendors' SDHC functionality
if their SDHCs require SDCLK disabled.
Thus I prefer to keep it inside our SDHC driver.
>> + * If Internal clock is disabled, the 3.3V/1.8V bit can not be updated.
>> + * Thus here manually enable internal clock.
>> + *
>> + * After switch completes, it is unnecessary to disable internal clock,
>> + * since keeping internal clock active obeys SD spec.
>> + */
>> + enable_xenon_internal_clk(host);
>> +
>> + if (priv->emmc_slot)
>> + return xenon_emmc_signal_voltage_switch(mmc, ios);
>> +
>> + return sdhci_start_signal_voltage_switch(mmc, ios);
>> +}
>> +
>> +/*
>> + * After determining which slot is used for SDIO,
>> + * some additional task is required.
>> + */
>> +static void xenon_init_card(struct mmc_host *mmc, struct mmc_card *card)
>> +{
>> + struct sdhci_host *host = mmc_priv(mmc);
>> + u32 reg;
>> + u8 slot_idx;
>> + struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
>> + struct sdhci_xenon_priv *priv = sdhci_pltfm_priv(pltfm_host);
>> +
>> + /* Link the card for delay adjustment */
>> + priv->card_candidate = card;
>> + /* Set tuning functionality of this slot */
>> + xenon_slot_tuning_setup(host);
>
> This looks weird. I assume this can be done as a part of the regular
> tuning seqeunce!?
>
It is our SDHC specific preparation prior to tuning, rather than a
standard step in spec.
Thus I leave it inside our driver.
>> +
>> + slot_idx = priv->slot_idx;
>> + if (!mmc_card_sdio(card)) {
>> + /* Clear SDIO Card Inserted indication */
>
> Why do you need this?
>
> If you need to reset this, I think it's better to do it from
> ->set_ios() at MMC_POWER_OFF.
>
This field indicates SDIO card and controls async interrupt feature
of SDIO in our SDHC.
This async interrupt feature is enabled when SDIO card is inserted.
It should be disabled if SD card is inserted instead.
>> + reg = sdhci_readl(host, SDHC_SYS_CFG_INFO);
>> + reg &= ~(1 << (slot_idx + SLOT_TYPE_SDIO_SHIFT));
>> + sdhci_writel(host, reg, SDHC_SYS_CFG_INFO);
>> +
>> + if (mmc_card_mmc(card)) {
>> + mmc->caps |= MMC_CAP_NONREMOVABLE;
>> + if (!(host->quirks2 & SDHCI_QUIRK2_NO_1_8_V))
>> + mmc->caps |= MMC_CAP_1_8V_DDR;
>> + /*
>> + * Force to clear BUS_TEST to
>> + * skip bus_test_pre and bus_test_post
>> + */
>> + mmc->caps &= ~MMC_CAP_BUS_WIDTH_TEST;
>> + mmc->caps2 |= MMC_CAP2_HC_ERASE_SZ |
>> + MMC_CAP2_PACKED_CMD;
>> + if (mmc->caps & MMC_CAP_8_BIT_DATA)
>> + mmc->caps2 |= MMC_CAP2_HS400_1_8V;
>
> Most of this can be specified as DT configurations. Please use that instead.
>
> More importantly, please don't use the ->init_card() ops to assign
> host caps. If not DT, please do it from ->probe().
>
Sure. Will try to use DT instead.
>> + }
>> + } else {
>> + /*
>> + * Set SDIO Card Inserted indication
>> + * to inform that the current slot is for SDIO
>> + */
>> + reg = sdhci_readl(host, SDHC_SYS_CFG_INFO);
>> + reg |= (1 << (slot_idx + SLOT_TYPE_SDIO_SHIFT));
>> + sdhci_writel(host, reg, SDHC_SYS_CFG_INFO);
>
> So this makes sence to have in the ->init_card() ops. The rest above, not.
>
>> + }
>> +}
>> +
>> +static int xenon_execute_tuning(struct mmc_host *mmc, u32 opcode)
>> +{
>> + struct sdhci_host *host = mmc_priv(mmc);
>> +
>> + if (host->timing == MMC_TIMING_UHS_DDR50)
>> + return 0;
>> +
>> + return sdhci_execute_tuning(mmc, opcode);
>> +}
>> +
>> +static void xenon_replace_mmc_host_ops(struct sdhci_host *host)
>> +{
>> + host->mmc_host_ops.set_ios = xenon_set_ios;
>> + host->mmc_host_ops.start_signal_voltage_switch =
>> + xenon_start_signal_voltage_switch;
>> + host->mmc_host_ops.init_card = xenon_init_card;
>> + host->mmc_host_ops.execute_tuning = xenon_execute_tuning;
>> +}
>> +
>> +static int xenon_probe_dt(struct platform_device *pdev)
>> +{
>> + struct device_node *np = pdev->dev.of_node;
>> + struct sdhci_host *host = platform_get_drvdata(pdev);
>> + struct mmc_host *mmc = host->mmc;
>> + struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
>> + struct sdhci_xenon_priv *priv = sdhci_pltfm_priv(pltfm_host);
>> + int err;
>> + u32 slot_idx, nr_slot;
>> + u32 tuning_count;
>> + u32 reg;
>> +
>> + /* Standard MMC property */
>> + err = mmc_of_parse(mmc);
>> + if (err)
>> + return err;
>> +
>> + /* Standard SDHCI property */
>> + sdhci_get_of_property(pdev);
>> +
>> + /*
>> + * Xenon Specific property:
>> + * emmc: explicitly indicate whether this slot is for eMMC
>> + * slotno: the index of slot. Refer to SDHC_SYS_CFG_INFO register
>> + * tun-count: the interval between re-tuning
>> + * PHY type: "sdhc phy", "emmc phy 5.0" or "emmc phy 5.1"
>> + */
>> + if (of_property_read_bool(np, "marvell,xenon-emmc"))
>> + priv->emmc_slot = true;
>
> So, you need this because of the eMMC voltage switch behaviour, right?
>
> Then I would rather like to describe this a generic DT bindings for
> the eMMC voltage level support. There have acutally been some earlier
> discussions for this, but we haven't yet made some changes.
>
> I think what is missing is a mmc-ddr-3_3v DT binding, which when set,
> allows the host driver to accept I/O voltage switches to 3.3V. If not
> supported the ->start_signal_voltage_switch() ops may return -EINVAL.
> This would inform the mmc core to move on to the next supported
> voltage level. There might be some minor additional changes to the mmc
> card initialization sequence, but those should be simple.
>
> I can help out to look into this, unless you want to do it yourself of course!?
>
Yes. One of the reasons is to provide eMMC specific voltage setting.
But in my very own opinion, it should be irrelevant to voltage level.
The eMMC voltage setting on our SDHC is different from SD/SDIO voltage switch.
It will become more complex with different SOC implementation details.
Unfortunately, MMC driver cannot determine the card type yet when eMMC voltage
setting should be executed.
Thus an flag is required here to tell driver to execute eMMC voltage setting.
Besides, additional eMMC specific settings might be implemented in future, besides
voltage setting. Most of them should be completed before MMC driver recognizes the
card type. Thus I have to keep this flag to indicate current SDHC is for eMMC.
>> + else
>> + priv->emmc_slot = false;
>> +
>> + if (!of_property_read_u32(np, "marvell,xenon-slotno", &slot_idx)) {
>> + nr_slot = sdhci_readl(host, SDHC_SYS_CFG_INFO);
>> + nr_slot &= NR_SUPPORTED_SLOT_MASK;
>> + if (unlikely(slot_idx > nr_slot)) {
>> + dev_err(mmc_dev(mmc), "Slot Index %d exceeds Number of slots %d\n",
>> + slot_idx, nr_slot);
>> + return -EINVAL;
>> + }
>> + } else {
>> + priv->slot_idx = 0x0;
>> + }
>> +
>> + if (!of_property_read_u32(np, "marvell,xenon-tun-count",
>> + &tuning_count)) {
>> + if (unlikely(tuning_count >= TMR_RETUN_NO_PRESENT)) {
>> + dev_err(mmc_dev(mmc), "Wrong Re-tuning Count. Set default value %d\n",
>> + DEF_TUNING_COUNT);
>> + tuning_count = DEF_TUNING_COUNT;
>> + }
>> + } else {
>> + priv->tuning_count = DEF_TUNING_COUNT;
>> + }
>
> To make the code a bit easier...
>
> Maybe set "priv->tuning_count = DEF_TUNING_COUNT" before the "if", and
> instead have the of_property_read_u32() to update the value when set.
>
Yes. You are correct.
>> +
>> + if (of_property_read_bool(np, "marvell,xenon-mask-conflict-err")) {
>> + reg = sdhci_readl(host, SDHC_SYS_EXT_OP_CTRL);
>> + reg |= MASK_CMD_CONFLICT_ERROR;
>> + sdhci_writel(host, reg, SDHC_SYS_EXT_OP_CTRL);
>> + }
>> +
>> + return err;
>> +}
>> +
>> +static int xenon_slot_probe(struct sdhci_host *host)
>> +{
>> + struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
>> + struct sdhci_xenon_priv *priv = sdhci_pltfm_priv(pltfm_host);
>> + u8 slot_idx = priv->slot_idx;
>> +
>> + /* Enable slot */
>> + xenon_enable_slot(host, slot_idx);
>> +
>> + /* Enable ACG */
>> + xenon_set_acg(host, true);
>> +
>> + /* Enable Parallel Transfer Mode */
>> + xenon_enable_slot_parallel_tran(host, slot_idx);
>> +
>> + priv->timing = MMC_TIMING_FAKE;
>> + priv->clock = 0;
>
> What are these used for?
>
During card initialization, our SDHC PHY setting depends on current
timing and SDCLK frequency.
priv->timing and priv->clock will be used in PHY setting later.
It can be considered as a clean-up.
Anyway, it does look ugly. I will improve them after our PHY setting
passes your review.
>> +
>> + return 0;
>> +}
>> +
>> +static void xenon_slot_remove(struct sdhci_host *host)
>> +{
>> + struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
>> + struct sdhci_xenon_priv *priv = sdhci_pltfm_priv(pltfm_host);
>> + u8 slot_idx = priv->slot_idx;
>> +
>> + /* disable slot */
>> + xenon_disable_slot(host, slot_idx);
>> +}
>> +
>> +static int sdhci_xenon_probe(struct platform_device *pdev)
>> +{
>> + struct sdhci_pltfm_host *pltfm_host;
>> + struct sdhci_host *host;
>> + struct clk *clk, *axi_clk;
>> + struct sdhci_xenon_priv *priv;
>> + int err;
>> +
>> + host = sdhci_pltfm_init(pdev, &sdhci_xenon_pdata,
>> + sizeof(struct sdhci_xenon_priv));
>> + if (IS_ERR(host))
>> + return PTR_ERR(host);
>> +
>> + pltfm_host = sdhci_priv(host);
>> + priv = sdhci_pltfm_priv(pltfm_host);
>> +
>> + xenon_set_acg(host, false);
>> +
>> + /*
>> + * Link Xenon specific mmc_host_ops function,
>> + * to replace standard ones in sdhci_ops.
>> + */
>> + xenon_replace_mmc_host_ops(host);
>> +
>> + clk = devm_clk_get(&pdev->dev, "core");
>> + if (IS_ERR(clk)) {
>> + dev_err(&pdev->dev, "Failed to setup input clk.\n");
>> + err = PTR_ERR(clk);
>> + goto free_pltfm;
>> + }
>> + clk_prepare_enable(clk);
>
> Check error code.
>
>> + pltfm_host->clk = clk;
>
> Why not assign pltfm_host->clk immedately when doing devm_clk_get(),
> that would make this a bit cleaner, right?
>
Yes, of course.
>> +
>> + /*
>> + * Some SOCs require additional clock to
>> + * manage AXI bus clock.
>> + * It is optional.
>> + */
>> + axi_clk = devm_clk_get(&pdev->dev, "axi");
>> + if (!IS_ERR(axi_clk)) {
>> + clk_prepare_enable(axi_clk);
>> + priv->axi_clk = axi_clk;
>> + }
>
> Same comments as for the above core clock.
>
OK.
>> +
>> + err = xenon_probe_dt(pdev);
>> + if (err)
>> + goto err_clk;
>> +
>> + err = xenon_slot_probe(host);
>> + if (err)
>> + goto err_clk;
>> +
>> + err = sdhci_add_host(host);
>> + if (err)
>> + goto remove_slot;
>> +
>> + return 0;
>> +
>> +remove_slot:
>> + xenon_slot_remove(host);
>> +err_clk:
>> + clk_disable_unprepare(pltfm_host->clk);
>> + if (!IS_ERR(axi_clk))
>> + clk_disable_unprepare(axi_clk);
>> +free_pltfm:
>> + sdhci_pltfm_free(pdev);
>> + return err;
>> +}
>> +
>> +static int sdhci_xenon_remove(struct platform_device *pdev)
>> +{
>> + struct sdhci_host *host = platform_get_drvdata(pdev);
>> + struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
>> + struct sdhci_xenon_priv *priv = sdhci_pltfm_priv(pltfm_host);
>> + int dead = (readl(host->ioaddr + SDHCI_INT_STATUS) == 0xFFFFFFFF);
>> +
>> + xenon_slot_remove(host);
>> +
>> + sdhci_remove_host(host, dead);
>> +
>> + clk_disable_unprepare(pltfm_host->clk);
>> + clk_disable_unprepare(priv->axi_clk);
>> +
>> + sdhci_pltfm_free(pdev);
>> +
>> + return 0;
>> +}
>> +
>> +static const struct of_device_id sdhci_xenon_dt_ids[] = {
>> + { .compatible = "marvell,xenon-sdhci",},
>> + { .compatible = "marvell,armada-3700-sdhci",},
>> + {}
>> +};
>> +MODULE_DEVICE_TABLE(of, sdhci_xenon_dt_ids);
>> +
>> +static struct platform_driver sdhci_xenon_driver = {
>> + .driver = {
>> + .name = "xenon-sdhci",
>> + .of_match_table = sdhci_xenon_dt_ids,
>> + .pm = &sdhci_pltfm_pmops,
>> + },
>> + .probe = sdhci_xenon_probe,
>> + .remove = sdhci_xenon_remove,
>> +};
>> +
>> +module_platform_driver(sdhci_xenon_driver);
>> +
>> +MODULE_DESCRIPTION("SDHCI platform driver for Marvell Xenon SDHC");
>> +MODULE_AUTHOR("Hu Ziji <huziji@marvell.com>");
>> +MODULE_LICENSE("GPL v2");
>> diff --git a/drivers/mmc/host/sdhci-xenon.h b/drivers/mmc/host/sdhci-xenon.h
>> new file mode 100644
>> index 000000000000..4601d0a4b22f
>> --- /dev/null
>> +++ b/drivers/mmc/host/sdhci-xenon.h
>
> I don't think you need a specific header for this, let's instead just
> put everthing in the c-file.
>
Some definitions inside this file will also be referred in PHY setting in
sdhci-xenon-phy.c.
Thus I put all the definitions together into a header file.
>> @@ -0,0 +1,142 @@
>> +/*
>> + * Copyright (C) 2016 Marvell, All Rights Reserved.
>> + *
>> + * Author: Hu Ziji <huziji@marvell.com>
>> + * Date: 2016-8-24
>> + *
>> + * This program is free software; you can redistribute it and/or
>> + * modify it under the terms of the GNU General Public License as
>> + * published by the Free Software Foundation version 2.
>> + */
>> +#ifndef SDHCI_XENON_H_
>> +#define SDHCI_XENON_H_
>> +
>> +#include <linux/clk.h>
>> +#include <linux/mmc/card.h>
>> +#include <linux/of.h>
>> +#include "sdhci.h"
>> +
>> +/* Register Offset of SD Host Controller SOCP self-defined register */
>> +#define SDHC_SYS_CFG_INFO 0x0104
>> +#define SLOT_TYPE_SDIO_SHIFT 24
>> +#define SLOT_TYPE_EMMC_MASK 0xFF
>> +#define SLOT_TYPE_EMMC_SHIFT 16
>> +#define SLOT_TYPE_SD_SDIO_MMC_MASK 0xFF
>> +#define SLOT_TYPE_SD_SDIO_MMC_SHIFT 8
>> +#define NR_SUPPORTED_SLOT_MASK 0x7
>> +
>> +#define SDHC_SYS_OP_CTRL 0x0108
>> +#define AUTO_CLKGATE_DISABLE_MASK BIT(20)
>> +#define SDCLK_IDLEOFF_ENABLE_SHIFT 8
>> +#define SLOT_ENABLE_SHIFT 0
>> +
>> +#define SDHC_SYS_EXT_OP_CTRL 0x010C
>> +#define MASK_CMD_CONFLICT_ERROR BIT(8)
>> +
>> +#define SDHC_SLOT_OP_STATUS_CTRL 0x0128
>> +#define DELAY_90_DEGREE_MASK_EMMC5 BIT(7)
>> +#define DELAY_90_DEGREE_SHIFT_EMMC5 7
>> +#define EMMC_5_0_PHY_FIXED_DELAY_MASK 0x7F
>> +#define EMMC_PHY_FIXED_DELAY_MASK 0xFF
>> +#define EMMC_PHY_FIXED_DELAY_WINDOW_MIN (EMMC_PHY_FIXED_DELAY_MASK >> 3)
>> +#define SDH_PHY_FIXED_DELAY_MASK 0x1FF
>> +#define SDH_PHY_FIXED_DELAY_WINDOW_MIN (SDH_PHY_FIXED_DELAY_MASK >> 4)
>> +
>> +#define TUN_CONSECUTIVE_TIMES_SHIFT 16
>> +#define TUN_CONSECUTIVE_TIMES_MASK 0x7
>> +#define TUN_CONSECUTIVE_TIMES 0x4
>> +#define TUNING_STEP_SHIFT 12
>> +#define TUNING_STEP_MASK 0xF
>> +#define TUNING_STEP_DIVIDER BIT(6)
>> +
>> +#define FORCE_SEL_INVERSE_CLK_SHIFT 11
>> +
>> +#define SDHC_SLOT_EMMC_CTRL 0x0130
>> +#define ENABLE_DATA_STROBE BIT(24)
>> +#define SET_EMMC_RSTN BIT(16)
>> +#define DISABLE_RD_DATA_CRC BIT(14)
>> +#define DISABLE_CRC_STAT_TOKEN BIT(13)
>> +#define EMMC_VCCQ_MASK 0x3
>> +#define EMMC_VCCQ_1_8V 0x1
>> +#define EMMC_VCCQ_3_3V 0x3
>> +
>> +#define SDHC_SLOT_RETUNING_REQ_CTRL 0x0144
>> +/* retuning compatible */
>> +#define RETUNING_COMPATIBLE 0x1
>> +
>> +#define SDHC_SLOT_EXT_PRESENT_STATE 0x014C
>> +#define LOCK_STATE 0x1
>> +
>> +#define SDHC_SLOT_DLL_CUR_DLY_VAL 0x0150
>> +
>> +/* Tuning Parameter */
>> +#define TMR_RETUN_NO_PRESENT 0xF
>> +#define DEF_TUNING_COUNT 0x9
>> +
>> +#define MMC_TIMING_FAKE 0xFF
>> +
>> +#define DEFAULT_SDCLK_FREQ (400000)
>> +
>> +/* Xenon specific Mode Select value */
>> +#define XENON_SDHCI_CTRL_HS200 0x5
>> +#define XENON_SDHCI_CTRL_HS400 0x6
>
> For all defines above:
>
> All these defines needs some *SDHCI* prefix. Can you please update that.
Sure. Will add prefix for all of them.
>
>> +
>> +struct sdhci_xenon_priv {
>> + /*
>> + * The bus_width, timing, and clock fields in below
>> + * record the current setting of Xenon SDHC.
>> + * Driver will call a Sampling Fixed Delay Adjustment
>> + * if any setting is changed.
>> + */
>> + unsigned char bus_width;
>> + unsigned char timing;
>
> These two are not used. Please remove.
>
The above two variables will be used in PHY setting
in sdhci-xenon-phy.c.
Could you please help review them in next patch?
>> + unsigned char tuning_count;
>> + unsigned int clock;
>
> "clock" isn't used, please remove.
>
It will be accessed in PHY setting in sdhci-xenon-phy.c.
Could you please help review it in next patch?
>> + struct clk *axi_clk;
>> +
>> + /* Slot idx */
>> + u8 slot_idx;
>> + /* Whether this slot is for eMMC */
>> + bool emmc_slot;
>> +
>> + /*
>> + * When initializing card, Xenon has to determine card type and
>> + * adjust Sampling Fixed delay for the speed mode in which
>> + * DLL tuning is not support.
>> + * However, at that time, card structure is not linked to mmc_host.
>> + * Thus a card pointer is added here to provide
>> + * the delay adjustment function with the card structure
>> + * of the card during initialization.
>> + *
>> + * It is only valid during initialization after it is updated in
>> + * xenon_init_card().
>> + * Do not access this variable in normal transfers after
>> + * initialization completes.
>> + */
>> + struct mmc_card *card_candidate;
>
> Not activley used in this change, please remove and let's discuss it
> in the next step.
>
This varible will be accessed in PHY setting in sdhci-xenon-phy.c.
I would like to discuss about it in PHY file. Could you please help
review it in next patch?
Thank you.
Best regards,
Hu Ziji
>> +};
>> +
>> +static inline int enable_xenon_internal_clk(struct sdhci_host *host)
>> +{
>> + u32 reg;
>> + u8 timeout;
>> +
>> + reg = sdhci_readl(host, SDHCI_CLOCK_CONTROL);
>> + reg |= SDHCI_CLOCK_INT_EN;
>> + sdhci_writel(host, reg, SDHCI_CLOCK_CONTROL);
>> + /* Wait max 20 ms */
>> + timeout = 20;
>> + while (!((reg = sdhci_readw(host, SDHCI_CLOCK_CONTROL))
>> + & SDHCI_CLOCK_INT_STABLE)) {
>> + if (timeout == 0) {
>> + pr_err("%s: Internal clock never stabilised.\n",
>> + mmc_hostname(host->mmc));
>> + return -ETIMEDOUT;
>> + }
>> + timeout--;
>> + mdelay(1);
>> + }
>> +
>> + return 0;
>> +}
>> +#endif
>> --
>> git-series 0.8.10
>
> Kind regards
> Uffe
>
^ permalink raw reply
* [PATCH v3 2/2] dt-bindings: power: add bindings for sbs-charger
From: Nicolas Saenz Julienne @ 2016-11-24 12:33 UTC (permalink / raw)
To: sre, robh+dt, mark.rutland
Cc: linux-kernel, devicetree, linux-pm, nicolas.saenz
In-Reply-To: <1479990823-25841-1-git-send-email-nicolas.saenz@prodys.net>
Adds device tree documentation for SBS charger compilant devices as defined
here: http://sbs-forum.org/specs/sbc110.pdf
Signed-off-by: Nicolas Saenz Julienne <nicolas.saenz@prodys.net>
---
v2 -> v3:
- add part number as compatible
.../bindings/power/supply/sbs_sbs-charger.txt | 24 ++++++++++++++++++++++
1 file changed, 24 insertions(+)
create mode 100644 Documentation/devicetree/bindings/power/supply/sbs_sbs-charger.txt
diff --git a/Documentation/devicetree/bindings/power/supply/sbs_sbs-charger.txt b/Documentation/devicetree/bindings/power/supply/sbs_sbs-charger.txt
new file mode 100644
index 0000000..f6b6027
--- /dev/null
+++ b/Documentation/devicetree/bindings/power/supply/sbs_sbs-charger.txt
@@ -0,0 +1,24 @@
+SBS sbs-charger
+~~~~~~~~~~
+
+Required properties:
+ - compatible: should contain one of the following:
+ - "lltc,ltc4100"
+ - "sbs,sbs-charger"
+
+Optional properties:
+- interrupt-parent: Should be the phandle for the interrupt controller. Use in
+ conjunction with "interrupts".
+- interrupts: Interrupt mapping for GPIO IRQ. Use in conjunction with
+ "interrupt-parent". If an interrupt is not provided the driver will switch
+ automatically to polling.
+
+Example:
+
+ ltc4100@9 {
+ compatible = "sbs,sbs-charger";
+ reg = <0x9>;
+ interrupt-parent = <&gpio6>;
+ interrupts = <7 IRQ_TYPE_LEVEL_LOW>;
+ };
+
--
2.7.4
^ permalink raw reply related
* [PATCH v3 1/2] power: supply: add sbs-charger driver
From: Nicolas Saenz Julienne @ 2016-11-24 12:33 UTC (permalink / raw)
To: sre, robh+dt, mark.rutland
Cc: linux-kernel, devicetree, linux-pm, nicolas.saenz
In-Reply-To: <1479990823-25841-1-git-send-email-nicolas.saenz@prodys.net>
This adds support for sbs-charger compilant chips as defined here:
http://sbs-forum.org/specs/sbc110.pdf
This was tested on a arm board connected to an LTC41000 battery charger
chip.
Signed-off-by: Nicolas Saenz Julienne <nicolas.saenz@prodys.net>
---
v2 -> v3:
- add readable_reg() function to regmap config
- update compatible strings with part number
v1 -> v2:
- add spec link in header
- use proper gpio/interrupt interface
- update regmap configuration (max register & endianness)
- dropped oldschool .supplied_to assignments
- use devm_* APIs
drivers/power/supply/Kconfig | 6 +
drivers/power/supply/Makefile | 1 +
drivers/power/supply/sbs-charger.c | 275 +++++++++++++++++++++++++++++++++++++
3 files changed, 282 insertions(+)
create mode 100644 drivers/power/supply/sbs-charger.c
diff --git a/drivers/power/supply/Kconfig b/drivers/power/supply/Kconfig
index 76806a0..42877ff 100644
--- a/drivers/power/supply/Kconfig
+++ b/drivers/power/supply/Kconfig
@@ -164,6 +164,12 @@ config BATTERY_SBS
Say Y to include support for SBS battery driver for SBS-compliant
gas gauges.
+config CHARGER_SBS
+ tristate "SBS Compliant charger"
+ depends on I2C
+ help
+ Say Y to include support for SBS compilant battery chargers.
+
config BATTERY_BQ27XXX
tristate "BQ27xxx battery driver"
help
diff --git a/drivers/power/supply/Makefile b/drivers/power/supply/Makefile
index 36c599d..06d9ef5 100644
--- a/drivers/power/supply/Makefile
+++ b/drivers/power/supply/Makefile
@@ -31,6 +31,7 @@ obj-$(CONFIG_BATTERY_COLLIE) += collie_battery.o
obj-$(CONFIG_BATTERY_IPAQ_MICRO) += ipaq_micro_battery.o
obj-$(CONFIG_BATTERY_WM97XX) += wm97xx_battery.o
obj-$(CONFIG_BATTERY_SBS) += sbs-battery.o
+obj-$(CONFIG_CHARGER_SBS) += sbs-charger.o
obj-$(CONFIG_BATTERY_BQ27XXX) += bq27xxx_battery.o
obj-$(CONFIG_BATTERY_BQ27XXX_I2C) += bq27xxx_battery_i2c.o
obj-$(CONFIG_BATTERY_DA9030) += da9030_battery.o
diff --git a/drivers/power/supply/sbs-charger.c b/drivers/power/supply/sbs-charger.c
new file mode 100644
index 0000000..2c4cd45
--- /dev/null
+++ b/drivers/power/supply/sbs-charger.c
@@ -0,0 +1,275 @@
+/*
+ * Copyright (c) 2016, Prodys S.L.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This adds support for sbs-charger compilant chips as defined here:
+ * http://sbs-forum.org/specs/sbc110.pdf
+ *
+ * Implemetation based on sbs-battery.c
+ */
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/err.h>
+#include <linux/power_supply.h>
+#include <linux/i2c.h>
+#include <linux/slab.h>
+#include <linux/interrupt.h>
+#include <linux/gpio.h>
+#include <linux/regmap.h>
+#include <linux/of_gpio.h>
+#include <linux/bitops.h>
+
+#define SBS_CHARGER_REG_SPEC_INFO 0x11
+#define SBS_CHARGER_REG_STATUS 0x13
+#define SBS_CHARGER_REG_ALARM_WARNING 0x16
+
+#define SBS_CHARGER_STATUS_CHARGE_INHIBITED BIT(1)
+#define SBS_CHARGER_STATUS_RES_COLD BIT(9)
+#define SBS_CHARGER_STATUS_RES_HOT BIT(10)
+#define SBS_CHARGER_STATUS_BATTERY_PRESENT BIT(14)
+#define SBS_CHARGER_STATUS_AC_PRESENT BIT(15)
+
+#define SBS_CHARGER_POLL_TIME 500
+
+struct sbs_info {
+ struct i2c_client *client;
+ struct power_supply *power_supply;
+ struct regmap *regmap;
+ struct delayed_work work;
+ unsigned int last_state;
+};
+
+static int sbs_get_property(struct power_supply *psy,
+ enum power_supply_property psp,
+ union power_supply_propval *val)
+{
+ struct sbs_info *chip = power_supply_get_drvdata(psy);
+ unsigned int reg;
+
+ reg = chip->last_state;
+
+ switch (psp) {
+ case POWER_SUPPLY_PROP_PRESENT:
+ val->intval = !!(reg & SBS_CHARGER_STATUS_BATTERY_PRESENT);
+ break;
+
+ case POWER_SUPPLY_PROP_ONLINE:
+ val->intval = !!(reg & SBS_CHARGER_STATUS_AC_PRESENT);
+ break;
+
+ case POWER_SUPPLY_PROP_STATUS:
+ val->intval = POWER_SUPPLY_STATUS_UNKNOWN;
+
+ if (!(reg & SBS_CHARGER_STATUS_BATTERY_PRESENT))
+ val->intval = POWER_SUPPLY_STATUS_NOT_CHARGING;
+ else if (reg & SBS_CHARGER_STATUS_AC_PRESENT &&
+ !(reg & SBS_CHARGER_STATUS_CHARGE_INHIBITED))
+ val->intval = POWER_SUPPLY_STATUS_CHARGING;
+ else
+ val->intval = POWER_SUPPLY_STATUS_DISCHARGING;
+
+ break;
+
+ case POWER_SUPPLY_PROP_HEALTH:
+ if (reg & SBS_CHARGER_STATUS_RES_COLD)
+ val->intval = POWER_SUPPLY_HEALTH_COLD;
+ if (reg & SBS_CHARGER_STATUS_RES_HOT)
+ val->intval = POWER_SUPPLY_HEALTH_OVERHEAT;
+ else
+ val->intval = POWER_SUPPLY_HEALTH_GOOD;
+
+ break;
+
+ default:
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int sbs_check_state(struct sbs_info *chip)
+{
+ unsigned int reg;
+ int ret;
+
+ ret = regmap_read(chip->regmap, SBS_CHARGER_REG_STATUS, ®);
+ if (!ret && reg != chip->last_state) {
+ chip->last_state = reg;
+ power_supply_changed(chip->power_supply);
+ return 1;
+ }
+
+ return 0;
+}
+
+static void sbs_delayed_work(struct work_struct *work)
+{
+ struct sbs_info *chip = container_of(work, struct sbs_info, work.work);
+
+ sbs_check_state(chip);
+
+ schedule_delayed_work(&chip->work,
+ msecs_to_jiffies(SBS_CHARGER_POLL_TIME));
+}
+
+static irqreturn_t sbs_irq_thread(int irq, void *data)
+{
+ struct sbs_info *chip = data;
+ int ret;
+
+ ret = sbs_check_state(chip);
+
+ return ret ? IRQ_HANDLED : IRQ_NONE;
+}
+
+static enum power_supply_property sbs_properties[] = {
+ POWER_SUPPLY_PROP_STATUS,
+ POWER_SUPPLY_PROP_PRESENT,
+ POWER_SUPPLY_PROP_ONLINE,
+ POWER_SUPPLY_PROP_HEALTH,
+};
+
+static bool sbs_readable_reg(struct device *dev, unsigned int reg)
+{
+ if (reg < SBS_CHARGER_REG_SPEC_INFO)
+ return false;
+ else
+ return true;
+}
+
+static bool sbs_volatile_reg(struct device *dev, unsigned int reg)
+{
+ switch (reg) {
+ case SBS_CHARGER_REG_STATUS:
+ return true;
+ }
+
+ return false;
+}
+
+static const struct regmap_config sbs_regmap = {
+ .reg_bits = 8,
+ .val_bits = 16,
+ .max_register = SBS_CHARGER_REG_ALARM_WARNING,
+ .readable_reg = sbs_readable_reg,
+ .volatile_reg = sbs_volatile_reg,
+ .val_format_endian = REGMAP_ENDIAN_LITTLE, /* since based on SMBus */
+};
+
+static const struct power_supply_desc sbs_desc = {
+ .name = "sbs-charger",
+ .type = POWER_SUPPLY_TYPE_MAINS,
+ .properties = sbs_properties,
+ .num_properties = ARRAY_SIZE(sbs_properties),
+ .get_property = sbs_get_property,
+};
+
+static int sbs_probe(struct i2c_client *client,
+ const struct i2c_device_id *id)
+{
+ struct power_supply_config psy_cfg = {};
+ struct sbs_info *chip;
+ int ret, val;
+
+ chip = devm_kzalloc(&client->dev, sizeof(struct sbs_info), GFP_KERNEL);
+ if (!chip)
+ return -ENOMEM;
+
+ chip->client = client;
+ psy_cfg.of_node = client->dev.of_node;
+ psy_cfg.drv_data = chip;
+
+ i2c_set_clientdata(client, chip);
+
+ chip->regmap = devm_regmap_init_i2c(client, &sbs_regmap);
+ if (IS_ERR(chip->regmap))
+ return PTR_ERR(chip->regmap);
+
+ /*
+ * Before we register, we need to make sure we can actually talk
+ * to the battery.
+ */
+ ret = regmap_read(chip->regmap, SBS_CHARGER_REG_STATUS, &val);
+ if (ret) {
+ dev_err(&client->dev, "Failed to get device status\n");
+ return ret;
+ }
+ chip->last_state = val;
+
+ chip->power_supply = devm_power_supply_register(&client->dev, &sbs_desc,
+ &psy_cfg);
+ if (IS_ERR(chip->power_supply)) {
+ dev_err(&client->dev, "Failed to register power supply\n");
+ return PTR_ERR(chip->power_supply);
+ }
+
+ /*
+ * The sbs-charger spec doesn't impose the use of an interrupt. So in
+ * the case it wasn't provided we use polling in order get the charger's
+ * status.
+ */
+ if (client->irq) {
+ ret = devm_request_threaded_irq(&client->dev, client->irq,
+ NULL, sbs_irq_thread,
+ IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
+ dev_name(&client->dev), chip);
+ if (ret) {
+ dev_err(&client->dev, "Failed to request irq, %d\n", ret);
+ return ret;
+ }
+ } else {
+ INIT_DELAYED_WORK(&chip->work, sbs_delayed_work);
+ schedule_delayed_work(&chip->work,
+ msecs_to_jiffies(SBS_CHARGER_POLL_TIME));
+ }
+
+ dev_info(&client->dev,
+ "%s: smart charger device registered\n", client->name);
+
+ return 0;
+}
+
+static int sbs_remove(struct i2c_client *client)
+{
+ struct sbs_info *chip = i2c_get_clientdata(client);
+
+ cancel_delayed_work_sync(&chip->work);
+
+ return 0;
+}
+
+#ifdef CONFIG_OF
+static const struct of_device_id sbs_dt_ids[] = {
+ { .compatible = "lltc,ltc4100" },
+ { .compatible = "sbs,sbs-charger" },
+ { },
+};
+MODULE_DEVICE_TABLE(of, sbs_dt_ids);
+#endif
+
+static const struct i2c_device_id sbs_id[] = {
+ { "sbs-charger", 0 },
+ { }
+};
+MODULE_DEVICE_TABLE(i2c, sbs_id);
+
+static struct i2c_driver sbs_driver = {
+ .probe = sbs_probe,
+ .remove = sbs_remove,
+ .id_table = sbs_id,
+ .driver = {
+ .name = "sbs-charger",
+ .of_match_table = of_match_ptr(sbs_dt_ids),
+ },
+};
+module_i2c_driver(sbs_driver);
+
+MODULE_AUTHOR("Nicolas Saenz Julienne <nicolassaenzj@gmail.com>");
+MODULE_DESCRIPTION("SBS smart charger driver");
+MODULE_LICENSE("GPL v2");
--
2.7.4
^ permalink raw reply related
* [PATCH v3 0/2] power: supply: add sbs-charger driver
From: Nicolas Saenz Julienne @ 2016-11-24 12:33 UTC (permalink / raw)
To: sre-DgEjT+Ai2ygdnm+yROfE0A, robh+dt-DgEjT+Ai2ygdnm+yROfE0A,
mark.rutland-5wv7dgnIgG8
Cc: linux-kernel-u79uwXL29TY76Z2rM5mHXA,
devicetree-u79uwXL29TY76Z2rM5mHXA,
linux-pm-u79uwXL29TY76Z2rM5mHXA,
nicolas.saenz-gbiq2sxWoaasTnJN9+BGXg
Hi,
This series adds support for all SBS compatible battery chargers, as defined
here: http://sbs-forum.org/specs/sbc110.pdf.
The first patch changes the sbs-battery device name in order to be able to
create a proper supplier/supplied relation between the two of them.
The second introduces the driver.
Regards,
Nicolas
changes since v2:
- updated driver and dt-binding with Sebatian's comments
changes since v1:
- added dt bindings
- updated driver with Sebastian's comments
- s/Nicola/Nicolas/ in commits
Nicolas Saenz Julienne (2):
power: supply: add sbs-charger driver
dt-bindings: power: add bindings for sbs-charger
.../bindings/power/supply/sbs_sbs-charger.txt | 24 ++
drivers/power/supply/Kconfig | 6 +
drivers/power/supply/Makefile | 1 +
drivers/power/supply/sbs-charger.c | 275 +++++++++++++++++++++
4 files changed, 306 insertions(+)
create mode 100644 Documentation/devicetree/bindings/power/supply/sbs_sbs-charger.txt
create mode 100644 drivers/power/supply/sbs-charger.c
--
2.7.4
--
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] drivers/of: Export phandle iterators
From: Robin Murphy @ 2016-11-24 12:33 UTC (permalink / raw)
To: Rob Herring
Cc: devicetree@vger.kernel.org, linux-kernel@vger.kernel.org,
Frank Rowand
In-Reply-To: <CAL_JsqLNCZnKyUmzYAuJSLhVNf1MhnSp_uEw4jn=WcLsw2GCZQ@mail.gmail.com>
Hi Rob,
On 23/11/16 21:49, Rob Herring wrote:
> On Wed, Nov 23, 2016 at 1:06 PM, Robin Murphy <robin.murphy@arm.com> wrote:
>> Modular drivers may want to use of_for_each_phandle() - export its
>> constituent functions.
>
> Do you have a user?
I've been experimenting with modular IOMMU drivers on top of the
probe-deferral stuff[1], and the ARM SMMU driver in particular demands a
whole pile of exports. I thought I'd throw this one out now since nearly
all the other of_* functions are exported already, but I'm quite happy
to sit on it if you'd prefer to wait for a concrete in-tree need (it'll
be a while yet).
Robin.
[1]:http://www.linux-arm.org/git?p=linux-rm.git;a=shortlog;h=refs/heads/iommu/defer
^ permalink raw reply
* [PATCH v9 4/4] tests: Add overlay tests
From: Pantelis Antoniou @ 2016-11-24 12:31 UTC (permalink / raw)
To: David Gibson
Cc: Jon Loeliger, Grant Likely, Frank Rowand, Rob Herring, Jan Luebbe,
Sascha Hauer, Phil Elwell, Simon Glass, Maxime Ripard,
Thomas Petazzoni, Boris Brezillon, Antoine Tenart, Stephen Boyd,
Devicetree Compiler, devicetree-u79uwXL29TY76Z2rM5mHXA,
Pantelis Antoniou
In-Reply-To: <1479990693-14260-1-git-send-email-pantelis.antoniou-OWPKS81ov/FWk0Htik3J/w@public.gmane.org>
Add a number of tests for dynamic objects/overlays.
Re-use the original test by moving the contents to a .dtsi include
Signed-off-by: Pantelis Antoniou <pantelis.antoniou-OWPKS81ov/FWk0Htik3J/w@public.gmane.org>
---
tests/overlay_overlay_dtc.dts | 76 +----------------------------------
tests/overlay_overlay_dtc.dtsi | 83 +++++++++++++++++++++++++++++++++++++++
tests/overlay_overlay_new_dtc.dts | 11 ++++++
tests/overlay_overlay_simple.dts | 12 ++++++
tests/run_tests.sh | 20 ++++++++++
5 files changed, 127 insertions(+), 75 deletions(-)
create mode 100644 tests/overlay_overlay_dtc.dtsi
create mode 100644 tests/overlay_overlay_new_dtc.dts
create mode 100644 tests/overlay_overlay_simple.dts
diff --git a/tests/overlay_overlay_dtc.dts b/tests/overlay_overlay_dtc.dts
index 30d2362..ca943ea 100644
--- a/tests/overlay_overlay_dtc.dts
+++ b/tests/overlay_overlay_dtc.dts
@@ -8,78 +8,4 @@
/dts-v1/;
/plugin/;
-/ {
- /* Test that we can change an int by another */
- fragment@0 {
- target = <&test>;
-
- __overlay__ {
- test-int-property = <43>;
- };
- };
-
- /* Test that we can replace a string by a longer one */
- fragment@1 {
- target = <&test>;
-
- __overlay__ {
- test-str-property = "foobar";
- };
- };
-
- /* Test that we add a new property */
- fragment@2 {
- target = <&test>;
-
- __overlay__ {
- test-str-property-2 = "foobar2";
- };
- };
-
- /* Test that we add a new node (by phandle) */
- fragment@3 {
- target = <&test>;
-
- __overlay__ {
- new-node {
- new-property;
- };
- };
- };
-
- fragment@5 {
- target = <&test>;
-
- __overlay__ {
- local: new-local-node {
- new-property;
- };
- };
- };
-
- fragment@6 {
- target = <&test>;
-
- __overlay__ {
- test-phandle = <&test>, <&local>;
- };
- };
-
- fragment@7 {
- target = <&test>;
-
- __overlay__ {
- test-several-phandle = <&local>, <&local>;
- };
- };
-
- fragment@8 {
- target = <&test>;
-
- __overlay__ {
- sub-test-node {
- new-sub-test-property;
- };
- };
- };
-};
+/include/ "overlay_overlay_dtc.dtsi"
diff --git a/tests/overlay_overlay_dtc.dtsi b/tests/overlay_overlay_dtc.dtsi
new file mode 100644
index 0000000..8ea8d5d
--- /dev/null
+++ b/tests/overlay_overlay_dtc.dtsi
@@ -0,0 +1,83 @@
+/*
+ * Copyright (c) 2016 NextThing Co
+ * Copyright (c) 2016 Free Electrons
+ * Copyright (c) 2016 Konsulko Inc.
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+/ {
+ /* Test that we can change an int by another */
+ fragment@0 {
+ target = <&test>;
+
+ __overlay__ {
+ test-int-property = <43>;
+ };
+ };
+
+ /* Test that we can replace a string by a longer one */
+ fragment@1 {
+ target = <&test>;
+
+ __overlay__ {
+ test-str-property = "foobar";
+ };
+ };
+
+ /* Test that we add a new property */
+ fragment@2 {
+ target = <&test>;
+
+ __overlay__ {
+ test-str-property-2 = "foobar2";
+ };
+ };
+
+ /* Test that we add a new node (by phandle) */
+ fragment@3 {
+ target = <&test>;
+
+ __overlay__ {
+ new-node {
+ new-property;
+ };
+ };
+ };
+
+ fragment@5 {
+ target = <&test>;
+
+ __overlay__ {
+ local: new-local-node {
+ new-property;
+ };
+ };
+ };
+
+ fragment@6 {
+ target = <&test>;
+
+ __overlay__ {
+ test-phandle = <&test>, <&local>;
+ };
+ };
+
+ fragment@7 {
+ target = <&test>;
+
+ __overlay__ {
+ test-several-phandle = <&local>, <&local>;
+ };
+ };
+
+ fragment@8 {
+ target = <&test>;
+
+ __overlay__ {
+ sub-test-node {
+ new-sub-test-property;
+ };
+ };
+ };
+};
diff --git a/tests/overlay_overlay_new_dtc.dts b/tests/overlay_overlay_new_dtc.dts
new file mode 100644
index 0000000..14d3f54
--- /dev/null
+++ b/tests/overlay_overlay_new_dtc.dts
@@ -0,0 +1,11 @@
+/*
+ * Copyright (c) 2016 NextThing Co
+ * Copyright (c) 2016 Free Electrons
+ * Copyright (c) 2016 Konsulko Inc.
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+/dts-v1/ /plugin/;
+
+/include/ "overlay_overlay_dtc.dtsi"
diff --git a/tests/overlay_overlay_simple.dts b/tests/overlay_overlay_simple.dts
new file mode 100644
index 0000000..8657e1e
--- /dev/null
+++ b/tests/overlay_overlay_simple.dts
@@ -0,0 +1,12 @@
+/*
+ * Copyright (c) 2016 Konsulko Inc.
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+/dts-v1/;
+/plugin/;
+
+&test {
+ test-int-property = <43>;
+};
diff --git a/tests/run_tests.sh b/tests/run_tests.sh
index e4139dd..99c09bc 100755
--- a/tests/run_tests.sh
+++ b/tests/run_tests.sh
@@ -181,6 +181,26 @@ overlay_tests () {
run_dtc_test -@ -I dts -O dtb -o overlay_base_with_symbols.test.dtb overlay_base.dts
run_dtc_test -@ -I dts -O dtb -o overlay_overlay_with_symbols.test.dtb overlay_overlay_dtc.dts
run_test overlay overlay_base_with_symbols.test.dtb overlay_overlay_with_symbols.test.dtb
+
+ # new /plugin/ format
+ run_dtc_test -@ -I dts -O dtb -o overlay_overlay_new_with_symbols.test.dtb overlay_overlay_new_dtc.dts
+
+ # test new magic option
+ run_dtc_test -M@ -I dts -O dtb -o overlay_overlay_with_symbols_new_magic.test.dtb overlay_overlay_dtc.dts
+
+ # test plugin source to dtb and back
+ run_dtc_test -@ -I dtb -O dts -o overlay_overlay_dtc.test.dts overlay_overlay_with_symbols.test.dtb
+ run_dtc_test -@ -I dts -O dtb -o overlay_overlay_with_symbols.test.test.dtb overlay_overlay_dtc.test.dts
+ run_test dtbs_equal_ordered overlay_overlay_with_symbols.test.dtb overlay_overlay_with_symbols.test.test.dtb
+
+ # test simplified plugin syntax
+ run_dtc_test -@ -I dts -O dtb -o overlay_overlay_simple.dtb overlay_overlay_simple.dts
+
+ # test plugin source to dtb and back (with new magic)
+ run_dtc_test -@ -I dtb -O dts -o overlay_overlay_dtc_new_magic.test.dts overlay_overlay_with_symbols_new_magic.test.dtb
+ run_dtc_test -@ -I dts -O dtb -o overlay_overlay_with_symbols_new_magic.test.test.dtb overlay_overlay_dtc_new_magic.test.dts
+ run_test dtbs_equal_ordered overlay_overlay_with_symbols_new_magic.test.dtb overlay_overlay_with_symbols_new_magic.test.test.dtb
+
fi
# Bad fixup tests
--
2.1.4
^ permalink raw reply related
* [PATCH v9 3/4] dtc: Plugin and fixup support
From: Pantelis Antoniou @ 2016-11-24 12:31 UTC (permalink / raw)
To: David Gibson
Cc: Jon Loeliger, Grant Likely, Frank Rowand, Rob Herring, Jan Luebbe,
Sascha Hauer, Phil Elwell, Simon Glass, Maxime Ripard,
Thomas Petazzoni, Boris Brezillon, Antoine Tenart, Stephen Boyd,
Devicetree Compiler, devicetree-u79uwXL29TY76Z2rM5mHXA,
Pantelis Antoniou
In-Reply-To: <1479990693-14260-1-git-send-email-pantelis.antoniou-OWPKS81ov/FWk0Htik3J/w@public.gmane.org>
This patch enable the generation of symbols & local fixup information
for trees compiled with the -@ (--symbols) option.
Using this patch labels in the tree and their users emit information
in __symbols__ and __local_fixups__ nodes.
The __fixups__ node make possible the dynamic resolution of phandle
references which are present in the plugin tree but lie in the
tree that are applying the overlay against.
While there is a new magic number for dynamic device tree/overlays blobs
it is by default disabled. This is in order to give time for DT blob
methods to be updated.
Signed-off-by: Pantelis Antoniou <pantelis.antoniou-OWPKS81ov/FWk0Htik3J/w@public.gmane.org>
Signed-off-by: Sascha Hauer <s.hauer-bIcnvbaLZ9MEGnE8C9+IrQ@public.gmane.org>
Signed-off-by: Jan Luebbe <jlu-bIcnvbaLZ9MEGnE8C9+IrQ@public.gmane.org>
---
Documentation/manual.txt | 25 +++++-
checks.c | 8 +-
dtc-lexer.l | 5 ++
dtc-parser.y | 49 +++++++++--
dtc.c | 39 +++++++-
dtc.h | 20 ++++-
fdtdump.c | 2 +-
flattree.c | 17 ++--
fstree.c | 2 +-
libfdt/fdt.c | 2 +-
libfdt/fdt.h | 3 +-
livetree.c | 225 ++++++++++++++++++++++++++++++++++++++++++++++-
tests/mangle-layout.c | 7 +-
treesource.c | 7 +-
14 files changed, 380 insertions(+), 31 deletions(-)
diff --git a/Documentation/manual.txt b/Documentation/manual.txt
index 398de32..65fbf09 100644
--- a/Documentation/manual.txt
+++ b/Documentation/manual.txt
@@ -119,6 +119,24 @@ Options:
Make space for <number> reserve map entries
Relevant for dtb and asm output only.
+ -@
+ Generates a __symbols__ node at the root node of the resulting blob
+ for any node labels used, and for any local references using phandles
+ it also generates a __local_fixups__ node that tracks them.
+
+ When using the /plugin/ tag all unresolved label references to
+ be tracked in the __fixups__ node, making dynamic resolution possible.
+
+ -A
+ Generate automatically aliases for all node labels. This is similar to
+ the -@ option (the __symbols__ node contain identical information) but
+ the semantics are slightly different since no phandles are automatically
+ generated for labeled nodes.
+
+ -M
+ Generate blobs with the new FDT magic number. By default blobs with the
+ standard FDT magic number are generated.
+
-S <bytes>
Ensure the blob at least <bytes> long, adding additional
space if needed.
@@ -146,13 +164,18 @@ Additionally, dtc performs various sanity checks on the tree.
Here is a very rough overview of the layout of a DTS source file:
- sourcefile: list_of_memreserve devicetree
+ sourcefile: versioninfo plugindecl list_of_memreserve devicetree
memreserve: label 'memreserve' ADDR ADDR ';'
| label 'memreserve' ADDR '-' ADDR ';'
devicetree: '/' nodedef
+ versioninfo: '/' 'dts-v1' '/' ';'
+
+ plugindecl: '/' 'plugin' '/' ';'
+ | /* empty */
+
nodedef: '{' list_of_property list_of_subnode '}' ';'
property: label PROPNAME '=' propdata ';'
diff --git a/checks.c b/checks.c
index 609975a..bc03d42 100644
--- a/checks.c
+++ b/checks.c
@@ -486,8 +486,12 @@ static void fixup_phandle_references(struct check *c, struct boot_info *bi,
refnode = get_node_by_ref(dt, m->ref);
if (! refnode) {
- FAIL(c, "Reference to non-existent node or label \"%s\"\n",
- m->ref);
+ if (!(bi->versionflags & VF_PLUGIN))
+ FAIL(c, "Reference to non-existent node or "
+ "label \"%s\"\n", m->ref);
+ else /* mark the entry as unresolved */
+ *((cell_t *)(prop->val.val + m->offset)) =
+ cpu_to_fdt32(0xffffffff);
continue;
}
diff --git a/dtc-lexer.l b/dtc-lexer.l
index 790fbf6..40bbc87 100644
--- a/dtc-lexer.l
+++ b/dtc-lexer.l
@@ -121,6 +121,11 @@ static void lexical_error(const char *fmt, ...);
return DT_V1;
}
+<*>"/plugin/" {
+ DPRINT("Keyword: /plugin/\n");
+ return DT_PLUGIN;
+ }
+
<*>"/memreserve/" {
DPRINT("Keyword: /memreserve/\n");
BEGIN_DEFAULT();
diff --git a/dtc-parser.y b/dtc-parser.y
index 14aaf2e..4afc592 100644
--- a/dtc-parser.y
+++ b/dtc-parser.y
@@ -19,6 +19,7 @@
*/
%{
#include <stdio.h>
+#include <inttypes.h>
#include "dtc.h"
#include "srcpos.h"
@@ -33,6 +34,9 @@ extern void yyerror(char const *s);
extern struct boot_info *the_boot_info;
extern bool treesource_error;
+
+/* temporary while the tree is not built */
+static unsigned int the_versionflags;
%}
%union {
@@ -52,9 +56,11 @@ extern bool treesource_error;
struct node *nodelist;
struct reserve_info *re;
uint64_t integer;
+ unsigned int flags;
}
%token DT_V1
+%token DT_PLUGIN
%token DT_MEMRESERVE
%token DT_LSHIFT DT_RSHIFT DT_LE DT_GE DT_EQ DT_NE DT_AND DT_OR
%token DT_BITS
@@ -71,6 +77,8 @@ extern bool treesource_error;
%type <data> propdata
%type <data> propdataprefix
+%type <flags> versioninfo
+%type <flags> plugindecl
%type <re> memreserve
%type <re> memreserves
%type <array> arrayprefix
@@ -101,16 +109,36 @@ extern bool treesource_error;
%%
sourcefile:
- v1tag memreserves devicetree
+ versioninfo plugindecl memreserves devicetree
+ {
+ the_boot_info = build_boot_info($1 | $2, $3, $4,
+ guess_boot_cpuid($4));
+ }
+ ;
+
+versioninfo:
+ v1tag
{
- the_boot_info = build_boot_info($2, $3,
- guess_boot_cpuid($3));
+ the_versionflags |= VF_DT_V1;
+ $$ = the_versionflags;
}
;
v1tag:
DT_V1 ';'
+ | DT_V1
| DT_V1 ';' v1tag
+
+plugindecl:
+ DT_PLUGIN ';'
+ {
+ the_versionflags |= VF_PLUGIN;
+ $$ = VF_PLUGIN;
+ }
+ | /* empty */
+ {
+ $$ = 0;
+ }
;
memreserves:
@@ -161,10 +189,14 @@ devicetree:
{
struct node *target = get_node_by_ref($1, $2);
- if (target)
+ if (target) {
merge_nodes(target, $3);
- else
- ERROR(&@2, "Label or path %s not found", $2);
+ } else {
+ if (the_versionflags & VF_PLUGIN)
+ add_orphan_node($1, $3, $2);
+ else
+ ERROR(&@2, "Label or path %s not found", $2);
+ }
$$ = $1;
}
| devicetree DT_DEL_NODE DT_REF ';'
@@ -179,6 +211,11 @@ devicetree:
$$ = $1;
}
+ | /* empty */
+ {
+ /* build empty node */
+ $$ = name_node(build_node(NULL, NULL), "");
+ }
;
nodedef:
diff --git a/dtc.c b/dtc.c
index 9dcf640..a654267 100644
--- a/dtc.c
+++ b/dtc.c
@@ -32,6 +32,9 @@ int minsize; /* Minimum blob size */
int padsize; /* Additional padding to blob */
int alignsize; /* Additional padding to blob accroding to the alignsize */
int phandle_format = PHANDLE_BOTH; /* Use linux,phandle or phandle properties */
+int symbol_fixup_support; /* enable symbols & fixup support */
+int auto_label_aliases; /* auto generate labels -> aliases */
+int new_magic; /* use new FDT magic values for objects */
static int is_power_of_2(int x)
{
@@ -59,7 +62,7 @@ static void fill_fullpaths(struct node *tree, const char *prefix)
#define FDT_VERSION(version) _FDT_VERSION(version)
#define _FDT_VERSION(version) #version
static const char usage_synopsis[] = "dtc [options] <input file>";
-static const char usage_short_opts[] = "qI:O:o:V:d:R:S:p:a:fb:i:H:sW:E:hv";
+static const char usage_short_opts[] = "qI:O:o:V:d:R:S:p:a:fb:i:H:sW:E:@AMhv";
static struct option const usage_long_opts[] = {
{"quiet", no_argument, NULL, 'q'},
{"in-format", a_argument, NULL, 'I'},
@@ -78,6 +81,9 @@ static struct option const usage_long_opts[] = {
{"phandle", a_argument, NULL, 'H'},
{"warning", a_argument, NULL, 'W'},
{"error", a_argument, NULL, 'E'},
+ {"symbols", no_argument, NULL, '@'},
+ {"auto-alias", no_argument, NULL, 'A'},
+ {"new-magic", no_argument, NULL, 'M'},
{"help", no_argument, NULL, 'h'},
{"version", no_argument, NULL, 'v'},
{NULL, no_argument, NULL, 0x0},
@@ -109,6 +115,9 @@ static const char * const usage_opts_help[] = {
"\t\tboth - Both \"linux,phandle\" and \"phandle\" properties",
"\n\tEnable/disable warnings (prefix with \"no-\")",
"\n\tEnable/disable errors (prefix with \"no-\")",
+ "\n\tEnable symbols/fixup support",
+ "\n\tEnable auto-alias of labels",
+ "\n\tUse new blog magic value",
"\n\tPrint this help and exit",
"\n\tPrint version and exit",
NULL,
@@ -153,7 +162,7 @@ static const char *guess_input_format(const char *fname, const char *fallback)
fclose(f);
magic = fdt32_to_cpu(magic);
- if (magic == FDT_MAGIC)
+ if (magic == FDT_MAGIC || magic == FDT_MAGIC_DTBO)
return "dtb";
return guess_type_by_name(fname, fallback);
@@ -172,6 +181,7 @@ int main(int argc, char *argv[])
FILE *outf = NULL;
int outversion = DEFAULT_FDT_VERSION;
long long cmdline_boot_cpuid = -1;
+ fdt32_t out_magic = FDT_MAGIC;
quiet = 0;
reservenum = 0;
@@ -249,6 +259,16 @@ int main(int argc, char *argv[])
parse_checks_option(false, true, optarg);
break;
+ case '@':
+ symbol_fixup_support = 1;
+ break;
+ case 'A':
+ auto_label_aliases = 1;
+ break;
+ case 'M':
+ new_magic = 1;
+ break;
+
case 'h':
usage(NULL);
default:
@@ -306,6 +326,14 @@ int main(int argc, char *argv[])
fill_fullpaths(bi->dt, "");
process_checks(force, bi);
+ if (auto_label_aliases)
+ generate_label_tree(bi->dt, "aliases", false);
+
+ if (symbol_fixup_support) {
+ generate_label_tree(bi->dt, "__symbols__", true);
+ generate_fixups_tree(bi->dt);
+ }
+
if (sort)
sort_tree(bi);
@@ -318,12 +346,15 @@ int main(int argc, char *argv[])
outname, strerror(errno));
}
+ if (new_magic && (bi->versionflags & VF_PLUGIN))
+ out_magic = FDT_MAGIC_DTBO;
+
if (streq(outform, "dts")) {
dt_to_source(outf, bi);
} else if (streq(outform, "dtb")) {
- dt_to_blob(outf, bi, outversion);
+ dt_to_blob(outf, bi, out_magic, outversion);
} else if (streq(outform, "asm")) {
- dt_to_asm(outf, bi, outversion);
+ dt_to_asm(outf, bi, out_magic, outversion);
} else if (streq(outform, "null")) {
/* do nothing */
} else {
diff --git a/dtc.h b/dtc.h
index 32009bc..889b8f8 100644
--- a/dtc.h
+++ b/dtc.h
@@ -55,6 +55,9 @@ extern int minsize; /* Minimum blob size */
extern int padsize; /* Additional padding to blob */
extern int alignsize; /* Additional padding to blob accroding to the alignsize */
extern int phandle_format; /* Use linux,phandle or phandle properties */
+extern int symbol_fixup_support;/* enable symbols & fixup support */
+extern int auto_label_aliases; /* auto generate labels -> aliases */
+extern int new_magic; /* use new FDT magic values for objects */
#define PHANDLE_LEGACY 0x1
#define PHANDLE_EPAPR 0x2
@@ -195,6 +198,7 @@ struct node *build_node_delete(void);
struct node *name_node(struct node *node, char *name);
struct node *chain_node(struct node *first, struct node *list);
struct node *merge_nodes(struct node *old_node, struct node *new_node);
+void add_orphan_node(struct node *old_node, struct node *new_node, char *ref);
void add_property(struct node *node, struct property *prop);
void delete_property_by_name(struct node *node, char *name);
@@ -202,6 +206,8 @@ void delete_property(struct property *prop);
void add_child(struct node *parent, struct node *child);
void delete_node_by_name(struct node *parent, char *name);
void delete_node(struct node *node);
+void append_to_property(struct node *node,
+ char *name, const void *data, int len);
const char *get_unitname(struct node *node);
struct property *get_property(struct node *node, const char *propname);
@@ -237,14 +243,22 @@ struct reserve_info *add_reserve_entry(struct reserve_info *list,
struct boot_info {
+ unsigned int versionflags;
struct reserve_info *reservelist;
struct node *dt; /* the device tree */
uint32_t boot_cpuid_phys;
};
-struct boot_info *build_boot_info(struct reserve_info *reservelist,
+/* version flags definitions */
+#define VF_DT_V1 0x0001 /* /dts-v1/ */
+#define VF_PLUGIN 0x0002 /* /plugin/ */
+
+struct boot_info *build_boot_info(unsigned int versionflags,
+ struct reserve_info *reservelist,
struct node *tree, uint32_t boot_cpuid_phys);
void sort_tree(struct boot_info *bi);
+void generate_label_tree(struct node *dt, char *gen_node_name, bool allocph);
+void generate_fixups_tree(struct node *dt);
/* Checks */
@@ -253,8 +267,8 @@ void process_checks(bool force, struct boot_info *bi);
/* Flattened trees */
-void dt_to_blob(FILE *f, struct boot_info *bi, int version);
-void dt_to_asm(FILE *f, struct boot_info *bi, int version);
+void dt_to_blob(FILE *f, struct boot_info *bi, fdt32_t magic, int version);
+void dt_to_asm(FILE *f, struct boot_info *bi, fdt32_t magic, int version);
struct boot_info *dt_from_blob(const char *fname);
diff --git a/fdtdump.c b/fdtdump.c
index a9a2484..dd63ac2 100644
--- a/fdtdump.c
+++ b/fdtdump.c
@@ -201,7 +201,7 @@ int main(int argc, char *argv[])
p = memchr(p, smagic[0], endp - p - FDT_MAGIC_SIZE);
if (!p)
break;
- if (fdt_magic(p) == FDT_MAGIC) {
+ if (fdt_magic(p) == FDT_MAGIC || fdt_magic(p) == FDT_MAGIC_DTBO) {
/* try and validate the main struct */
off_t this_len = endp - p;
fdt32_t max_version = 17;
diff --git a/flattree.c b/flattree.c
index a9d9520..57d76cf 100644
--- a/flattree.c
+++ b/flattree.c
@@ -335,6 +335,7 @@ static struct data flatten_reserve_list(struct reserve_info *reservelist,
}
static void make_fdt_header(struct fdt_header *fdt,
+ fdt32_t magic,
struct version_info *vi,
int reservesize, int dtsize, int strsize,
int boot_cpuid_phys)
@@ -345,7 +346,7 @@ static void make_fdt_header(struct fdt_header *fdt,
memset(fdt, 0xff, sizeof(*fdt));
- fdt->magic = cpu_to_fdt32(FDT_MAGIC);
+ fdt->magic = cpu_to_fdt32(magic);
fdt->version = cpu_to_fdt32(vi->version);
fdt->last_comp_version = cpu_to_fdt32(vi->last_comp_version);
@@ -366,7 +367,7 @@ static void make_fdt_header(struct fdt_header *fdt,
fdt->size_dt_struct = cpu_to_fdt32(dtsize);
}
-void dt_to_blob(FILE *f, struct boot_info *bi, int version)
+void dt_to_blob(FILE *f, struct boot_info *bi, fdt32_t magic, int version)
{
struct version_info *vi = NULL;
int i;
@@ -390,7 +391,7 @@ void dt_to_blob(FILE *f, struct boot_info *bi, int version)
reservebuf = flatten_reserve_list(bi->reservelist, vi);
/* Make header */
- make_fdt_header(&fdt, vi, reservebuf.len, dtbuf.len, strbuf.len,
+ make_fdt_header(&fdt, magic, vi, reservebuf.len, dtbuf.len, strbuf.len,
bi->boot_cpuid_phys);
/*
@@ -467,7 +468,7 @@ static void dump_stringtable_asm(FILE *f, struct data strbuf)
}
}
-void dt_to_asm(FILE *f, struct boot_info *bi, int version)
+void dt_to_asm(FILE *f, struct boot_info *bi, fdt32_t magic, int version)
{
struct version_info *vi = NULL;
int i;
@@ -830,6 +831,7 @@ struct boot_info *dt_from_blob(const char *fname)
struct node *tree;
uint32_t val;
int flags = 0;
+ unsigned int versionflags = VF_DT_V1;
f = srcfile_relative_open(fname, NULL);
@@ -845,9 +847,12 @@ struct boot_info *dt_from_blob(const char *fname)
}
magic = fdt32_to_cpu(magic);
- if (magic != FDT_MAGIC)
+ if (magic != FDT_MAGIC && magic != FDT_MAGIC_DTBO)
die("Blob has incorrect magic number\n");
+ if (magic == FDT_MAGIC_DTBO)
+ versionflags |= VF_PLUGIN;
+
rc = fread(&totalsize, sizeof(totalsize), 1, f);
if (ferror(f))
die("Error reading DT blob size: %s\n", strerror(errno));
@@ -942,5 +947,5 @@ struct boot_info *dt_from_blob(const char *fname)
fclose(f);
- return build_boot_info(reservelist, tree, boot_cpuid_phys);
+ return build_boot_info(versionflags, reservelist, tree, boot_cpuid_phys);
}
diff --git a/fstree.c b/fstree.c
index 6d1beec..54f520b 100644
--- a/fstree.c
+++ b/fstree.c
@@ -86,6 +86,6 @@ struct boot_info *dt_from_fs(const char *dirname)
tree = read_fstree(dirname);
tree = name_node(tree, "");
- return build_boot_info(NULL, tree, guess_boot_cpuid(tree));
+ return build_boot_info(VF_DT_V1, NULL, tree, guess_boot_cpuid(tree));
}
diff --git a/libfdt/fdt.c b/libfdt/fdt.c
index 22286a1..28d422c 100644
--- a/libfdt/fdt.c
+++ b/libfdt/fdt.c
@@ -57,7 +57,7 @@
int fdt_check_header(const void *fdt)
{
- if (fdt_magic(fdt) == FDT_MAGIC) {
+ if (fdt_magic(fdt) == FDT_MAGIC || fdt_magic(fdt) == FDT_MAGIC_DTBO) {
/* Complete tree */
if (fdt_version(fdt) < FDT_FIRST_SUPPORTED_VERSION)
return -FDT_ERR_BADVERSION;
diff --git a/libfdt/fdt.h b/libfdt/fdt.h
index 526aedb..493cd55 100644
--- a/libfdt/fdt.h
+++ b/libfdt/fdt.h
@@ -55,7 +55,7 @@
#ifndef __ASSEMBLY__
struct fdt_header {
- fdt32_t magic; /* magic word FDT_MAGIC */
+ fdt32_t magic; /* magic word FDT_MAGIC[|_DTBO] */
fdt32_t totalsize; /* total size of DT block */
fdt32_t off_dt_struct; /* offset to structure */
fdt32_t off_dt_strings; /* offset to strings */
@@ -93,6 +93,7 @@ struct fdt_property {
#endif /* !__ASSEMBLY */
#define FDT_MAGIC 0xd00dfeed /* 4: version, 4: total size */
+#define FDT_MAGIC_DTBO 0xd00dfdb0 /* DTBO magic */
#define FDT_TAGSIZE sizeof(fdt32_t)
#define FDT_BEGIN_NODE 0x1 /* Start node: full name */
diff --git a/livetree.c b/livetree.c
index 3dc7559..1a2f4b1 100644
--- a/livetree.c
+++ b/livetree.c
@@ -216,6 +216,31 @@ struct node *merge_nodes(struct node *old_node, struct node *new_node)
return old_node;
}
+void add_orphan_node(struct node *dt, struct node *new_node, char *ref)
+{
+ static unsigned int next_orphan_fragment = 0;
+ struct node *node = xmalloc(sizeof(*node));
+ struct property *p;
+ struct data d = empty_data;
+ char *name;
+
+ memset(node, 0, sizeof(*node));
+
+ d = data_add_marker(d, REF_PHANDLE, ref);
+ d = data_append_integer(d, 0xffffffff, 32);
+
+ p = build_property("target", d);
+ add_property(node, p);
+
+ xasprintf(&name, "fragment@%u",
+ next_orphan_fragment++);
+ name_node(node, name);
+ name_node(new_node, "__overlay__");
+
+ add_child(dt, node);
+ add_child(node, new_node);
+}
+
struct node *chain_node(struct node *first, struct node *list)
{
assert(first->next_sibling == NULL);
@@ -296,6 +321,23 @@ void delete_node(struct node *node)
delete_labels(&node->labels);
}
+void append_to_property(struct node *node,
+ char *name, const void *data, int len)
+{
+ struct data d;
+ struct property *p;
+
+ p = get_property(node, name);
+ if (p) {
+ d = data_append_data(p->val, data, len);
+ p->val = d;
+ } else {
+ d = data_append_data(empty_data, data, len);
+ p = build_property(name, d);
+ add_property(node, p);
+ }
+}
+
struct reserve_info *build_reserve_entry(uint64_t address, uint64_t size)
{
struct reserve_info *new = xmalloc(sizeof(*new));
@@ -335,12 +377,14 @@ struct reserve_info *add_reserve_entry(struct reserve_info *list,
return list;
}
-struct boot_info *build_boot_info(struct reserve_info *reservelist,
+struct boot_info *build_boot_info(unsigned int versionflags,
+ struct reserve_info *reservelist,
struct node *tree, uint32_t boot_cpuid_phys)
{
struct boot_info *bi;
bi = xmalloc(sizeof(*bi));
+ bi->versionflags = versionflags;
bi->reservelist = reservelist;
bi->dt = tree;
bi->boot_cpuid_phys = boot_cpuid_phys;
@@ -709,3 +753,182 @@ void sort_tree(struct boot_info *bi)
sort_reserve_entries(bi);
sort_node(bi->dt);
}
+
+/* utility helper to avoid code duplication */
+static struct node *build_and_name_child_node(struct node *parent, char *name)
+{
+ struct node *node;
+
+ node = build_node(NULL, NULL);
+ name_node(node, xstrdup(name));
+ add_child(parent, node);
+
+ return node;
+}
+
+static void generate_label_tree_internal(struct node *dt, struct node *node,
+ struct node *an, bool allocph)
+{
+ struct node *c;
+ struct property *p;
+ struct label *l;
+
+ /* if if there are labels */
+ if (node->labels) {
+ /* now add the label in the node */
+ for_each_label(node->labels, l) {
+ /* check whether the label already exists */
+ p = get_property(an, l->label);
+ if (p) {
+ fprintf(stderr, "WARNING: label %s already"
+ " exists in /%s", l->label,
+ an->name);
+ continue;
+ }
+
+ /* insert it */
+ p = build_property(l->label,
+ data_copy_escape_string(node->fullpath,
+ strlen(node->fullpath)));
+ add_property(an, p);
+ }
+
+ /* force allocation of a phandle for this node */
+ if (allocph)
+ (void)get_node_phandle(dt, node);
+ }
+
+ for_each_child(node, c)
+ generate_label_tree_internal(dt, c, an, allocph);
+}
+
+void generate_label_tree(struct node *dt, char *gen_node_name, bool allocph)
+{
+ struct node *an;
+
+ for_each_child(dt, an)
+ if (streq(gen_node_name, an->name))
+ break;
+
+ if (!an)
+ an = build_and_name_child_node(dt, gen_node_name);
+ if (!an)
+ die("Could not build label node /%s\n", gen_node_name);
+
+ generate_label_tree_internal(dt, dt, an, allocph);
+}
+
+static char *fixups_name = "__fixups__";
+static char *local_fixups_name = "__local_fixups__";
+
+static void add_fixup_entry(struct node *dt, struct node *node,
+ struct property *prop, struct marker *m)
+{
+ struct node *fn; /* fixup node */
+ char *entry;
+
+ /* m->ref can only be a REF_PHANDLE, but check anyway */
+ assert(m->type == REF_PHANDLE);
+
+ /* fn is the node we're putting entries in */
+ fn = get_subnode(dt, fixups_name);
+ assert(fn != NULL);
+
+ /* there shouldn't be any ':' in the arguments */
+ if (strchr(node->fullpath, ':') || strchr(prop->name, ':'))
+ die("arguments should not contain ':'\n");
+
+ xasprintf(&entry, "%s:%s:%u",
+ node->fullpath, prop->name, m->offset);
+ append_to_property(fn, m->ref, entry, strlen(entry) + 1);
+}
+
+static void add_local_fixup_entry(struct node *dt, struct node *node,
+ struct property *prop, struct marker *m,
+ struct node *refnode)
+{
+ struct node *lfn, *wn, *nwn; /* local fixup node, walk node, new */
+ uint32_t value_32;
+ char *s, *e, *comp;
+ int len;
+
+ /* fn is the node we're putting entries in */
+ lfn = get_subnode(dt, local_fixups_name);
+ assert(lfn != NULL);
+
+ /* walk the path components creating nodes if they don't exist */
+ comp = xmalloc(strlen(node->fullpath) + 1);
+ /* start skipping the first / */
+ s = node->fullpath + 1;
+ wn = lfn;
+ while (*s) {
+ /* retrieve path component */
+ e = strchr(s, '/');
+ if (e == NULL)
+ e = s + strlen(s);
+ len = e - s;
+ memcpy(comp, s, len);
+ comp[len] = '\0';
+
+ /* if no node exists, create it */
+ nwn = get_subnode(wn, comp);
+ if (!nwn)
+ nwn = build_and_name_child_node(wn, comp);
+ wn = nwn;
+
+ /* last path component */
+ if (!*e)
+ break;
+
+ /* next path component */
+ s = e + 1;
+ }
+ free(comp);
+
+ value_32 = cpu_to_fdt32(m->offset);
+ append_to_property(wn, prop->name, &value_32, sizeof(value_32));
+}
+
+static void generate_fixups_tree_internal(struct node *dt, struct node *node)
+{
+ struct node *c;
+ struct property *prop;
+ struct marker *m;
+ struct node *refnode;
+
+ for_each_property(node, prop) {
+ m = prop->val.markers;
+ for_each_marker_of_type(m, REF_PHANDLE) {
+ refnode = get_node_by_ref(dt, m->ref);
+ if (!refnode)
+ add_fixup_entry(dt, node, prop, m);
+ else
+ add_local_fixup_entry(dt, node, prop, m,
+ refnode);
+ }
+ }
+
+ for_each_child(node, c)
+ generate_fixups_tree_internal(dt, c);
+}
+
+void generate_fixups_tree(struct node *dt)
+{
+ struct node *an;
+
+ for_each_child(dt, an)
+ if (streq(fixups_name, an->name))
+ break;
+
+ if (!an)
+ build_and_name_child_node(dt, fixups_name);
+
+ for_each_child(dt, an)
+ if (streq(local_fixups_name, an->name))
+ break;
+
+ if (!an)
+ build_and_name_child_node(dt, local_fixups_name);
+
+ generate_fixups_tree_internal(dt, dt);
+}
diff --git a/tests/mangle-layout.c b/tests/mangle-layout.c
index a76e51e..d29ebc6 100644
--- a/tests/mangle-layout.c
+++ b/tests/mangle-layout.c
@@ -42,7 +42,8 @@ static void expand_buf(struct bufstate *buf, int newsize)
buf->size = newsize;
}
-static void new_header(struct bufstate *buf, int version, const void *fdt)
+static void new_header(struct bufstate *buf, fdt32_t magic, int version,
+ const void *fdt)
{
int hdrsize;
@@ -56,7 +57,7 @@ static void new_header(struct bufstate *buf, int version, const void *fdt)
expand_buf(buf, hdrsize);
memset(buf->buf, 0, hdrsize);
- fdt_set_magic(buf->buf, FDT_MAGIC);
+ fdt_set_magic(buf->buf, magic);
fdt_set_version(buf->buf, version);
fdt_set_last_comp_version(buf->buf, 16);
fdt_set_boot_cpuid_phys(buf->buf, fdt_boot_cpuid_phys(fdt));
@@ -145,7 +146,7 @@ int main(int argc, char *argv[])
if (fdt_version(fdt) < 17)
CONFIG("Input tree must be v17");
- new_header(&buf, version, fdt);
+ new_header(&buf, FDT_MAGIC, version, fdt);
while (*blockorder) {
add_block(&buf, version, *blockorder, fdt);
diff --git a/treesource.c b/treesource.c
index a55d1d1..75e920d 100644
--- a/treesource.c
+++ b/treesource.c
@@ -267,7 +267,12 @@ void dt_to_source(FILE *f, struct boot_info *bi)
{
struct reserve_info *re;
- fprintf(f, "/dts-v1/;\n\n");
+ fprintf(f, "/dts-v1/");
+
+ if (bi->versionflags & VF_PLUGIN)
+ fprintf(f, " /plugin/");
+
+ fprintf(f, ";\n\n");
for (re = bi->reservelist; re; re = re->next) {
struct label *l;
--
2.1.4
^ permalink raw reply related
* [PATCH v9 2/4] dtc: Document the dynamic plugin internals
From: Pantelis Antoniou @ 2016-11-24 12:31 UTC (permalink / raw)
To: David Gibson
Cc: Jon Loeliger, Grant Likely, Frank Rowand, Rob Herring, Jan Luebbe,
Sascha Hauer, Phil Elwell, Simon Glass, Maxime Ripard,
Thomas Petazzoni, Boris Brezillon, Antoine Tenart, Stephen Boyd,
Devicetree Compiler, devicetree-u79uwXL29TY76Z2rM5mHXA,
Pantelis Antoniou
In-Reply-To: <1479990693-14260-1-git-send-email-pantelis.antoniou-OWPKS81ov/FWk0Htik3J/w@public.gmane.org>
Provides the document explaining the internal mechanics of
plugins and options.
Signed-off-by: Pantelis Antoniou <pantelis.antoniou-OWPKS81ov/FWk0Htik3J/w@public.gmane.org>
---
Documentation/dt-object-internal.txt | 318 +++++++++++++++++++++++++++++++++++
1 file changed, 318 insertions(+)
create mode 100644 Documentation/dt-object-internal.txt
diff --git a/Documentation/dt-object-internal.txt b/Documentation/dt-object-internal.txt
new file mode 100644
index 0000000..d5b841e
--- /dev/null
+++ b/Documentation/dt-object-internal.txt
@@ -0,0 +1,318 @@
+Device Tree Dynamic Object format internals
+-------------------------------------------
+
+The Device Tree for most platforms is a static representation of
+the hardware capabilities. This is insufficient for many platforms
+that need to dynamically insert device tree fragments to the
+running kernel's live tree.
+
+This document explains the the device tree object format and the
+modifications made to the device tree compiler, which make it possible.
+
+1. Simplified Problem Definition
+--------------------------------
+
+Assume we have a platform which boots using following simplified device tree.
+
+---- foo.dts -----------------------------------------------------------------
+ /* FOO platform */
+ / {
+ compatible = "corp,foo";
+
+ /* shared resources */
+ res: res {
+ };
+
+ /* On chip peripherals */
+ ocp: ocp {
+ /* peripherals that are always instantiated */
+ peripheral1 { ... };
+ };
+ };
+---- foo.dts -----------------------------------------------------------------
+
+We have a number of peripherals that after probing (using some undefined method)
+should result in different device tree configuration.
+
+We cannot boot with this static tree because due to the configuration of the
+foo platform there exist multiple conficting peripherals DT fragments.
+
+So for the bar peripheral we would have this:
+
+---- foo+bar.dts -------------------------------------------------------------
+ /* FOO platform + bar peripheral */
+ / {
+ compatible = "corp,foo";
+
+ /* shared resources */
+ res: res {
+ };
+
+ /* On chip peripherals */
+ ocp: ocp {
+ /* peripherals that are always instantiated */
+ peripheral1 { ... };
+
+ /* bar peripheral */
+ bar {
+ compatible = "corp,bar";
+ ... /* various properties and child nodes */
+ };
+ };
+ };
+---- foo+bar.dts -------------------------------------------------------------
+
+While for the baz peripheral we would have this:
+
+---- foo+baz.dts -------------------------------------------------------------
+ /* FOO platform + baz peripheral */
+ / {
+ compatible = "corp,foo";
+
+ /* shared resources */
+ res: res {
+ /* baz resources */
+ baz_res: res_baz { ... };
+ };
+
+ /* On chip peripherals */
+ ocp: ocp {
+ /* peripherals that are always instantiated */
+ peripheral1 { ... };
+
+ /* baz peripheral */
+ baz {
+ compatible = "corp,baz";
+ /* reference to another point in the tree */
+ ref-to-res = <&baz_res>;
+ ... /* various properties and child nodes */
+ };
+ };
+ };
+---- foo+baz.dts -------------------------------------------------------------
+
+We note that the baz case is more complicated, since the baz peripheral needs to
+reference another node in the DT tree.
+
+2. Device Tree Object Format Requirements
+-----------------------------------------
+
+Since the device tree is used for booting a number of very different hardware
+platforms it is imperative that we tread very carefully.
+
+2.a) No changes to the Device Tree binary format for the base tree. We cannot
+modify the tree format at all and all the information we require should be
+encoded using device tree itself. We can add nodes that can be safely ignored
+by both bootloaders and the kernel. The plugin dtb's are optionally tagged
+with a different magic number in the header but otherwise they too are simple
+blobs.
+
+2.b) Changes to the DTS source format should be absolutely minimal, and should
+only be needed for the DT fragment definitions, and not the base boot DT.
+
+2.c) An explicit option should be used to instruct DTC to generate the required
+information needed for object resolution. Platforms that don't use the
+dynamic object format can safely ignore it.
+
+2.d) Finally, DT syntax changes should be kept to a minimum. It should be
+possible to express everything using the existing DT syntax.
+
+3. Implementation
+-----------------
+
+The basic unit of addressing in Device Tree is the phandle. Turns out it's
+relatively simple to extend the way phandles are generated and referenced
+so that it's possible to dynamically convert symbolic references (labels)
+to phandle values. This is a valid assumption as long as the author uses
+reference syntax and does not assign phandle values manually (which might
+be a problem with decompiled source files).
+
+We can roughly divide the operation into two steps.
+
+3.a) Compilation of the base board DTS file using the '-@' option
+generates a valid DT blob with an added __symbols__ node at the root node,
+containing a list of all nodes that are marked with a label.
+
+Using the foo.dts file above the following node will be generated;
+
+$ dtc -@ -O dtb -o foo.dtb -b 0 foo.dts
+$ fdtdump foo.dtb
+...
+/ {
+ ...
+ res {
+ ...
+ phandle = <0x00000001>;
+ ...
+ };
+ ocp {
+ ...
+ phandle = <0x00000002>;
+ ...
+ };
+ __symbols__ {
+ res="/res";
+ ocp="/ocp";
+ };
+};
+
+Notice that all the nodes that had a label have been recorded, and that
+phandles have been generated for them.
+
+This blob can be used to boot the board normally, the __symbols__ node will
+be safely ignored both by the bootloader and the kernel (the only loss will
+be a few bytes of memory and disk space).
+
+3.b) The Device Tree fragments must be compiled with the same option but they
+must also have a tag (/plugin/) that allows undefined references to nodes
+that are not present at compilation time to be recorded so that the runtime
+loader can fix them.
+
+So the bar peripheral's DTS format would be of the form:
+
+/dts-v1/ /plugin/; /* allow undefined references and record them */
+/ {
+ .... /* various properties for loader use; i.e. part id etc. */
+ fragment@0 {
+ target = <&ocp>;
+ __overlay__ {
+ /* bar peripheral */
+ bar {
+ compatible = "corp,bar";
+ ... /* various properties and child nodes */
+ }
+ };
+ };
+};
+
+Note that there's a target property that specifies the location where the
+contents of the overlay node will be placed, and it references the node
+in the foo.dts file.
+
+$ dtc -@ -O dtb -o bar.dtbo -b 0 bar.dts
+$ fdtdump bar.dtbo
+...
+/ {
+ ... /* properties */
+ fragment@0 {
+ target = <0xffffffff>;
+ __overlay__ {
+ bar {
+ compatible = "corp,bar";
+ ... /* various properties and child nodes */
+ }
+ };
+ };
+ __fixups__ {
+ ocp = "/fragment@0:target:0";
+ };
+};
+
+No __symbols__ has been generated (no label in bar.dts).
+Note that the target's ocp label is undefined, so the phandle handle
+value is filled with the illegal value '0xffffffff', while a __fixups__
+node has been generated, which marks the location in the tree where
+the label lookup should store the runtime phandle value of the ocp node.
+
+The format of the __fixups__ node entry is
+
+ <label> = "<local-full-path>:<property-name>:<offset>";
+
+<label> Is the label we're referring
+<local-full-path> Is the full path of the node the reference is
+<property-name> Is the name of the property containing the
+ reference
+<offset> The offset (in bytes) of where the property's
+ phandle value is located.
+
+Doing the same with the baz peripheral's DTS format is a little bit more
+involved, since baz contains references to local labels which require
+local fixups.
+
+/dts-v1/ /plugin/; /* allow undefined label references and record them */
+/ {
+ .... /* various properties for loader use; i.e. part id etc. */
+ fragment@0 {
+ target = <&res>;
+ __overlay__ {
+ /* baz resources */
+ baz_res: res_baz { ... };
+ };
+ };
+ fragment@1 {
+ target = <&ocp>;
+ __overlay__ {
+ /* baz peripheral */
+ baz {
+ compatible = "corp,baz";
+ /* reference to another point in the tree */
+ ref-to-res = <&baz_res>;
+ ... /* various properties and child nodes */
+ }
+ };
+ };
+};
+
+Note that &bar_res reference.
+
+$ dtc -@ -O dtb -o baz.dtbo -b 0 baz.dts
+$ fdtdump baz.dtbo
+...
+/ {
+ ... /* properties */
+ fragment@0 {
+ target = <0xffffffff>;
+ __overlay__ {
+ res_baz {
+ ....
+ phandle = <0x00000001>;
+ };
+ };
+ };
+ fragment@1 {
+ target = <0xffffffff>;
+ __overlay__ {
+ baz {
+ compatible = "corp,baz";
+ ... /* various properties and child nodes */
+ ref-to-res = <0x00000001>;
+ }
+ };
+ };
+ __fixups__ {
+ res = "/fragment@0:target:0";
+ ocp = "/fragment@1:target:0";
+ };
+ __local_fixups__ {
+ fragment@1 {
+ __overlay__ {
+ baz {
+ ref-to-res = <0>;
+ };
+ };
+ };
+ };
+};
+
+This is similar to the bar case, but the reference of a local label by the
+baz node generates a __local_fixups__ entry that records the place that the
+local reference is being made. No matter how phandles are allocated from dtc
+the run time loader must apply an offset to each phandle in every dynamic
+DT object loaded. The __local_fixups__ node records the place of every
+local reference so that the loader can apply the offset.
+
+There is an alternative syntax to the expanded form for overlays with phandle
+targets which makes the format similar to the one using in .dtsi include files.
+
+So for the &ocp target example above one can simply write:
+
+/dts-v1/ /plugin/;
+&ocp {
+ /* bar peripheral */
+ bar {
+ compatible = "corp,bar";
+ ... /* various properties and child nodes */
+ }
+};
+
+The resulting dtb object is identical.
--
2.1.4
--
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 related
* [PATCH v9 1/4] checks: Pass boot_info to the check methods
From: Pantelis Antoniou @ 2016-11-24 12:31 UTC (permalink / raw)
To: David Gibson
Cc: Jon Loeliger, Grant Likely, Frank Rowand, Rob Herring, Jan Luebbe,
Sascha Hauer, Phil Elwell, Simon Glass, Maxime Ripard,
Thomas Petazzoni, Boris Brezillon, Antoine Tenart, Stephen Boyd,
Devicetree Compiler, devicetree-u79uwXL29TY76Z2rM5mHXA,
Pantelis Antoniou
In-Reply-To: <1479990693-14260-1-git-send-email-pantelis.antoniou-OWPKS81ov/FWk0Htik3J/w@public.gmane.org>
As preparation for overlay support we need to pass boot info
as an extra boot_info parameter to each check method.
No other functional changes are made.
Signed-off-by: Pantelis Antoniou <pantelis.antoniou-OWPKS81ov/FWk0Htik3J/w@public.gmane.org>
---
checks.c | 113 +++++++++++++++++++++++++++++++++------------------------------
1 file changed, 59 insertions(+), 54 deletions(-)
diff --git a/checks.c b/checks.c
index 0381c98..609975a 100644
--- a/checks.c
+++ b/checks.c
@@ -40,7 +40,8 @@ enum checkstatus {
struct check;
-typedef void (*check_fn)(struct check *c, struct node *dt, struct node *node);
+typedef void (*check_fn)(struct check *c, struct boot_info *bi,
+ struct node *dt, struct node *node);
struct check {
const char *name;
@@ -97,19 +98,20 @@ static inline void check_msg(struct check *c, const char *fmt, ...)
check_msg((c), __VA_ARGS__); \
} while (0)
-static void check_nodes_props(struct check *c, struct node *dt, struct node *node)
+static void check_nodes_props(struct check *c, struct boot_info *bi,
+ struct node *dt, struct node *node)
{
struct node *child;
TRACE(c, "%s", node->fullpath);
if (c->fn)
- c->fn(c, dt, node);
+ c->fn(c, bi, dt, node);
for_each_child(node, child)
- check_nodes_props(c, dt, child);
+ check_nodes_props(c, bi, dt, child);
}
-static bool run_check(struct check *c, struct node *dt)
+static bool run_check(struct check *c, struct boot_info *bi, struct node *dt)
{
bool error = false;
int i;
@@ -123,7 +125,7 @@ static bool run_check(struct check *c, struct node *dt)
for (i = 0; i < c->num_prereqs; i++) {
struct check *prq = c->prereq[i];
- error = error || run_check(prq, dt);
+ error = error || run_check(prq, bi, dt);
if (prq->status != PASSED) {
c->status = PREREQ;
check_msg(c, "Failed prerequisite '%s'",
@@ -134,7 +136,7 @@ static bool run_check(struct check *c, struct node *dt)
if (c->status != UNCHECKED)
goto out;
- check_nodes_props(c, dt, dt);
+ check_nodes_props(c, bi, dt, dt);
if (c->status == UNCHECKED)
c->status = PASSED;
@@ -153,15 +155,15 @@ out:
*/
/* A check which always fails, for testing purposes only */
-static inline void check_always_fail(struct check *c, struct node *dt,
- struct node *node)
+static inline void check_always_fail(struct check *c, struct boot_info *bi,
+ struct node *dt, struct node *node)
{
FAIL(c, "always_fail check");
}
CHECK(always_fail, check_always_fail, NULL);
-static void check_is_string(struct check *c, struct node *root,
- struct node *node)
+static void check_is_string(struct check *c, struct boot_info *bi,
+ struct node *root, struct node *node)
{
struct property *prop;
char *propname = c->data;
@@ -179,8 +181,8 @@ static void check_is_string(struct check *c, struct node *root,
#define ERROR_IF_NOT_STRING(nm, propname) \
ERROR(nm, check_is_string, (propname))
-static void check_is_cell(struct check *c, struct node *root,
- struct node *node)
+static void check_is_cell(struct check *c, struct boot_info *bi,
+ struct node *root, struct node *node)
{
struct property *prop;
char *propname = c->data;
@@ -202,8 +204,8 @@ static void check_is_cell(struct check *c, struct node *root,
* Structural check functions
*/
-static void check_duplicate_node_names(struct check *c, struct node *dt,
- struct node *node)
+static void check_duplicate_node_names(struct check *c, struct boot_info *bi,
+ struct node *dt, struct node *node)
{
struct node *child, *child2;
@@ -217,8 +219,8 @@ static void check_duplicate_node_names(struct check *c, struct node *dt,
}
ERROR(duplicate_node_names, check_duplicate_node_names, NULL);
-static void check_duplicate_property_names(struct check *c, struct node *dt,
- struct node *node)
+static void check_duplicate_property_names(struct check *c, struct boot_info *bi,
+ struct node *dt, struct node *node)
{
struct property *prop, *prop2;
@@ -239,8 +241,8 @@ ERROR(duplicate_property_names, check_duplicate_property_names, NULL);
#define DIGITS "0123456789"
#define PROPNODECHARS LOWERCASE UPPERCASE DIGITS ",._+*#?-"
-static void check_node_name_chars(struct check *c, struct node *dt,
- struct node *node)
+static void check_node_name_chars(struct check *c, struct boot_info *bi,
+ struct node *dt, struct node *node)
{
int n = strspn(node->name, c->data);
@@ -250,8 +252,8 @@ static void check_node_name_chars(struct check *c, struct node *dt,
}
ERROR(node_name_chars, check_node_name_chars, PROPNODECHARS "@");
-static void check_node_name_format(struct check *c, struct node *dt,
- struct node *node)
+static void check_node_name_format(struct check *c, struct boot_info *bi,
+ struct node *dt, struct node *node)
{
if (strchr(get_unitname(node), '@'))
FAIL(c, "Node %s has multiple '@' characters in name",
@@ -259,8 +261,8 @@ static void check_node_name_format(struct check *c, struct node *dt,
}
ERROR(node_name_format, check_node_name_format, NULL, &node_name_chars);
-static void check_unit_address_vs_reg(struct check *c, struct node *dt,
- struct node *node)
+static void check_unit_address_vs_reg(struct check *c, struct boot_info *bi,
+ struct node *dt, struct node *node)
{
const char *unitname = get_unitname(node);
struct property *prop = get_property(node, "reg");
@@ -283,8 +285,8 @@ static void check_unit_address_vs_reg(struct check *c, struct node *dt,
}
WARNING(unit_address_vs_reg, check_unit_address_vs_reg, NULL);
-static void check_property_name_chars(struct check *c, struct node *dt,
- struct node *node)
+static void check_property_name_chars(struct check *c, struct boot_info *bi,
+ struct node *dt, struct node *node)
{
struct property *prop;
@@ -305,9 +307,10 @@ ERROR(property_name_chars, check_property_name_chars, PROPNODECHARS);
((prop) ? (prop)->name : ""), \
((prop) ? "' in " : ""), (node)->fullpath
-static void check_duplicate_label(struct check *c, struct node *dt,
- const char *label, struct node *node,
- struct property *prop, struct marker *mark)
+static void check_duplicate_label(struct check *c, struct boot_info *bi,
+ struct node *dt, const char *label,
+ struct node *node, struct property *prop,
+ struct marker *mark)
{
struct node *othernode = NULL;
struct property *otherprop = NULL;
@@ -331,29 +334,30 @@ static void check_duplicate_label(struct check *c, struct node *dt,
DESCLABEL_ARGS(othernode, otherprop, othermark));
}
-static void check_duplicate_label_node(struct check *c, struct node *dt,
- struct node *node)
+static void check_duplicate_label_node(struct check *c, struct boot_info *bi,
+ struct node *dt, struct node *node)
{
struct label *l;
struct property *prop;
for_each_label(node->labels, l)
- check_duplicate_label(c, dt, l->label, node, NULL, NULL);
+ check_duplicate_label(c, bi, dt, l->label, node, NULL, NULL);
for_each_property(node, prop) {
struct marker *m = prop->val.markers;
for_each_label(prop->labels, l)
- check_duplicate_label(c, dt, l->label, node, prop, NULL);
+ check_duplicate_label(c, bi, dt, l->label, node, prop, NULL);
for_each_marker_of_type(m, LABEL)
- check_duplicate_label(c, dt, m->ref, node, prop, m);
+ check_duplicate_label(c, bi, dt, m->ref, node, prop, m);
}
}
ERROR(duplicate_label, check_duplicate_label_node, NULL);
-static cell_t check_phandle_prop(struct check *c, struct node *root,
- struct node *node, const char *propname)
+static cell_t check_phandle_prop(struct check *c, struct boot_info *bi,
+ struct node *root, struct node *node,
+ const char *propname)
{
struct property *prop;
struct marker *m;
@@ -398,8 +402,8 @@ static cell_t check_phandle_prop(struct check *c, struct node *root,
return phandle;
}
-static void check_explicit_phandles(struct check *c, struct node *root,
- struct node *node)
+static void check_explicit_phandles(struct check *c, struct boot_info *bi,
+ struct node *root, struct node *node)
{
struct node *other;
cell_t phandle, linux_phandle;
@@ -407,9 +411,9 @@ static void check_explicit_phandles(struct check *c, struct node *root,
/* Nothing should have assigned phandles yet */
assert(!node->phandle);
- phandle = check_phandle_prop(c, root, node, "phandle");
+ phandle = check_phandle_prop(c, bi, root, node, "phandle");
- linux_phandle = check_phandle_prop(c, root, node, "linux,phandle");
+ linux_phandle = check_phandle_prop(c, bi, root, node, "linux,phandle");
if (!phandle && !linux_phandle)
/* No valid phandles; nothing further to check */
@@ -433,8 +437,8 @@ static void check_explicit_phandles(struct check *c, struct node *root,
}
ERROR(explicit_phandles, check_explicit_phandles, NULL);
-static void check_name_properties(struct check *c, struct node *root,
- struct node *node)
+static void check_name_properties(struct check *c, struct boot_info *bi,
+ struct node *root, struct node *node)
{
struct property **pp, *prop = NULL;
@@ -467,8 +471,8 @@ ERROR(name_properties, check_name_properties, NULL, &name_is_string);
* Reference fixup functions
*/
-static void fixup_phandle_references(struct check *c, struct node *dt,
- struct node *node)
+static void fixup_phandle_references(struct check *c, struct boot_info *bi,
+ struct node *dt, struct node *node)
{
struct property *prop;
@@ -495,8 +499,8 @@ static void fixup_phandle_references(struct check *c, struct node *dt,
ERROR(phandle_references, fixup_phandle_references, NULL,
&duplicate_node_names, &explicit_phandles);
-static void fixup_path_references(struct check *c, struct node *dt,
- struct node *node)
+static void fixup_path_references(struct check *c, struct boot_info *bi,
+ struct node *dt, struct node *node)
{
struct property *prop;
@@ -534,8 +538,8 @@ WARNING_IF_NOT_STRING(device_type_is_string, "device_type");
WARNING_IF_NOT_STRING(model_is_string, "model");
WARNING_IF_NOT_STRING(status_is_string, "status");
-static void fixup_addr_size_cells(struct check *c, struct node *dt,
- struct node *node)
+static void fixup_addr_size_cells(struct check *c, struct boot_info *bi,
+ struct node *dt, struct node *node)
{
struct property *prop;
@@ -558,8 +562,8 @@ WARNING(addr_size_cells, fixup_addr_size_cells, NULL,
#define node_size_cells(n) \
(((n)->size_cells == -1) ? 1 : (n)->size_cells)
-static void check_reg_format(struct check *c, struct node *dt,
- struct node *node)
+static void check_reg_format(struct check *c, struct boot_info *bi,
+ struct node *dt, struct node *node)
{
struct property *prop;
int addr_cells, size_cells, entrylen;
@@ -587,8 +591,8 @@ static void check_reg_format(struct check *c, struct node *dt,
}
WARNING(reg_format, check_reg_format, NULL, &addr_size_cells);
-static void check_ranges_format(struct check *c, struct node *dt,
- struct node *node)
+static void check_ranges_format(struct check *c, struct boot_info *bi,
+ struct node *dt, struct node *node)
{
struct property *prop;
int c_addr_cells, p_addr_cells, c_size_cells, p_size_cells, entrylen;
@@ -631,8 +635,8 @@ WARNING(ranges_format, check_ranges_format, NULL, &addr_size_cells);
/*
* Style checks
*/
-static void check_avoid_default_addr_size(struct check *c, struct node *dt,
- struct node *node)
+static void check_avoid_default_addr_size(struct check *c, struct boot_info *bi,
+ struct node *dt, struct node *node)
{
struct property *reg, *ranges;
@@ -657,6 +661,7 @@ WARNING(avoid_default_addr_size, check_avoid_default_addr_size, NULL,
&addr_size_cells);
static void check_obsolete_chosen_interrupt_controller(struct check *c,
+ struct boot_info *bi,
struct node *dt,
struct node *node)
{
@@ -773,7 +778,7 @@ void process_checks(bool force, struct boot_info *bi)
struct check *c = check_table[i];
if (c->warn || c->error)
- error = error || run_check(c, dt);
+ error = error || run_check(c, bi, dt);
}
if (error) {
--
2.1.4
--
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 related
* [PATCH v9 0/4] dtc: Dynamic DT support
From: Pantelis Antoniou @ 2016-11-24 12:31 UTC (permalink / raw)
To: David Gibson
Cc: Jon Loeliger, Grant Likely, Frank Rowand, Rob Herring, Jan Luebbe,
Sascha Hauer, Phil Elwell, Simon Glass, Maxime Ripard,
Thomas Petazzoni, Boris Brezillon, Antoine Tenart, Stephen Boyd,
Devicetree Compiler, devicetree-u79uwXL29TY76Z2rM5mHXA,
Pantelis Antoniou
This patchset adds Dynamic DT support in the DTC compiler
as used in a number of boards like the beaglebone/rpi/chip and others.
The first patch passes an extra boot_info argument to the check methods.
The second patch documents the internals of overlay generation, while
the third one adds dynamic object/overlay support proper.
The last patch simply adds a few overlay tests verifying operation.
This patchset is against DTC mainline and is also available for a pull
request from https://github.com/pantoniou/dtc/tree/overlays
Regards
-- Pantelis
Changes since v8:
* Removed extra member of boot_info in each node; passing boot_info
parameter to the check methods instead.
* Reworked yacc syntax that supports both old and new plugin syntax
* Added handling for new magic number (enabled by 'M' switch).
* Dropped dtbo/asmo formats.
* Added overlay testsuite.
* Addressed last version maintainer comments.
Changes since v7:
* Dropped xasprintf & backward compatibility patch
* Rebased against dgibson's overlay branch
* Minor doc wording fixes.
Changes since v6:
* Introduced xasprintf
* Added append_to_property and used it
* Changed some die()'s to assert
* Reordered node generation to respect sort
* Addressed remaining maintainer changes from v6
Changes since v5:
* Rebase to latest dtc version.
* Addressed all the maintainer requested changes from v5
* Added new magic value for dynamic objects and new format
Changes since v4:
* Rebase to latest dtc version.
* Completely redesigned the generation of resolution data.
Now instead of being generated as part of blob generation
they are created in the live tree.
* Consequently the patchset is much smaller.
* Added -A auto-label alias generation option.
* Addressed maintainer comments.
* Added syntactic sugar for overlays in the form of .dtsi
* Added /dts-v1/ /plugin/ preferred plugin form and deprecate
the previous form (although still works for backward compatibility)
Changes since v3:
* Rebase to latest dtc version.
Changes since v2:
* Split single patch to a patchset.
* Updated to dtc mainline.
* Changed __local_fixups__ format
* Clean up for better legibility.
Pantelis Antoniou (4):
checks: Pass boot_info to the check methods
dtc: Document the dynamic plugin internals
dtc: Plugin and fixup support
tests: Add overlay tests
Documentation/dt-object-internal.txt | 318 +++++++++++++++++++++++++++++++++++
Documentation/manual.txt | 25 ++-
checks.c | 121 +++++++------
dtc-lexer.l | 5 +
dtc-parser.y | 49 +++++-
dtc.c | 39 ++++-
dtc.h | 20 ++-
fdtdump.c | 2 +-
flattree.c | 17 +-
fstree.c | 2 +-
libfdt/fdt.c | 2 +-
libfdt/fdt.h | 3 +-
livetree.c | 225 ++++++++++++++++++++++++-
tests/mangle-layout.c | 7 +-
tests/overlay_overlay_dtc.dts | 76 +--------
tests/overlay_overlay_dtc.dtsi | 83 +++++++++
tests/overlay_overlay_new_dtc.dts | 11 ++
tests/overlay_overlay_simple.dts | 12 ++
tests/run_tests.sh | 20 +++
treesource.c | 7 +-
20 files changed, 884 insertions(+), 160 deletions(-)
create mode 100644 Documentation/dt-object-internal.txt
create mode 100644 tests/overlay_overlay_dtc.dtsi
create mode 100644 tests/overlay_overlay_new_dtc.dts
create mode 100644 tests/overlay_overlay_simple.dts
--
2.1.4
--
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 v4 1/6] arm64: arch_timer: Add device tree binding for hisilicon-161601 erratum
From: John Garry @ 2016-11-24 12:12 UTC (permalink / raw)
To: Ding Tianhong, catalin.marinas-5wv7dgnIgG8,
will.deacon-5wv7dgnIgG8, marc.zyngier-5wv7dgnIgG8,
mark.rutland-5wv7dgnIgG8, oss-fOR+EgIDQEHk1uMJSBkQmQ,
devicetree-u79uwXL29TY76Z2rM5mHXA,
shawnguo-DgEjT+Ai2ygdnm+yROfE0A, stuart.yoder-3arQi8VN3Tc,
linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
linuxarm-hv44wF8Li93QT0dZR+AlfA,
hanjun.guo-QSEj5FYQhm4dnm+yROfE0A
In-Reply-To: <c3020c0d-bc45-2bb1-f53a-c5e76ab45499-hv44wF8Li93QT0dZR+AlfA@public.gmane.org>
On 21/11/2016 12:49, Ding Tianhong wrote:
> Ping....
Hi,
was there a cover letter for 0/6? I never saw it.
Thanks,
John
>
> On 2016/11/15 20:16, Ding Tianhong wrote:
>> This erratum describes a bug in logic outside the core, so MIDR can't be
>> used to identify its presence, and reading an SoC-specific revision
>> register from common arch timer code would be awkward. So, describe it
>> in the device tree.
>>
>> v2: Use the new erratum name and update the description.
>>
>> Signed-off-by: Ding Tianhong <dingtianhong-hv44wF8Li93QT0dZR+AlfA@public.gmane.org>
>> Acked-by: Rob Herring <robh-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org>
>> ---
>> Documentation/devicetree/bindings/arm/arch_timer.txt | 8 ++++++++
>> 1 file changed, 8 insertions(+)
>>
>> diff --git a/Documentation/devicetree/bindings/arm/arch_timer.txt b/Documentation/devicetree/bindings/arm/arch_timer.txt
>> index ef5fbe9..c27b2c4 100644
>> --- a/Documentation/devicetree/bindings/arm/arch_timer.txt
>> +++ b/Documentation/devicetree/bindings/arm/arch_timer.txt
>> @@ -31,6 +31,14 @@ to deliver its interrupts via SPIs.
>> This also affects writes to the tval register, due to the implicit
>> counter read.
>>
>> +- hisilicon,erratum-161601 : A boolean property. Indicates the presence of
>> + erratum 161601, which says that reading the counter is unreliable unless
>> + reading twice on the register and the value of the second read is larger
>> + than the first by less than 32. If the verification is unsuccessful, then
>> + discard the value of this read and repeat this procedure until the verification
>> + is successful. This also affects writes to the tval register, due to the
>> + implicit counter read.
>> +
>> ** Optional properties:
>>
>> - arm,cpu-registers-not-fw-configured : Firmware does not initialize
>>
>
> _______________________________________________
> linuxarm mailing list
> linuxarm-hv44wF8Li93QT0dZR+AlfA@public.gmane.org
> http://rnd-openeuler.huawei.com/mailman/listinfo/linuxarm
>
> .
>
--
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
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