Skip to contentSkip to conversation

how to use "ranges" in device tree

query Jisheng Zhang 4 participants 9 messages Apr 16, 2015 – Apr 17, 2015 PCI

lore
Share & tools
lore
#0 lore raw

Hi all,

I didn't fully understand the "ranges" usage, here is one situation which I dunno how to handle.

In arch/arm/boot/dts/berlin2q.dtsi, we describe the /soc ranges as

ranges = <0 0xf7000000 0x1000000>;

That's fine. Now there's a pci device based on pcie-designware.c which prefer put "config" space in reg. But the config space starts at 0xe0000000, due to the /soc ranges, the "config" space following pcie node is not correct in fact.

soc {
	ranges = <0 0xf7000000 0x1000000>;
	...
	pcie: pcie at e40000 {
		compatible = "...";
		reg = <0xe40000 0x10000>, <0xe0000000 0x8000000>;
		reg-names = "dbi", "pad", "config";
		...
	};
	...
};

How to define the "config" space in this situation? Did we need to change the /soc ranges as the following?

soc {
	ranges;
}

Thanks in advance,
Jisheng

#1 lore raw

Hi,

Well, I'm not sure..
But in my understanding..configuration range might be support both "ranges" and "config" of reg.

Quoted 13 lines · Jisheng Zhang

Hi all,

I didn't fully understand the "ranges" usage, here is one situation which I dunno how to handle.

In arch/arm/boot/dts/berlin2q.dtsi, we describe the /soc ranges as

ranges = <0 0xf7000000 0x1000000>;

That's fine. Now there's a pci device based on pcie-designware.c which prefer put "config" space in reg. But the config space starts at 0xe0000000, due to the /soc ranges, the "config" space following pcie node is not correct in fact.

Quoted 11 lines
soc {
	ranges = <0 0xf7000000 0x1000000>;
	...
	pcie: pcie at e40000 {
		compatible = "...";
		reg = <0xe40000 0x10000>, <0xe0000000 0x8000000>;
		reg-names = "dbi", "pad", "config";
		...
	};
	...
};

According to yours,

reg = <0xe40000 0x1000 /* dbi */

	0xe000000 0x800000	/* pad */
	0xf7000000 0x1000000>;	/* config ? */

If there is not "config" into reg-names, it should be tried to find it into "ranges".

If my understanding is wrong, let me know, plz.

In my case,

	reg = <0x156b0000 0x1000
		0x15680000 0x1000
		0x0c000000 0x1000>;
	reg-names = "elbi", "phy", "config";

	ranges = < ..... /* downstream I/O */
		  ...... /* non-prefetchable memory */

Best Regards,
Jaehoon Chung

Quoted 16 lines

How to define the "config" space in this situation? Did we need to change the /soc ranges as the following?

soc {
	ranges;
}

Thanks in advance,
Jisheng

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel at lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

#2 lore raw

Hi Jaehoon,

Quoted 31 lines · On Thu, 16 Apr 2015 15:59:45 -0700 Jaehoon Chung <[email protected]> wrote:

Hi,

Well, I'm not sure..
But in my understanding..configuration range might be support both "ranges" and "config" of reg.

Quoted 13 lines · Jisheng Zhang

Hi all,

I didn't fully understand the "ranges" usage, here is one situation which I dunno how to handle.

In arch/arm/boot/dts/berlin2q.dtsi, we describe the /soc ranges as

ranges = <0 0xf7000000 0x1000000>;

That's fine. Now there's a pci device based on pcie-designware.c which prefer put "config" space in reg. But the config space starts at 0xe0000000, due to the /soc ranges, the "config" space following pcie node is not correct in fact.

Quoted 11 lines
soc {
	ranges = <0 0xf7000000 0x1000000>;
	...
	pcie: pcie at e40000 {
		compatible = "...";
		reg = <0xe40000 0x10000>, <0xe0000000 0x8000000>;
		reg-names = "dbi", "pad", "config";
		...
	};
	...
};
Quoted 5 lines

According to yours,

reg = <0xe40000 0x1000 /* dbi */

	0xe000000 0x800000	/* pad */
	0xf7000000 0x1000000>;	/* config ? */

oops, there's no pad at all, dbi starts at 0xf7e40000, config space starts at 0xe0000000

