[1/2] regulator: pbias: use untranslated address to program pbias regulator
diff mbox

Message ID 1437996250-2913-2-git-send-email-kishon@ti.com
State New
Headers show

Commit Message

Kishon Vijay Abraham I July 27, 2015, 11:24 a.m. UTC
vsel_reg and enable_reg of the pbias regulator descriptor should actually
have the offset from syscon. However after the pbias device tree node
is moved as a child node of syscon, vsel_reg and enable_reg has the
absolute address because of the address translation that happens while
creating device from device tree node.
So avoid using platform_get_resource and use of_get_address in order to
get only the offset (untranslated address) and populate these in
vsel_reg and enable_reg.

Cc: <stable@vger.kernel.org>
Cc: Tero Kristo <t-kristo@ti.com>
Signed-off-by: Kishon Vijay Abraham I <kishon@ti.com>
---
 drivers/regulator/pbias-regulator.c |   16 +++++++++++-----
 1 file changed, 11 insertions(+), 5 deletions(-)

Comments

Grygorii Strashko July 29, 2015, 8:57 a.m. UTC | #1
On 07/27/2015 02:24 PM, Kishon Vijay Abraham I wrote:
> vsel_reg and enable_reg of the pbias regulator descriptor should actually
> have the offset from syscon. However after the pbias device tree node
> is moved as a child node of syscon, vsel_reg and enable_reg has the
> absolute address because of the address translation that happens while
> creating device from device tree node.
> So avoid using platform_get_resource and use of_get_address in order to
> get only the offset (untranslated address) and populate these in
> vsel_reg and enable_reg.
>
> Cc: <stable@vger.kernel.org>
> Cc: Tero Kristo <t-kristo@ti.com>
> Signed-off-by: Kishon Vijay Abraham I <kishon@ti.com>

For dra7-evm:
Tested-by: Grygorii Strashko <grygorii.strashko@ti.com>
Tony Lindgren Aug. 5, 2015, 9:47 a.m. UTC | #2
* Kishon Vijay Abraham I <kishon@ti.com> [150727 04:27]:
> vsel_reg and enable_reg of the pbias regulator descriptor should actually
> have the offset from syscon. However after the pbias device tree node
> is moved as a child node of syscon, vsel_reg and enable_reg has the
> absolute address because of the address translation that happens while
> creating device from device tree node.
> So avoid using platform_get_resource and use of_get_address in order to
> get only the offset (untranslated address) and populate these in
> vsel_reg and enable_reg.

I think this gets fixed automatically with your other series
adding the "simple-bus" to the nodes. For the children of_ioremap
and friends should do the right thing, but without help from the bus
things won't work right without "simple-bus".

Regards,

Tony
--
To unsubscribe from this list: send the line "unsubscribe linux-omap" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Kishon Vijay Abraham I Aug. 5, 2015, 2:56 p.m. UTC | #3
Hi Tony,

On Wednesday 05 August 2015 03:17 PM, Tony Lindgren wrote:
> * Kishon Vijay Abraham I <kishon@ti.com> [150727 04:27]:
>> vsel_reg and enable_reg of the pbias regulator descriptor should actually
>> have the offset from syscon. However after the pbias device tree node
>> is moved as a child node of syscon, vsel_reg and enable_reg has the
>> absolute address because of the address translation that happens while
>> creating device from device tree node.
>> So avoid using platform_get_resource and use of_get_address in order to
>> get only the offset (untranslated address) and populate these in
>> vsel_reg and enable_reg.
> 
> I think this gets fixed automatically with your other series
> adding the "simple-bus" to the nodes. For the children of_ioremap

Nope. The probe of pbias regulator fails as Grygorii has already pointed out
here [1].

Thanks
Kishon

[1] -> http://www.spinics.net/lists/linux-omap/msg120462.html
--
To unsubscribe from this list: send the line "unsubscribe linux-omap" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Tony Lindgren Aug. 6, 2015, 6:26 a.m. UTC | #4
* Kishon Vijay Abraham I <kishon@ti.com> [150805 07:59]:
> Hi Tony,
> 
> On Wednesday 05 August 2015 03:17 PM, Tony Lindgren wrote:
> > * Kishon Vijay Abraham I <kishon@ti.com> [150727 04:27]:
> >> vsel_reg and enable_reg of the pbias regulator descriptor should actually
> >> have the offset from syscon. However after the pbias device tree node
> >> is moved as a child node of syscon, vsel_reg and enable_reg has the
> >> absolute address because of the address translation that happens while
> >> creating device from device tree node.
> >> So avoid using platform_get_resource and use of_get_address in order to
> >> get only the offset (untranslated address) and populate these in
> >> vsel_reg and enable_reg.
> > 
> > I think this gets fixed automatically with your other series
> > adding the "simple-bus" to the nodes. For the children of_ioremap
> 
> Nope. The probe of pbias regulator fails as Grygorii has already pointed out
> here [1].