so my pcie in my understanding is

pcie: pcie at e40000 {
	compatible = "...";
	reg = <0xe40000 0x10000>, <0xe0000000 0x8000000>;
	reg-names = "dbi", "config";
};

But the "/soc" ranges is defined as "<0 0xf7000000 0x1000000>;", so the config space in the above dts is not correct.

My solution is change the "/soc" ranges as following:

soc {
	ranges;
	...
};

Is there any elegant solutions for this situation?

Quoted 2 lines

If there is not "config" into reg-names, it should be tried to find it into "ranges".

The pcie-designware driver prefers users define config space in "reg"

Thanks for your help,
Jisheng

Quoted 34 lines

If my understanding is wrong, let me know, plz.

In my case,

	reg = <0x156b0000 0x1000
		0x15680000 0x1000
		0x0c000000 0x1000>;
	reg-names = "elbi", "phy", "config";

	ranges = < ..... /* downstream I/O */
		  ...... /* non-prefetchable memory */

Best Regards,
Jaehoon Chung

Quoted 16 lines

How to define the "config" space in this situation? Did we need to change the /soc ranges as the following?

soc {
	ranges;
}

Thanks in advance,
Jisheng

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel at lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

#3 lore raw

Hi all,

I got the solution, the ranges can define two or more ranges. What I need to do is just add ranges for 0xe0000000 - 0xf0000000 as the following:

soc {
	ranges = <0 0xf7000000 0x1000000
		  0xe0000000 0xe0000000 0x10000000>;  //add this line
	...
	pcie: pcie at e40000 {
		...
		reg = <0xe40000 0x10000>, <0xe0000000 0x8000000>;
		reg-names = "dbi", "pad", "config";
		...
	};
}

Now, we can get the config space correctly.

Thanks,
Jisheng

Quoted 107 lines · On Thu, 16 Apr 2015 19:24:13 -0700 Jisheng Zhang <[email protected]> wrote:

Hi Jaehoon,

Quoted 31 lines · On Thu, 16 Apr 2015 15:59:45 -0700 Jaehoon Chung <[email protected]> wrote:

Hi,

Well, I'm not sure..
But in my understanding..configuration range might be support both "ranges" and "config" of reg.

Quoted 13 lines · Jisheng Zhang

Hi all,

I didn't fully understand the "ranges" usage, here is one situation which I dunno how to handle.

In arch/arm/boot/dts/berlin2q.dtsi, we describe the /soc ranges as

ranges = <0 0xf7000000 0x1000000>;

That's fine. Now there's a pci device based on pcie-designware.c which prefer put "config" space in reg. But the config space starts at 0xe0000000, due to the /soc ranges, the "config" space following pcie node is not correct in fact.

Quoted 11 lines
soc {
	ranges = <0 0xf7000000 0x1000000>;
	...
	pcie: pcie at e40000 {
		compatible = "...";
		reg = <0xe40000 0x10000>, <0xe0000000 0x8000000>;
		reg-names = "dbi", "pad", "config";
		...
	};
	...
};
Quoted 5 lines

According to yours,

reg = <0xe40000 0x1000 /* dbi */

	0xe000000 0x800000	/* pad */
	0xf7000000 0x1000000>;	/* config ? */

oops, there's no pad at all, dbi starts at 0xf7e40000, config space starts at 0xe0000000

so my pcie in my understanding is

pcie: pcie at e40000 {
	compatible = "...";
	reg = <0xe40000 0x10000>, <0xe0000000 0x8000000>;
	reg-names = "dbi", "config";
};

But the "/soc" ranges is defined as "<0 0xf7000000 0x1000000>;", so the config space in the above dts is not correct.

My solution is change the "/soc" ranges as following:

soc {
	ranges;
	...
};

Is there any elegant solutions for this situation?

Quoted 2 lines

If there is not "config" into reg-names, it should be tried to find it into "ranges".

The pcie-designware driver prefers users define config space in "reg"

Thanks for your help,
Jisheng

Quoted 34 lines

If my understanding is wrong, let me know, plz.

In my case,

	reg = <0x156b0000 0x1000
		0x15680000 0x1000
		0x0c000000 0x1000>;
	reg-names = "elbi", "phy", "config";

	ranges = < ..... /* downstream I/O */
		  ...... /* non-prefetchable memory */

Best Regards,
Jaehoon Chung

Quoted 16 lines

How to define the "config" space in this situation? Did we need to change the /soc ranges as the following?

soc {
	ranges;
}

Thanks in advance,
Jisheng

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel at lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

#4 lore raw
Quoted 17 lines · On Friday 17 April 2015 11:50:16 Jisheng Zhang wrote:

Hi all,

I got the solution, the ranges can define two or more ranges. What I need to do is just add ranges for 0xe0000000 - 0xf0000000 as the following:

soc {
        ranges = <0 0xf7000000 0x1000000
                  0xe0000000 0xe0000000 0x10000000>;  //add this line
        ...
        pcie: pcie at e40000 {
                ...
                reg = <0xe40000 0x10000>, <0xe0000000 0x8000000>;
                reg-names = "dbi", "pad", "config";
                ...
        };
}
Quoted 2 lines

Now, we can get the config space correctly.

This will work correctly, but it is not a very clean solution, because you define an intermediate address space that has some part of the bus mapped to zero, and another part mapped to a high address that matches the address the CPU sees.

A nicer (but a little more complicated) way to do this would be to use #address-cells=<2> in the parent bus and use that to enumerate the address ranges that get passed through:

soc {
	#address-cells=<2>;
	#size-cells=<1>;
        ranges = <0 0  0xf7000000  0x1000000>, /* 0: the normal regs */
		  <1 0  0xe0000000 0x16000000>; /* 1: reallocated registers for PCI */

	pcie at e40000 {
		#address-cells = <3>;
		#size-cells = <2>;
		reg = <0 0xe40000 0x10000>, <1 0 0x8000000>;

		/* memory space at pci address 0xf0000000, cpu address 0xf0000000, 
		   bus address 0x10000000 */
		ranges = <0x02000000 0 0xf0000000   0 0x10000000   0 0x06000000>;
	};

	...
};

The ranges property inside of the pcie node here should match whatever you program into the inbound mapping registers of the PCIe host controller (if any).

Arnd

#5 lore raw

Dear Arnd,

Quoted 18 lines · On Fri, 17 Apr 2015 01:32:00 -0700 Arnd Bergmann <[email protected]> wrote:
Quoted 17 lines · On Friday 17 April 2015 11:50:16 Jisheng Zhang wrote:

Hi all,

I got the solution, the ranges can define two or more ranges. What I need to do is just add ranges for 0xe0000000 - 0xf0000000 as the following:

soc {
        ranges = <0 0xf7000000 0x1000000
                  0xe0000000 0xe0000000 0x10000000>;  //add this line
        ...
        pcie: pcie at e40000 {
                ...
                reg = <0xe40000 0x10000>, <0xe0000000 0x8000000>;
                reg-names = "dbi", "pad", "config";
                ...
        };
}
Quoted 7 lines
Quoted 2 lines

Now, we can get the config space correctly.

This will work correctly, but it is not a very clean solution, because you define an intermediate address space that has some part of the bus mapped to zero, and another part mapped to a high address that matches the address the CPU sees.

Seems I had a better understanding of the "ranges" usage, thanks for your explanation.

Quoted 3 lines

A nicer (but a little more complicated) way to do this would be to use #address-cells=<2> in the parent bus and use that to enumerate the

In this way, we need to change all device nodes' "reg" in arch/arm/boot/dts/berlin2q.dtsi? And in arm64 case, we should use #address-cells=<3>?

If above two answer is yes, setting "ranges = <..>" seems add complexity in my humble opinion. So is it better to use 1:1 mapping by "ranges;" in "/soc" node?

Thanks a lot,
Jisheng

Quoted 25 lines

address ranges that get passed through:

soc {
	#address-cells=<2>;
	#size-cells=<1>;
        ranges = <0 0  0xf7000000  0x1000000>, /* 0: the normal regs */
		  <1 0  0xe0000000 0x16000000>; /* 1: reallocated registers for PCI */

	pcie at e40000 {
		#address-cells = <3>;
		#size-cells = <2>;
		reg = <0 0xe40000 0x10000>, <1 0 0x8000000>;

		/* memory space at pci address 0xf0000000, cpu address 0xf0000000, 
		   bus address 0x10000000 */
		ranges = <0x02000000 0 0xf0000000   0 0x10000000   0 0x06000000>;
	};

	...
};