Oh I see, you want the offset from syscon, not the virtual address of
the register. Yeah then it makes sense to me. You could also get the
offset by doing res->start & 0xff or something but I don't know if
that's any better. I guess ideallly we'd have some syscon function
to get the offest from the syscon base if it does not exist already.

Regards,

Tony

 
> [1] -> http://www.spinics.net/lists/linux-omap/msg120462.html
--
To unsubscribe from this list: send the line "unsubscribe linux-omap" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Grygorii Strashko Aug. 6, 2015, 9:58 a.m. UTC | #5
On 08/06/2015 09:26 AM, Tony Lindgren wrote:
> * Kishon Vijay Abraham I <kishon@ti.com> [150805 07:59]:
>> Hi Tony,
>>
>> On Wednesday 05 August 2015 03:17 PM, Tony Lindgren wrote:
>>> * Kishon Vijay Abraham I <kishon@ti.com> [150727 04:27]:
>>>> vsel_reg and enable_reg of the pbias regulator descriptor should actually
>>>> have the offset from syscon. However after the pbias device tree node
>>>> is moved as a child node of syscon, vsel_reg and enable_reg has the
>>>> absolute address because of the address translation that happens while
>>>> creating device from device tree node.
>>>> So avoid using platform_get_resource and use of_get_address in order to
>>>> get only the offset (untranslated address) and populate these in
>>>> vsel_reg and enable_reg.
>>>
>>> I think this gets fixed automatically with your other series
>>> adding the "simple-bus" to the nodes. For the children of_ioremap
>>
>> Nope. The probe of pbias regulator fails as Grygorii has already pointed out
>> here [1].
> 
> Oh I see, you want the offset from syscon, not the virtual address of
> the register. Yeah then it makes sense to me. You could also get the
> offset by doing res->start & 0xff or something but I don't know if
> that's any better. I guess ideallly we'd have some syscon function
> to get the offest from the syscon base if it does not exist already.

Hypothetically, the "syscon" property can be used to get register offset
syscon = <&scm_conf 0xe00>;
and even "reg" property can be dropped if driver uses syscon/regmap only for io.

But, in this particular case, such change will lead to DT compatibility issues :(
Mark Brown Aug. 14, 2015, 6 p.m. UTC | #6
On Mon, Jul 27, 2015 at 04:54:09PM +0530, Kishon Vijay Abraham I wrote:

> vsel_reg and enable_reg of the pbias regulator descriptor should actually
> have the offset from syscon. However after the pbias device tree node

I'm having a hard time understanding this statement, sorry.  What makes
you say that they "shouild actually have the offset from syscon"?  What
is the problem that this is supposed to fix?

> is moved as a child node of syscon, vsel_reg and enable_reg has the
> absolute address because of the address translation that happens while
> creating device from device tree node.
> So avoid using platform_get_resource and use of_get_address in order to
> get only the offset (untranslated address) and populate these in
> vsel_reg and enable_reg.

This sounds like we're going in the wrong direction, we're moving from a
more generic API to a firmware specific one.  Why is this a good fix?
Kishon Vijay Abraham I Aug. 18, 2015, 5:53 a.m. UTC | #7
Hi Mark Brown,

On Friday 14 August 2015 11:30 PM, Mark Brown wrote:
> On Mon, Jul 27, 2015 at 04:54:09PM +0530, Kishon Vijay Abraham I wrote:
> 
>> vsel_reg and enable_reg of the pbias regulator descriptor should actually
>> have the offset from syscon. However after the pbias device tree node
> 
> I'm having a hard time understanding this statement, sorry.  What makes
> you say that they "shouild actually have the offset from syscon"?  What
> is the problem that this is supposed to fix?

The register to program pbias regulator is 0x4A002E00. The syscon base address
is 0x4a002000. So the vsel_reg and enable_reg should have the offset from
syscon base address. regulator_enable_regmap gets the base address from
'regmap' and offset from 'enable_reg' in order to program the pbias regulator.

But without this patch vsel_reg and enable_reg have the absolute address
instead of just the offset.
> 
>> is moved as a child node of syscon, vsel_reg and enable_reg has the
>> absolute address because of the address translation that happens while
>> creating device from device tree node.
>> So avoid using platform_get_resource and use of_get_address in order to
>> get only the offset (untranslated address) and populate these in
>> vsel_reg and enable_reg.
> 
> This sounds like we're going in the wrong direction, we're moving from a
> more generic API to a firmware specific one.  Why is this a good fix?

platform_get_resource can be used if we need the absolute address but here we
need only the offset.

Thanks
Kishon
--
To unsubscribe from this list: send the line "unsubscribe linux-omap" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Mark Brown Aug. 19, 2015, 6:11 p.m. UTC | #8
On Tue, Aug 18, 2015 at 11:23:54AM +0530, Kishon Vijay Abraham I wrote:
> On Friday 14 August 2015 11:30 PM, Mark Brown wrote:
> > On Mon, Jul 27, 2015 at 04:54:09PM +0530, Kishon Vijay Abraham I wrote:

> >> is moved as a child node of syscon, vsel_reg and enable_reg has the
> >> absolute address because of the address translation that happens while
> >> creating device from device tree node.
> >> So avoid using platform_get_resource and use of_get_address in order to
> >> get only the offset (untranslated address) and populate these in
> >> vsel_reg and enable_reg.

> > This sounds like we're going in the wrong direction, we're moving from a
> > more generic API to a firmware specific one.  Why is this a good fix?

> platform_get_resource can be used if we need the absolute address but here we
> need only the offset.

So substract this address from the start of the resource to get the
offset?  Or provide a wrapper function in the resource code which does
that.  What you're saying above is pretty much "this happens to work"
but my concern is that the solution that happens to work isn't really
what we want to do.
Kishon Vijay Abraham I Aug. 20, 2015, 5:51 a.m. UTC | #9
Hi Mark Brown,

On Wednesday 19 August 2015 11:41 PM, Mark Brown wrote:
> On Tue, Aug 18, 2015 at 11:23:54AM +0530, Kishon Vijay Abraham I wrote:
>> On Friday 14 August 2015 11:30 PM, Mark Brown wrote:
>>> On Mon, Jul 27, 2015 at 04:54:09PM +0530, Kishon Vijay Abraham I wrote:
> 
>>>> is moved as a child node of syscon, vsel_reg and enable_reg has the
>>>> absolute address because of the address translation that happens while
>>>> creating device from device tree node.
>>>> So avoid using platform_get_resource and use of_get_address in order to
>>>> get only the offset (untranslated address) and populate these in
>>>> vsel_reg and enable_reg.
> 
>>> This sounds like we're going in the wrong direction, we're moving from a
>>> more generic API to a firmware specific one.  Why is this a good fix?
> 
>> platform_get_resource can be used if we need the absolute address but here we
>> need only the offset.
> 
> So substract this address from the start of the resource to get the

That would mean from the offset (provided in dt) get the absolute address and
then again from the absolute address get the offset.
> offset?  Or provide a wrapper function in the resource code which does

Why not use 'of_get_address' which does the same thing? Moreover it's not a
resource we are dealing with here. It's a resource only for the syscon driver.
> that.  What you're saying above is pretty much "this happens to work"
> but my concern is that the solution that happens to work isn't really
> what we want to do.

Not just makes this work, this is also the most reasonable solution available IMHO.

The most ideal way would have been to use something like what Grygorii
mentioned to use syscon = <&scm_conf 0xe00> and then use the phandle to get the
offset. But then with this we'll be breaking older dtbs.

Thanks
Kishon


--
To unsubscribe from this list: send the line "unsubscribe linux-omap" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Mark Brown Aug. 20, 2015, 5:42 p.m. UTC | #10
On Thu, Aug 20, 2015 at 11:21:06AM +0530, Kishon Vijay Abraham I wrote:
> On Wednesday 19 August 2015 11:41 PM, Mark Brown wrote:
> > On Tue, Aug 18, 2015 at 11:23:54AM +0530, Kishon Vijay Abraham I wrote:

Please fix your mail client to word wrap within paragraphs.

> >> platform_get_resource can be used if we need the absolute address but here we
> >> need only the offset.

> > So substract this address from the start of the resource to get the

> That would mean from the offset (provided in dt) get the absolute address and
> then again from the absolute address get the offset.

Sure, that's how the Linux APIs work right now and why I'm suggesting
you might want a wrapper.

> > offset?  Or provide a wrapper function in the resource code which does

> Why not use 'of_get_address' which does the same thing? Moreover it's not a
> resource we are dealing with here. It's a resource only for the syscon driver.

This is how the OF description you've done is intended to be parsed and
hence is interpreted by the generic code, it's just a detail of the
syscon implementation that you need to translate it into an offset.

> > that.  What you're saying above is pretty much "this happens to work"
> > but my concern is that the solution that happens to work isn't really
> > what we want to do.

> Not just makes this work, this is also the most reasonable solution available IMHO.

In general moving to a lower level inteface is not usually a step
forward.  As far as I can tell the driver already has all the
information it needs from the more generic APIs, it's just not
interpreting it in the way that the APIs it's trying to use wants.  It
just needs to fix the way it interprets the data it's passing through.

> The most ideal way would have been to use something like what Grygorii
> mentioned to use syscon = <&scm_conf 0xe00> and then use the phandle to get the
> offset. But then with this we'll be breaking older dtbs.

There is no need to break older DTs, that would clearly be a bad idea.
Grygorii Strashko Aug. 25, 2015, 10:03 a.m. UTC | #11
Hi Mark,

On 08/19/2015 09:11 PM, Mark Brown wrote:
> On Tue, Aug 18, 2015 at 11:23:54AM +0530, Kishon Vijay Abraham I wrote:
>> On Friday 14 August 2015 11:30 PM, Mark Brown wrote:
>>> On Mon, Jul 27, 2015 at 04:54:09PM +0530, Kishon Vijay Abraham I wrote:
>
>>>> is moved as a child node of syscon, vsel_reg and enable_reg has the
>>>> absolute address because of the address translation that happens while
>>>> creating device from device tree node.
>>>> So avoid using platform_get_resource and use of_get_address in order to
>>>> get only the offset (untranslated address) and populate these in
>>>> vsel_reg and enable_reg.
>
>>> This sounds like we're going in the wrong direction, we're moving from a
>>> more generic API to a firmware specific one.  Why is this a good fix?
>
>> platform_get_resource can be used if we need the absolute address but here we
>> need only the offset.
>
> So substract this address from the start of the resource to get the
> offset?  Or provide a wrapper function in the resource code which does
> that.  

I'd be very appreciated if you have and can share any thought on
How can we get this absolute base address to substract?

Below is what we have in DT:

	l4_cfg: l4@4a000000 {
			compatible = "ti,dra7-l4-cfg", "simple-bus";
			#address-cells = <1>;
			#size-cells = <1>;
			ranges = <0 0x4a000000 0x22c000>;

	[GS] <=== 0x4a000000 is our top level l4 base address

			scm: scm@2000 {
				compatible = "ti,dra7-scm-core", "simple-bus";
				reg = <0x2000 0x2000>;
				#address-cells = <1>;
				#size-cells = <1>;
				ranges = <0 0x2000 0x2000>;

	[GS] <=== 0x4a002000 is our scm-core base address
	IORESOURCE_MEM: 0x4a002000 : 4A003FFF

				scm_conf: scm_conf@0 {
					compatible = "syscon", "simple-bus";
					reg = <0x0 0x1400>;
					#address-cells = <1>;
					#size-cells = <1>;

	[GS] <=== 0x4a002000 is our syscon base address
	IORESOURCE_MEM: 0x4a002000 : 4A0033FF

					pbias_regulator: pbias_regulator {
						compatible = "ti,pbias-omap";
						reg = <0xe00 0x4>;

	[GS] <=== 0x4a002E00 is our pbias base address
	IORESOURCE_MEM: 0x4a002E00 : 4A002E03
	Here we should use reg_offset=0xE00 as input parameter for regmap APIs.

						syscon = <&scm_conf>;
						pbias_mmc_reg: pbias_mmc_omap5 {
							regulator-name = "pbias_mmc_omap5";
							regulator-min-microvolt = <1800000>;
							regulator-max-microvolt = <3000000>;
						};
					};

					scm_conf_clocks: clocks {
						#address-cells = <1>;
						#size-cells = <0>;
					};
				};

As I understood, all of_address APIs/code is designed to parse/translate
addresses in top-bottom direction, and it looks nontrivial to get any kind
of base addresses from driver's side (except of its own address), because
it will require reverse DT parsing in bottom-top direction.
Maybe I missed smth?
Mark Brown Aug. 25, 2015, 1:50 p.m. UTC | #12
On Tue, Aug 25, 2015 at 01:03:04PM +0300, Grygorii Strashko wrote:
> On 08/19/2015 09:11 PM, Mark Brown wrote:

> > So substract this address from the start of the resource to get the
> > offset?  Or provide a wrapper function in the resource code which does
> > that.  

> I'd be very appreciated if you have and can share any thought on
> How can we get this absolute base address to substract?

Ask the syscon device for its resource?  Or have it provide an absolute
address based interface for that matter?
Kishon Vijay Abraham I Aug. 31, 2015, 10:44 a.m. UTC | #13
Hi Mark,

On Tuesday 25 August 2015 07:20 PM, Mark Brown wrote:
> On Tue, Aug 25, 2015 at 01:03:04PM +0300, Grygorii Strashko wrote:
>> On 08/19/2015 09:11 PM, Mark Brown wrote:
> 
>>> So substract this address from the start of the resource to get the
>>> offset?  Or provide a wrapper function in the resource code which does
>>> that.  
> 
>> I'd be very appreciated if you have and can share any thought on
>> How can we get this absolute base address to substract?
> 
> Ask the syscon device for its resource?  Or have it provide an absolute

Even if we get the absolute address of syscon, we have to do the
subtraction only for the newer dtbs (previous dtbs already have only the
offset). Do you recommend adding a new property to differentiate between
older dtbs and newer dtbs? Any other suggestions here?

> address based interface for that matter?

Syscon doesn't directly expose any API's to write to it's register.
Rather it uses regmap APIs to read/write to it's register. I'm not sure
if it's possible to add regmap APIs to write to a register with absolute
address. Any hints?

Thanks
Kishon
--
To unsubscribe from this list: send the line "unsubscribe linux-omap" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Mark Brown Aug. 31, 2015, 2:52 p.m. UTC | #14
On Mon, Aug 31, 2015 at 04:14:07PM +0530, Kishon Vijay Abraham I wrote:
> On Tuesday 25 August 2015 07:20 PM, Mark Brown wrote:
> > On Tue, Aug 25, 2015 at 01:03:04PM +0300, Grygorii Strashko wrote:
> >> On 08/19/2015 09:11 PM, Mark Brown wrote:

> >>> So substract this address from the start of the resource to get the
> >>> offset?  Or provide a wrapper function in the resource code which does
> >>> that.  
> > 
> >> I'd be very appreciated if you have and can share any thought on
> >> How can we get this absolute base address to substract?
> > 
> > Ask the syscon device for its resource?  Or have it provide an absolute
> 
> Even if we get the absolute address of syscon, we have to do the
> subtraction only for the newer dtbs (previous dtbs already have only the
> offset). Do you recommend adding a new property to differentiate between
> older dtbs and newer dtbs? Any other suggestions here?

Hang on.  This is the first I've heard of any DTs not just having
absolute addresses.  How does any of this work - has it ever worked, and
is the situation completely understood?  My original concern with this
was that I coudn't understand the commit log and your original response
seemed to indicate that we always have the absolute address :(  Perhaps
this is something to do with the brief mention of having moved the DT
node for some reason?

We at least need some sort of coherent explanation of the problem and a
comprehensible fix to go with it.  Right now it seems like things are
just being moved about to hide problems without either of these things
which seems like it makes the code less clear and more fragile.

> > address based interface for that matter?

> Syscon doesn't directly expose any API's to write to it's register.
> Rather it uses regmap APIs to read/write to it's register. I'm not sure
> if it's possible to add regmap APIs to write to a register with absolute
> address. Any hints?

Yes, I'm aware that it is regmap based!  What I am suggesting is that if
people are making DTs like yours with devices that are children of the
syscon then presumably it might be useful for it to allow client drivers
to pass absolute addresses in so that it can translate for them.
Kishon Vijay Abraham I Sept. 1, 2015, 9:40 a.m. UTC | #15
Hi Mark,

On Monday 31 August 2015 08:22 PM, Mark Brown wrote:
> On Mon, Aug 31, 2015 at 04:14:07PM +0530, Kishon Vijay Abraham I wrote:
>> On Tuesday 25 August 2015 07:20 PM, Mark Brown wrote:
>>> On Tue, Aug 25, 2015 at 01:03:04PM +0300, Grygorii Strashko wrote:
>>>> On 08/19/2015 09:11 PM, Mark Brown wrote:
> 
>>>>> So substract this address from the start of the resource to get the
>>>>> offset?  Or provide a wrapper function in the resource code which does
>>>>> that.  
>>>
>>>> I'd be very appreciated if you have and can share any thought on
>>>> How can we get this absolute base address to substract?
>>>
>>> Ask the syscon device for its resource?  Or have it provide an absolute
>>
>> Even if we get the absolute address of syscon, we have to do the
>> subtraction only for the newer dtbs (previous dtbs already have only the
>> offset). Do you recommend adding a new property to differentiate between
>> older dtbs and newer dtbs? Any other suggestions here?
> 
> Hang on.  This is the first I've heard of any DTs not just having
> absolute addresses.  How does any of this work - has it ever worked, and
> is the situation completely understood?  My original concern with this

Before commit d919501feffa8715147582c3ffce96fad0c7016f ARM: dts: dra7:
add minimal l4 bus layout with control module support, the dt was like

ocp {
	dra7_ctrl_general: tisyscon@4a002e00 {
		compatible = "syscon";
		reg = <0x4a002e00 0x7c>;
	};

	pbias_regulator: pbias_regulator {
		compatible = "ti,pbias-omap";
		reg = <0 0x4>;
		syscon = <&dra7_ctrl_general>;
	};
};

Here platform_get_resource in pbias driver returns '0' which is
populated in vsel_reg and enable_reg. And regulator_enable_regmap uses
the base address from tisyscon@4a002e00 which is '0x4a002e00' and offset
from enable_reg which is '0' inorder to write to the pbias register.

But after commit d919501fef, the dt became like this (after a couple of
fixes)

ocp {
	l4_cfg: l4@4a000000 {
		compatible = "ti,dra7-l4-cfg", "simple-bus";
		ranges = <0 0x4a000000 0x22c000>;

		scm: scm@2000 {
			compatible = "ti,dra7-scm-core", "simple-bus";
			reg = <0x2000 0x2000>;
			ranges = <0 0x2000 0x2000>;

			scm_conf: scm_conf@0 {
				compatible = "syscon", "simple-bus";
				reg = <0x0 0x1400>;
				ranges = <0 0x0 0x1400>;

				pbias_regulator: pbias_regulator {
					compatible = "ti,pbias-omap";
					reg = <0xe00 0x4>;
					syscon = <&scm_conf>;
                                };
			};
		};
	};
};

Here platform_get_resource in pbias driver returns '4a002e00' which is
populated in vsel_reg and enable_reg. And regulator_enable_regmap uses
the base address from scm_conf@0 which is '0x4a002000' and offset from
enable_reg which is '4a002e00' inorder to write to the pbias register
and it results in a abort.

> was that I coudn't understand the commit log and your original response
> seemed to indicate that we always have the absolute address :(  Perhaps

We started having the absolute address only after the dt change (commit
d919501fef and a couple of more dt fixes).

> this is something to do with the brief mention of having moved the DT
> node for some reason?
> 
> We at least need some sort of coherent explanation of the problem and a
> comprehensible fix to go with it.  Right now it seems like things are
> just being moved about to hide problems without either of these things
> which seems like it makes the code less clear and more fragile.

hmm.. IMO the actual problem was modelling the 'offset' as a resource
(by populating the offset in 'reg' property) which was added when the
initial pbias dt node was created. And now since the pbias dt node is
being moved around, it's causing inadvertent address translation
breaking the pbias driver. IMHO the value in 'reg' property of pbias dt
node should be treated as 'offset' instead of address 'resource' and
that's what my patch tried to do.
> 
>>> address based interface for that matter?
> 
>> Syscon doesn't directly expose any API's to write to it's register.
>> Rather it uses regmap APIs to read/write to it's register. I'm not sure
>> if it's possible to add regmap APIs to write to a register with absolute
>> address. Any hints?
> 
> Yes, I'm aware that it is regmap based!  What I am suggesting is that if
> people are making DTs like yours with devices that are children of the
> syscon then presumably it might be useful for it to allow client drivers
> to pass absolute addresses in so that it can translate for them.

Arnd, Lee?

Thanks
Kishon
--
To unsubscribe from this list: send the line "unsubscribe linux-omap" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Kishon Vijay Abraham I Sept. 1, 2015, 11:31 a.m. UTC | #16
Now fixed Lee Jones mail address!

On Tuesday 01 September 2015 03:10 PM, Kishon Vijay Abraham I wrote:
> Hi Mark,
> 
> On Monday 31 August 2015 08:22 PM, Mark Brown wrote:
>> On Mon, Aug 31, 2015 at 04:14:07PM +0530, Kishon Vijay Abraham I wrote:
>>> On Tuesday 25 August 2015 07:20 PM, Mark Brown wrote:
>>>> On Tue, Aug 25, 2015 at 01:03:04PM +0300, Grygorii Strashko wrote:
>>>>> On 08/19/2015 09:11 PM, Mark Brown wrote:
>>
>>>>>> So substract this address from the start of the resource to get the
>>>>>> offset?  Or provide a wrapper function in the resource code which does
>>>>>> that.  
>>>>
>>>>> I'd be very appreciated if you have and can share any thought on
>>>>> How can we get this absolute base address to substract?
>>>>
>>>> Ask the syscon device for its resource?  Or have it provide an absolute
>>>
>>> Even if we get the absolute address of syscon, we have to do the
>>> subtraction only for the newer dtbs (previous dtbs already have only the
>>> offset). Do you recommend adding a new property to differentiate between
>>> older dtbs and newer dtbs? Any other suggestions here?
>>
>> Hang on.  This is the first I've heard of any DTs not just having
>> absolute addresses.  How does any of this work - has it ever worked, and
>> is the situation completely understood?  My original concern with this
> 
> Before commit d919501feffa8715147582c3ffce96fad0c7016f ARM: dts: dra7:
> add minimal l4 bus layout with control module support, the dt was like
> 
> ocp {
> 	dra7_ctrl_general: tisyscon@4a002e00 {
> 		compatible = "syscon";
> 		reg = <0x4a002e00 0x7c>;
> 	};
> 
> 	pbias_regulator: pbias_regulator {
> 		compatible = "ti,pbias-omap";
> 		reg = <0 0x4>;
> 		syscon = <&dra7_ctrl_general>;
> 	};
> };
> 
> Here platform_get_resource in pbias driver returns '0' which is
> populated in vsel_reg and enable_reg. And regulator_enable_regmap uses
> the base address from tisyscon@4a002e00 which is '0x4a002e00' and offset
> from enable_reg which is '0' inorder to write to the pbias register.
> 
> But after commit d919501fef, the dt became like this (after a couple of
> fixes)
> 
> ocp {
> 	l4_cfg: l4@4a000000 {
> 		compatible = "ti,dra7-l4-cfg", "simple-bus";
> 		ranges = <0 0x4a000000 0x22c000>;
> 
> 		scm: scm@2000 {
> 			compatible = "ti,dra7-scm-core", "simple-bus";
> 			reg = <0x2000 0x2000>;
> 			ranges = <0 0x2000 0x2000>;
> 
> 			scm_conf: scm_conf@0 {
> 				compatible = "syscon", "simple-bus";
> 				reg = <0x0 0x1400>;
> 				ranges = <0 0x0 0x1400>;
> 
> 				pbias_regulator: pbias_regulator {
> 					compatible = "ti,pbias-omap";
> 					reg = <0xe00 0x4>;
> 					syscon = <&scm_conf>;
>                                 };
> 			};
> 		};
> 	};
> };
> 
> Here platform_get_resource in pbias driver returns '4a002e00' which is
> populated in vsel_reg and enable_reg. And regulator_enable_regmap uses
> the base address from scm_conf@0 which is '0x4a002000' and offset from
> enable_reg which is '4a002e00' inorder to write to the pbias register
> and it results in a abort.
> 
>> was that I coudn't understand the commit log and your original response
>> seemed to indicate that we always have the absolute address :(  Perhaps
> 
> We started having the absolute address only after the dt change (commit
> d919501fef and a couple of more dt fixes).
> 
>> this is something to do with the brief mention of having moved the DT
>> node for some reason?
>>
>> We at least need some sort of coherent explanation of the problem and a
>> comprehensible fix to go with it.  Right now it seems like things are
>> just being moved about to hide problems without either of these things
>> which seems like it makes the code less clear and more fragile.
> 
> hmm.. IMO the actual problem was modelling the 'offset' as a resource
> (by populating the offset in 'reg' property) which was added when the
> initial pbias dt node was created. And now since the pbias dt node is
> being moved around, it's causing inadvertent address translation
> breaking the pbias driver. IMHO the value in 'reg' property of pbias dt
> node should be treated as 'offset' instead of address 'resource' and
> that's what my patch tried to do.
>>
>>>> address based interface for that matter?
>>
>>> Syscon doesn't directly expose any API's to write to it's register.
>>> Rather it uses regmap APIs to read/write to it's register. I'm not sure
>>> if it's possible to add regmap APIs to write to a register with absolute
>>> address. Any hints?
>>
>> Yes, I'm aware that it is regmap based!  What I am suggesting is that if
>> people are making DTs like yours with devices that are children of the
>> syscon then presumably it might be useful for it to allow client drivers
>> to pass absolute addresses in so that it can translate for them.
> 
> Arnd, Lee?
> 
> Thanks
> Kishon
> 
--
To unsubscribe from this list: send the line "unsubscribe linux-omap" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Tony Lindgren Sept. 1, 2015, 2:17 p.m. UTC | #17
Hi,

I think the fix is rather easy here.. See below.

* Kishon Vijay Abraham I <kishon@ti.com> [150901 02:43]:
> 
> Before commit d919501feffa8715147582c3ffce96fad0c7016f ARM: dts: dra7:
> add minimal l4 bus layout with control module support, the dt was like
> 
> ocp {
> 	dra7_ctrl_general: tisyscon@4a002e00 {
> 		compatible = "syscon";
> 		reg = <0x4a002e00 0x7c>;
> 	};
> 
> 	pbias_regulator: pbias_regulator {
> 		compatible = "ti,pbias-omap";
> 		reg = <0 0x4>;
> 		syscon = <&dra7_ctrl_general>;
> 	};
> };

Yes the reg = <0 0x4> above is wrong, it's not an offset from the
ocp but from the syscon base.
 
> But after commit d919501fef, the dt became like this (after a couple of
> fixes)
> 
> ocp {
> 	l4_cfg: l4@4a000000 {
> 		compatible = "ti,dra7-l4-cfg", "simple-bus";
> 		ranges = <0 0x4a000000 0x22c000>;
> 
> 		scm: scm@2000 {
> 			compatible = "ti,dra7-scm-core", "simple-bus";
> 			reg = <0x2000 0x2000>;
> 			ranges = <0 0x2000 0x2000>;
> 
> 			scm_conf: scm_conf@0 {
> 				compatible = "syscon", "simple-bus";
> 				reg = <0x0 0x1400>;
> 				ranges = <0 0x0 0x1400>;
> 
> 				pbias_regulator: pbias_regulator {
> 					compatible = "ti,pbias-omap";
> 					reg = <0xe00 0x4>;
> 					syscon = <&scm_conf>;
>                                 };
> 			};
> 		};
> 	};
> };

And here we properly describe the hardware interconnect layout and
of_ioremap and friends do the right thing. And reg = <0xxe00 0x4>
is correct offset from the scm_conf base.

Why don't you just make reg unused for pbias_regulator since
we already use regmap for this driver?

Then in the pbias driver just define the register offset from
the syscon base? You may need to set it based on the compatible
value, but it's not like it's going to change for SoC.

If we eventually add some API to calculate reg base offset
from the syscon base it's easy to update the driver to use
that.

Cheers,

Tony
--
To unsubscribe from this list: send the line "unsubscribe linux-omap" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Mark Brown Sept. 1, 2015, 6:36 p.m. UTC | #18
On Tue, Sep 01, 2015 at 07:17:21AM -0700, Tony Lindgren wrote:

> Why don't you just make reg unused for pbias_regulator since
> we already use regmap for this driver?

> Then in the pbias driver just define the register offset from
> the syscon base? You may need to set it based on the compatible
> value, but it's not like it's going to change for SoC.

> If we eventually add some API to calculate reg base offset
> from the syscon base it's easy to update the driver to use
> that.

That'd work.  The other thing I was thinking we could do is to get
syscon to treat any excessively large address that gets passed in that
looks like an absolute address appropriately.
Tony Lindgren Sept. 1, 2015, 6:56 p.m. UTC | #19
* Mark Brown <broonie@kernel.org> [150901 11:40]:
> On Tue, Sep 01, 2015 at 07:17:21AM -0700, Tony Lindgren wrote:
> 
> > Why don't you just make reg unused for pbias_regulator since
> > we already use regmap for this driver?
> 
> > Then in the pbias driver just define the register offset from
> > the syscon base? You may need to set it based on the compatible
> > value, but it's not like it's going to change for SoC.
> 
> > If we eventually add some API to calculate reg base offset
> > from the syscon base it's easy to update the driver to use
> > that.
> 
> That'd work.  The other thing I was thinking we could do is to get
> syscon to treat any excessively large address that gets passed in that
> looks like an absolute address appropriately.

Hmm wouldn't that get messy for 64-bit :) How about something
like:

unsigned long syscon_regmap_get_offset(struct regmap *syscon,
					void __iomem *base)

Not sure if that's something that some drivers would start to
misuse with read/writel though.. Presumably not if the driver
already is using syscon.

Regards,

Tony
--
To unsubscribe from this list: send the line "unsubscribe linux-omap" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Mark Brown Sept. 2, 2015, 11:15 a.m. UTC | #20
On Tue, Sep 01, 2015 at 11:56:06AM -0700, Tony Lindgren wrote:
> * Mark Brown <broonie@kernel.org> [150901 11:40]:

> > That'd work.  The other thing I was thinking we could do is to get
> > syscon to treat any excessively large address that gets passed in that
> > looks like an absolute address appropriately.

> Hmm wouldn't that get messy for 64-bit :) How about something
> like:

Meh, it'd probably be fine - I was thinking falling back to trying to
substract the base address if the passed address was out of bounds.
It's not super elegant though, something that directly does the right
thing would be better.

> unsigned long syscon_regmap_get_offset(struct regmap *syscon,
> 					void __iomem *base)

> Not sure if that's something that some drivers would start to
> misuse with read/writel though.. Presumably not if the driver
> already is using syscon.

It should be really easy to spot abuse I'd hope.

Patch
diff mbox

diff --git a/drivers/regulator/pbias-regulator.c b/drivers/regulator/pbias-regulator.c
index bd2b75c..a24cb43 100644
--- a/drivers/regulator/pbias-regulator.c
+++ b/drivers/regulator/pbias-regulator.c
@@ -22,6 +22,7 @@ 
 #include <linux/regulator/driver.h>
 #include <linux/regulator/machine.h>
 #include <linux/regulator/of_regulator.h>
+#include <linux/of_address.h>
 #include <linux/regmap.h>
 #include <linux/slab.h>
 #include <linux/of.h>
@@ -108,12 +109,14 @@  static int pbias_regulator_probe(struct platform_device *pdev)
 {
 	struct device_node *np = pdev->dev.of_node;
 	struct pbias_regulator_data *drvdata;
-	struct resource *res;
 	struct regulator_config cfg = { };
 	struct regmap *syscon;
 	const struct pbias_reg_info *info;
 	int ret = 0;
 	int count, idx, data_idx = 0;
+	const __be32 *addrp;
+	int ns;
+	unsigned int reg;
 
 	count = of_regulator_match(&pdev->dev, np, pbias_matches,
 						PBIAS_NUM_REGS);
@@ -141,10 +144,13 @@  static int pbias_regulator_probe(struct platform_device *pdev)
 		if (!info)
 			return -ENODEV;
 
-		res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-		if (!res)
+		addrp = of_get_address(np, 0, NULL, NULL);
+		if (!addrp)
 			return -EINVAL;
 
+		ns = of_n_size_cells(np);
+		reg = of_read_number(addrp, ns);
+
 		drvdata[data_idx].syscon = syscon;
 		drvdata[data_idx].info = info;
 		drvdata[data_idx].desc.name = info->name;
@@ -154,9 +160,9 @@  static int pbias_regulator_probe(struct platform_device *pdev)
 		drvdata[data_idx].desc.volt_table = pbias_volt_table;
 		drvdata[data_idx].desc.n_voltages = 2;
 		drvdata[data_idx].desc.enable_time = info->enable_time;
-		drvdata[data_idx].desc.vsel_reg = res->start;
+		drvdata[data_idx].desc.vsel_reg = reg;
 		drvdata[data_idx].desc.vsel_mask = info->vmode;
-		drvdata[data_idx].desc.enable_reg = res->start;
+		drvdata[data_idx].desc.enable_reg = reg;
 		drvdata[data_idx].desc.enable_mask = info->enable_mask;
 		drvdata[data_idx].desc.enable_val = info->enable;