The ranges property inside of the pcie node here should match whatever you program into the inbound mapping registers of the PCIe host controller (if any).

Arnd

#6 lore raw
Quoted 5 lines · On Friday 17 April 2015 16:45:46 Jisheng Zhang wrote:
Quoted 3 lines

A nicer (but a little more complicated) way to do this would be to use #address-cells=<2> in the parent bus and use that to enumerate the

In this way, we need to change all device nodes' "reg" in arch/arm/boot/dts/berlin2q.dtsi?

Correct

Quoted 1 line

And in arm64 case, we should use #address-cells=<3>?

It depends: if any of the address spaces within are 64-bit wide, yes, otherwise you can make the virtual spaces just 2-cell wide.

Quoted 2 lines

If above two answer is yes, setting "ranges = <..>" seems add complexity in my humble opinion. So is it better to use 1:1 mapping by "ranges;" in "/soc" node?

I agree, it gets a little awkward at that point. A better solution here would be to take the PCI node out of /soc and move it to the root node. This has the slight downside that you end up with registers being part of /soc and /pci, but that's perfectly legal.

Arnd

#7 lore raw
In reply to Jisheng Zhang
Quoted 2 lines · Jisheng Zhang

I got the solution, the ranges can define two or more ranges. What I need to do is just add ranges for 0xe0000000 - 0xf0000000 as the following:

Jisheng,

the beauty of ranges property often reminds me of perl code: once you stop looking at it, you cannot recall how you did it nor how that has ever worked.

What the ranges property does is to map an address range back to the address space of the parent node. In this case, the parent node of "soc" is the root node with "ranges;", i.e. 1:1 mapping.

Quoted 2 lines
soc {
	ranges = <0 0xf7000000 0x1000000

The line above maps 0x1000000 bytes starting@0 back to 0xf7000000 of the parent node's address space. This allows us to leave the 0xf7 prefix for each of the internal bus nodes below.

Quoted 1 line
		  0xe0000000 0xe0000000 0x10000000>;  //add this line

You could have chosen any address as the first value that does not interfere with 0x0-0x1000000 of the first range, e.g.

0x20000000 0xe0000000 0x10000000

would allow you to access the pcie memory space at 0x20000000 in nodes below that ranges property.

Sebastian

Quoted 9 lines
	pcie: pcie at e40000 {
		...
		reg = <0xe40000 0x10000>, <0xe0000000 0x8000000>;
		reg-names = "dbi", "pad", "config";
		...
	};
}

Now, we can get the config space correctly.

#8 lore raw
Quoted 23 lines · On Fri, 17 Apr 2015 01:38:16 -0700 Sebastian Hesselbarth…
Quoted 2 lines · Jisheng Zhang

I got the solution, the ranges can define two or more ranges. What I need to do is just add ranges for 0xe0000000 - 0xf0000000 as the following:

Jisheng,

the beauty of ranges property often reminds me of perl code: once you stop looking at it, you cannot recall how you did it nor how that has ever worked.

What the ranges property does is to map an address range back to the address space of the parent node. In this case, the parent node of "soc" is the root node with "ranges;", i.e. 1:1 mapping.

Quoted 2 lines
soc {
	ranges = <0 0xf7000000 0x1000000

The line above maps 0x1000000 bytes starting at 0 back to 0xf7000000 of the parent node's address space. This allows us to leave the 0xf7 prefix for each of the internal bus nodes below.

Quoted 1 line
		  0xe0000000 0xe0000000 0x10000000>;  //add this line
Quoted 8 lines

You could have chosen any address as the first value that does not interfere with 0x0-0x1000000 of the first range, e.g.

0x20000000 0xe0000000 0x10000000

would allow you to access the pcie memory space at 0x20000000 in nodes below that ranges property.

Thanks for this explanation which gives me good guide about the "ranges" usage.

Quoted 11 lines
Quoted 10 lines
	pcie: pcie at e40000 {
		...
		reg = <0xe40000 0x10000>, <0xe0000000 0x8000000>;
		reg-names = "dbi", "pad", "config";
		...
	};
}

Now, we can get the config space correctly.