Skip to contentSkip to conversation

ARM: tegra: Add PCIe support

PATCH Superseded Thierry Reding 7 participants 92 messages Aug 18, 2014 – Aug 27, 2014 1 message not in the archive

Subsystems (7)

v1 of 2 Superseded Latest is v2 →

lore
Share & tools
lore
#0 lore raw

cover ARM: tegra: Add PCIe support

From: Thierry Reding <[email protected]>

This series adds PCIe support for Tegra20, Tegra30 and Tegra124. The size is mostly due to the large number of infrastructure that's added (libfdt, Tegra specific drivers required by the PCIe driver).

Patches 1-5 add various FDT helpers to make it easier to parse complex device trees.

Patch 6 is a minor cleanup to the PCI command that prevents a spew of error messages if a bus does not exist. Patch 7 modifies the PCI enumeration code to honor theh restrictions encoded within a host controller driver's pci_ski_dev() implementation. This is required to prevent exceptions from the NVIDIA Tegra PCIe controller.

Patch 8 imports the pr_fmt() macro used within the Linux kernel to reduce the number of characters consumed by literal strings by allowing a source file to specify a prefix or suffix that should be applied to all format strings in the file. It is currently used by the debug() and error() macros.

Patches 9-14 are preparatory work for the Tegra PCIe controller. They add missing clock driver functionality as well as drivers for the Tegra powergate and XUSB pad controller blocks.

Patch 15 adds the PCIe controller driver for Tegra20, Tegra30 and Tegra124.

Finally, patches 16-23 add the various device tree nodes and configuration options to enable PCIe on the TrimSlice (Tegra20), Beaver, Cardhu (Tegra30) and Jetson TK1 (Tegra124) boards.

The above boards all have an ethernet NIC connected to PCIe, which is what I tested with. There are some cache maintenance issues related to that, but a separate series will shortly be sent out to address those.

Thierry

Thierry Reding (23):
fdt: Add functions to query a node's #address- and #size-cells
fdt: Add a function to get the index of a string
fdt: Add resource parsing functions
fdt: Add a function to return PCI BDF triplet
fdt: Add a subnodes iterator macro
pci: Abort early if bus does not exist
pci: Honour pci_skip_dev()
Add pr_fmt() macro
ARM: tegra: Implement tegra_plle_enable()
ARM: tegra: Provide PCIEXCLK reset ID
ARM: tegra: Implement powergate support
ARM: tegra: Implement XUSB pad controller
ARM: tegra: Add XUSB pad controller on Tegra124
ARM: tegra: Enable XUSB pad controller on Jetson TK1
pci: tegra: Add Tegra PCIe driver
ARM: tegra: Add Tegra20 PCIe device tree node
ARM: tegra: Enable PCIe on TrimSlice
ARM: tegra: Add Tegra30 PCIe device tree node
ARM: tegra: Enable PCIe on Beaver
ARM: tegra: Enable PCIe on Cardhu
ARM: tegra: Add GIC for Tegra124
ARM: tegra: Add Tegra124 PCIe device tree node
ARM: tegra: Enable PCIe on Jetson TK1

 arch/arm/cpu/tegra-common/Makefile               |    2 +
 arch/arm/cpu/tegra-common/powergate.c            |   80 ++
 arch/arm/cpu/tegra-common/xusb-padctl.c          |   39 +
 arch/arm/cpu/tegra124-common/Makefile            |    1 +
 arch/arm/cpu/tegra124-common/clock.c             |  109 +++
 arch/arm/cpu/tegra124-common/xusb-padctl.c       |  766 +++++++++++++++
 arch/arm/cpu/tegra20-common/clock.c              |  141 ++-
 arch/arm/cpu/tegra30-common/clock.c              |  155 +++
 arch/arm/dts/tegra124-jetson-tk1.dts             |  373 +++++++
 arch/arm/dts/tegra124.dtsi                       |   90 ++
 arch/arm/dts/tegra20-trimslice.dts               |   35 +
 arch/arm/dts/tegra20.dtsi                        |   56 ++
 arch/arm/dts/tegra30-beaver.dts                  |  166 ++++
 arch/arm/dts/tegra30-cardhu.dts                  |  357 +++++++
 arch/arm/dts/tegra30.dtsi                        |   71 ++
 arch/arm/include/asm/arch-tegra/powergate.h      |   27 +
 arch/arm/include/asm/arch-tegra/xusb-padctl.h    |   14 +
 arch/arm/include/asm/arch-tegra114/powergate.h   |    6 +
 arch/arm/include/asm/arch-tegra114/xusb-padctl.h |    6 +
 arch/arm/include/asm/arch-tegra124/clock.h       |    2 +
 arch/arm/include/asm/arch-tegra124/powergate.h   |    6 +
 arch/arm/include/asm/arch-tegra124/xusb-padctl.h |    6 +
 arch/arm/include/asm/arch-tegra20/clock-tables.h |    2 +-
 arch/arm/include/asm/arch-tegra20/clock.h        |    2 +
 arch/arm/include/asm/arch-tegra20/powergate.h    |    6 +
 arch/arm/include/asm/arch-tegra20/xusb-padctl.h  |    6 +
 arch/arm/include/asm/arch-tegra30/clock.h        |    2 +
 arch/arm/include/asm/arch-tegra30/powergate.h    |    6 +
 arch/arm/include/asm/arch-tegra30/xusb-padctl.h  |    6 +
 board/compulab/trimslice/trimslice.c             |    8 +
 board/nvidia/cardhu/cardhu.c                     |   56 ++
 board/nvidia/common/board.c                      |    3 +
 board/nvidia/jetson-tk1/jetson-tk1.c             |  218 +++++
 common/cmd_pci.c                                 |    7 +
 drivers/pci/Makefile                             |    1 +
 drivers/pci/pci.c                                |    3 +
 drivers/pci/pci_tegra.c                          | 1133 ++++++++++++++++++++++
 include/common.h                                 |   14 +-
 include/configs/beaver.h                         |   10 +
 include/configs/cardhu.h                         |   10 +
 include/configs/jetson-tk1.h                     |   10 +
 include/configs/trimslice.h                      |   10 +
 include/dt-bindings/clock/tegra124-car.h         |  341 +++++++
 include/dt-bindings/clock/tegra20-car.h          |  158 +++
 include/dt-bindings/clock/tegra30-car.h          |  265 +++++
 include/dt-bindings/pinctrl/pinctrl-tegra-xusb.h |    7 +
 include/fdtdec.h                                 |   64 ++
 include/libfdt.h                                 |   59 ++
 include/pci.h                                    |    1 +
 lib/fdtdec.c                                     |   61 ++
 lib/libfdt/fdt_ro.c                              |   64 ++
 51 files changed, 5033 insertions(+), 8 deletions(-)
 create mode 100644 arch/arm/cpu/tegra-common/powergate.c
 create mode 100644 arch/arm/cpu/tegra-common/xusb-padctl.c
 create mode 100644 arch/arm/cpu/tegra124-common/xusb-padctl.c
 create mode 100644 arch/arm/include/asm/arch-tegra/powergate.h
 create mode 100644 arch/arm/include/asm/arch-tegra/xusb-padctl.h
 create mode 100644 arch/arm/include/asm/arch-tegra114/powergate.h
 create mode 100644 arch/arm/include/asm/arch-tegra114/xusb-padctl.h
 create mode 100644 arch/arm/include/asm/arch-tegra124/powergate.h
 create mode 100644 arch/arm/include/asm/arch-tegra124/xusb-padctl.h
 create mode 100644 arch/arm/include/asm/arch-tegra20/powergate.h
 create mode 100644 arch/arm/include/asm/arch-tegra20/xusb-padctl.h
 create mode 100644 arch/arm/include/asm/arch-tegra30/powergate.h
 create mode 100644 arch/arm/include/asm/arch-tegra30/xusb-padctl.h
 create mode 100644 drivers/pci/pci_tegra.c
 create mode 100644 include/dt-bindings/clock/tegra124-car.h
 create mode 100644 include/dt-bindings/clock/tegra20-car.h
 create mode 100644 include/dt-bindings/clock/tegra30-car.h
 create mode 100644 include/dt-bindings/pinctrl/pinctrl-tegra-xusb.h
Signature · 1 line
2.0.4
#1 lore raw

PATCH 1/23 fdt: Add functions to query a node's #address- and #size-cells

From: Thierry Reding <[email protected]>

Given a device tree node, the fdt_n_addr_cells() function will walk up the device tree and search for an #address-cells property. It returns the number of cells required by the device tree node to represent an address.

Similarly the fdt_n_size_cells() function returns the number of cells required by the given device tree node to represent a size. It achieves that by walking up the device tree in seach for a #size-cells property.

If no #address-cells or #size-cells property can be found, both of the functions return 1.

---
 include/libfdt.h    | 28 ++++++++++++++++++++++++++++
 lib/libfdt/fdt_ro.c | 36 ++++++++++++++++++++++++++++++++++++
 2 files changed, 64 insertions(+)
include/libfdt.h +28 -0
index a1ef1e15df3d..e7f991b388cf 100644
@@ -1638,4 +1638,32 @@ int fdt_find_regions(const void *fdt, char * const inc[], int inc_count,
 		     struct fdt_region region[], int max_regions,
 		     char *path, int path_len, int add_string_tab);
 
+/**
+ * fdt_n_addr_cells() - find the number of address cells required by a node
+ *
+ * Looks up the #address-cells property of the node to examine. If that has
+ * no such property, walks up the device tree until it finds one in one of
+ * the device's parents. If no #address-cells property is found, it is
+ * assumed to be 1.
+ *
+ * @param fdt		FDT blob
+ * @param node		node to examine
+ * @return number of address cells
+ */
+int fdt_n_addr_cells(const void *fdt, int node);
+
+/**
+ * fdt_n_size_cells() - find the number of size cells required by a node
+ *
+ * Looks up the #size-cells property of the node to examine. If that has no
+ * such property, walks up the device tree until it finds one in one of the
+ * device's parents. If no #size-cells property is found, it is assumed to
+ * be 1.
+ *
+ * @param fdt		FDT blob
+ * @param node		node to examine
+ * @return number of size cells
+ */
+int fdt_n_size_cells(const void *fdt, int node);
+
 #endif /* _LIBFDT_H */
lib/libfdt/fdt_ro.c +36 -0
index 36af0435254b..17cd11333c1e 100644
@@ -530,3 +530,39 @@ int fdt_node_offset_by_compatible(const void *fdt, int startoffset,
 
 	return offset; /* error from fdt_next_node() */
 }
+
+int fdt_n_addr_cells(const void *fdt, int node)
+{
+	const fdt32_t *prop;
+	int len, parent;
+
+	do {
+		parent = fdt_parent_offset(fdt, node);
+		if (parent >= 0)
+			node = parent;
+
+		prop = fdt_getprop(fdt, node, "#address-cells", &len);
+		if (prop)
+			return fdt32_to_cpu(*prop);
+	} while (parent >= 0);
+
+	return 1;
+}
+
+int fdt_n_size_cells(const void *fdt, int node)
+{
+	const fdt32_t *prop;
+	int len, parent;
+
+	do {
+		parent = fdt_parent_offset(fdt, node);
+		if (parent >= 0)
+			node = parent;
+
+		prop = fdt_getprop(fdt, node, "#size-cells", &len);
+		if (prop)
+			return fdt32_to_cpu(*prop);
+	} while (parent >= 0);
+
+	return 1;
+}
Signature · 1 line
2.0.4
#2 lore raw

PATCH 1/23 fdt: Add functions to query a node's #address- and #size-cells

Hi Thierry,

Quoted 31 lines · Thierry Reding

From: Thierry Reding <[email protected]>

Given a device tree node, the fdt_n_addr_cells() function will walk up the device tree and search for an #address-cells property. It returns the number of cells required by the device tree node to represent an address.

Similarly the fdt_n_size_cells() function returns the number of cells required by the given device tree node to represent a size. It achieves that by walking up the device tree in seach for a #size-cells property.

If no #address-cells or #size-cells property can be found, both of the functions return 1.

---
 include/libfdt.h    | 28 ++++++++++++++++++++++++++++
 lib/libfdt/fdt_ro.c | 36 ++++++++++++++++++++++++++++++++++++
 2 files changed, 64 insertions(+)
include/libfdt.h +3 -0
index a1ef1e15df3d..e7f991b388cf 100644
@@ -1638,4 +1638,32 @@ int fdt_find_regions(const void *fdt, char * const inc[], int inc_count,
                     struct fdt_region region[], int max_regions,
                     char *path, int path_len, int add_string_tab);
 
+/**
+ * fdt_n_addr_cells() - find the number of address cells required by a node
+ *

include/libfdt.h int fdt_find_regions(const void *fdt, char * const inc[], int inc_count, · line 1653

Quoted 10 lines
include/libfdt.h +10 -0
+ * Looks up the #address-cells property of the node to examine. If that has
+ * no such property, walks up the device tree until it finds one in one of
+ * the device's parents. If no #address-cells property is found, it is
+ * assumed to be 1.
+ *
+ * @param fdt          FDT blob
+ * @param node         node to examine
+ * @return number of address cells
+ */
+int fdt_n_addr_cells(const void *fdt, int node);

There is a new fdt_address_cells() recently that looks suitable.

include/libfdt.h int fdt_find_regions(const void *fdt, char * const inc[], int inc_count, · line 1656

Quoted 3 lines
include/libfdt.h +3 -0
+
+/**
+ * fdt_n_size_cells() - find the number of size cells required by a node

Also fdt_size_cells().

Regards,
Simon

#3 lore raw

PATCH 1/23 fdt: Add functions to query a node's #address- and #size-cells

Quoted 47 lines · Simon Glass

Hi Thierry,

Quoted 31 lines · Thierry Reding

From: Thierry Reding <[email protected]>

Given a device tree node, the fdt_n_addr_cells() function will walk up the device tree and search for an #address-cells property. It returns the number of cells required by the device tree node to represent an address.

Similarly the fdt_n_size_cells() function returns the number of cells required by the given device tree node to represent a size. It achieves that by walking up the device tree in seach for a #size-cells property.

If no #address-cells or #size-cells property can be found, both of the functions return 1.

---
 include/libfdt.h    | 28 ++++++++++++++++++++++++++++
 lib/libfdt/fdt_ro.c | 36 ++++++++++++++++++++++++++++++++++++
 2 files changed, 64 insertions(+)
include/libfdt.h +3 -0
index a1ef1e15df3d..e7f991b388cf 100644
@@ -1638,4 +1638,32 @@ int fdt_find_regions(const void *fdt, char * const inc[], int inc_count,
                     struct fdt_region region[], int max_regions,
                     char *path, int path_len, int add_string_tab);
 
+/**
+ * fdt_n_addr_cells() - find the number of address cells required by a node
+ *

include/libfdt.h int fdt_find_regions(const void *fdt, char * const inc[], int inc_count, · line 1653

Quoted 10 lines
include/libfdt.h +10 -0
+ * Looks up the #address-cells property of the node to examine. If that has
+ * no such property, walks up the device tree until it finds one in one of
+ * the device's parents. If no #address-cells property is found, it is
+ * assumed to be 1.
+ *
+ * @param fdt          FDT blob
+ * @param node         node to examine
+ * @return number of address cells
+ */
+int fdt_n_addr_cells(const void *fdt, int node);

There is a new fdt_address_cells() recently that looks suitable.

Quoted 5 lines

include/libfdt.h int fdt_find_regions(const void *fdt, char * const inc[], int inc_count, · line 1656

Quoted 3 lines
include/libfdt.h +3 -0
+
+/**
+ * fdt_n_size_cells() - find the number of size cells required by a node

Also fdt_size_cells().

Neither of those seem to walk up the tree, so inheriting #address-cells or #size-cells from a parent will not work.

According to the comments in the code they're also supposed to return the number of cells represented by a bus, not a device (which might explain why it doesn't walk up the tree).

I also can't reuse them to implement these fdt_n_addr_cells() and fdt_n_size_cells() functions because they don't return an accurate error if the #address-cells and #size-cells are not found, therefore it's impossible to decide when to climb further up the tree.

Thierry
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 819 bytes
Desc: not available
URL: <http://lists.denx.de/pipermail/u-boot/attachments/20140819/f0c4df9d/attachment.pgp>

#4 lore raw

PATCH 1/23 fdt: Add functions to query a node's #address- and #size-cells

Hi Theirry,

Quoted 63 lines · Thierry Reding
Quoted 3 lines · Simon Glass

Hi Thierry,

On 18 August 2014 01:16, Thierry Reding <[email protected]>

Quoted 20 lines · wrote:
Quoted 20 lines

From: Thierry Reding <[email protected]>

Given a device tree node, the fdt_n_addr_cells() function will walk up the device tree and search for an #address-cells property. It returns the number of cells required by the device tree node to represent an address.

Similarly the fdt_n_size_cells() function returns the number of cells required by the given device tree node to represent a size. It achieves that by walking up the device tree in seach for a #size-cells property.

If no #address-cells or #size-cells property can be found, both of the functions return 1.

---
 include/libfdt.h    | 28 ++++++++++++++++++++++++++++
 lib/libfdt/fdt_ro.c | 36 ++++++++++++++++++++++++++++++++++++
 2 files changed, 64 insertions(+)
Quoted 5 lines

include/libfdt.h int fdt_find_regions(const void *fdt, char *

Quoted 5 lines
include/libfdt.h +0 -0
index a1ef1e15df3d..e7f991b388cf 100644
@@ -1638,4 +1638,32 @@ int fdt_find_regions(const void *fdt, char *

const inc[], int inc_count,

Quoted 5 lines

include/libfdt.h int fdt_find_regions(const void *fdt, char * const inc[], int inc_count,

Quoted 5 lines
include/libfdt.h +2 -0
                     struct fdt_region region[], int max_regions,
                     char *path, int path_len, int add_string_tab);
 
+/**
+ * fdt_n_addr_cells() - find the number of address cells required by

a node

Quoted 2 lines

include/libfdt.h int fdt_find_regions(const void *fdt, char * · line 1644

Quoted 2 lines
include/libfdt.h +2 -0
+ *
+ * Looks up the #address-cells property of the node to examine. If

that has

Quoted 1 line

include/libfdt.h int fdt_find_regions(const void *fdt, char * · line 1645

Quoted 1 line
include/libfdt.h +1 -0
+ * no such property, walks up the device tree until it finds one in

one of

Quoted 9 lines

include/libfdt.h int fdt_find_regions(const void *fdt, char * const inc[], int inc_count, · line 1653

Quoted 8 lines
include/libfdt.h +8 -0
+ * the device's parents. If no #address-cells property is found, it is
+ * assumed to be 1.
+ *
+ * @param fdt          FDT blob
+ * @param node         node to examine
+ * @return number of address cells
+ */
+int fdt_n_addr_cells(const void *fdt, int node);
Quoted 5 lines

There is a new fdt_address_cells() recently that looks suitable.

include/libfdt.h int fdt_find_regions(const void *fdt, char * const inc[], int inc_count,

Quoted 3 lines
include/libfdt.h +3 -0
+
+/**
+ * fdt_n_size_cells() - find the number of size cells required by a

node

Quoted 2 lines

Also fdt_size_cells().

Neither of those seem to walk up the tree, so inheriting #address-cells or #size-cells from a parent will not work.

Quoted 9 lines

According to the comments in the code they're also supposed to return the number of cells represented by a bus, not a device (which might explain why it doesn't walk up the tree).

I also can't reuse them to implement these fdt_n_addr_cells() and fdt_n_size_cells() functions because they don't return an accurate error if the #address-cells and #size-cells are not found, therefore it's impossible to decide when to climb further up the tree.

OK but I have one more question. I thought that dtc gave a warning when you don't explicitly specify these values in the parent node?

Regards,
Simon

#5 lore raw

Re: [PATCH 01/23] fdt: Add functions to query a node's #address- and #size-cells

Quoted 72 lines · Simon Glass

Hi Theirry,

Quoted 67 lines · Thierry Reding
Quoted 3 lines · Simon Glass

Hi Thierry,

On 18 August 2014 01:16, Thierry Reding <[email protected]>

Quoted 20 lines · wrote:
Quoted 20 lines

From: Thierry Reding <[email protected]>

Given a device tree node, the fdt_n_addr_cells() function will walk up the device tree and search for an #address-cells property. It returns the number of cells required by the device tree node to represent an address.

Similarly the fdt_n_size_cells() function returns the number of cells required by the given device tree node to represent a size. It achieves that by walking up the device tree in seach for a #size-cells property.

If no #address-cells or #size-cells property can be found, both of the functions return 1.

---
 include/libfdt.h    | 28 ++++++++++++++++++++++++++++
 lib/libfdt/fdt_ro.c | 36 ++++++++++++++++++++++++++++++++++++
 2 files changed, 64 insertions(+)
Quoted 5 lines

include/libfdt.h int fdt_find_regions(const void *fdt, char *

Quoted 5 lines
include/libfdt.h +0 -0
index a1ef1e15df3d..e7f991b388cf 100644
@@ -1638,4 +1638,32 @@ int fdt_find_regions(const void *fdt, char *

const inc[], int inc_count,

Quoted 5 lines

include/libfdt.h int fdt_find_regions(const void *fdt, char * const inc[], int inc_count,

Quoted 5 lines
include/libfdt.h +2 -0
                     struct fdt_region region[], int max_regions,
                     char *path, int path_len, int add_string_tab);
 
+/**
+ * fdt_n_addr_cells() - find the number of address cells required by

a node

Quoted 2 lines

include/libfdt.h int fdt_find_regions(const void *fdt, char * · line 1644

Quoted 2 lines
include/libfdt.h +2 -0
+ *
+ * Looks up the #address-cells property of the node to examine. If

that has

Quoted 1 line

include/libfdt.h int fdt_find_regions(const void *fdt, char * · line 1645

Quoted 1 line
include/libfdt.h +1 -0
+ * no such property, walks up the device tree until it finds one in

one of

Quoted 9 lines

include/libfdt.h int fdt_find_regions(const void *fdt, char * const inc[], int inc_count, · line 1653

Quoted 8 lines
include/libfdt.h +8 -0
+ * the device's parents. If no #address-cells property is found, it is
+ * assumed to be 1.
+ *
+ * @param fdt          FDT blob
+ * @param node         node to examine
+ * @return number of address cells
+ */
+int fdt_n_addr_cells(const void *fdt, int node);
Quoted 5 lines

There is a new fdt_address_cells() recently that looks suitable.

include/libfdt.h int fdt_find_regions(const void *fdt, char * const inc[], int inc_count,

Quoted 3 lines
include/libfdt.h +3 -0
+
+/**
+ * fdt_n_size_cells() - find the number of size cells required by a

node

Quoted 2 lines

Also fdt_size_cells().

Neither of those seem to walk up the tree, so inheriting #address-cells or #size-cells from a parent will not work.

According to the comments in the code they're also supposed to return the number of cells represented by a bus, not a device (which might explain why it doesn't walk up the tree).

Quoted 8 lines
Quoted 5 lines

I also can't reuse them to implement these fdt_n_addr_cells() and fdt_n_size_cells() functions because they don't return an accurate error if the #address-cells and #size-cells are not found, therefore it's impossible to decide when to climb further up the tree.

OK but I have one more question. I thought that dtc gave a warning when you don't explicitly specify these values in the parent node?

It doesn't explicitly warn about the properties being absent. Rather it will fallback to the default (#address-cells = <2>, #size-cells = <1> in the version that I have) and warn if those don't match what's expected.

Interestingly as opposed to what the Linux kernel does, DTC doesn't seem to climb further up the tree if it can't find the properties in a device tree node. Instead, it seems to always use the default values instead.

Adding the [email protected] mailing list. Maybe somebody there can help iron out this inconsistency. ePAPR explicitly says that both "... #address-cells and #size-cells properties are not inherited from ancestors in the device tree. They shall be explicitly defined." (see 2.3.5 "#address-cells and #size-cells").

Thierry

_______________________________________________
U-Boot mailing list
[email protected]
http://lists.denx.de/mailman/listinfo/u-boot

#6 lore raw

Re: [PATCH 01/23] fdt: Add functions to query a node's #address- and #size-cells

Hi Thierry,

Quoted 90 lines · Thierry Reding
Quoted 72 lines · Simon Glass

Hi Theirry,

Quoted 67 lines · Thierry Reding
Quoted 3 lines · Simon Glass

Hi Thierry,

On 18 August 2014 01:16, Thierry Reding <[email protected]>

Quoted 20 lines · wrote:
Quoted 20 lines

From: Thierry Reding <[email protected]>

Given a device tree node, the fdt_n_addr_cells() function will walk up the device tree and search for an #address-cells property. It returns the number of cells required by the device tree node to represent an address.

Similarly the fdt_n_size_cells() function returns the number of cells required by the given device tree node to represent a size. It achieves that by walking up the device tree in seach for a #size-cells property.

If no #address-cells or #size-cells property can be found, both of the functions return 1.

---
 include/libfdt.h    | 28 ++++++++++++++++++++++++++++
 lib/libfdt/fdt_ro.c | 36 ++++++++++++++++++++++++++++++++++++
 2 files changed, 64 insertions(+)
Quoted 5 lines

include/libfdt.h int fdt_find_regions(const void *fdt, char *

Quoted 5 lines
include/libfdt.h +0 -0
index a1ef1e15df3d..e7f991b388cf 100644
@@ -1638,4 +1638,32 @@ int fdt_find_regions(const void *fdt, char *

const inc[], int inc_count,

Quoted 5 lines

include/libfdt.h int fdt_find_regions(const void *fdt, char * const inc[], int inc_count,

Quoted 5 lines
include/libfdt.h +2 -0
                     struct fdt_region region[], int max_regions,
                     char *path, int path_len, int add_string_tab);
 
+/**
+ * fdt_n_addr_cells() - find the number of address cells required by

a node

Quoted 2 lines

include/libfdt.h int fdt_find_regions(const void *fdt, char * · line 1644

Quoted 2 lines
include/libfdt.h +2 -0
+ *
+ * Looks up the #address-cells property of the node to examine. If

that has

Quoted 1 line

include/libfdt.h int fdt_find_regions(const void *fdt, char * · line 1645

Quoted 1 line
include/libfdt.h +1 -0
+ * no such property, walks up the device tree until it finds one in

one of

Quoted 9 lines

include/libfdt.h int fdt_find_regions(const void *fdt, char * const inc[], int inc_count, · line 1653

Quoted 8 lines
include/libfdt.h +8 -0
+ * the device's parents. If no #address-cells property is found, it is
+ * assumed to be 1.
+ *
+ * @param fdt          FDT blob
+ * @param node         node to examine
+ * @return number of address cells
+ */
+int fdt_n_addr_cells(const void *fdt, int node);
Quoted 5 lines

There is a new fdt_address_cells() recently that looks suitable.

include/libfdt.h int fdt_find_regions(const void *fdt, char * const inc[], int inc_count,

Quoted 3 lines
include/libfdt.h +3 -0
+
+/**
+ * fdt_n_size_cells() - find the number of size cells required by a

node

Quoted 2 lines

Also fdt_size_cells().

Neither of those seem to walk up the tree, so inheriting #address-cells or #size-cells from a parent will not work.

According to the comments in the code they're also supposed to return the number of cells represented by a bus, not a device (which might explain why it doesn't walk up the tree).

Quoted 8 lines
Quoted 5 lines

I also can't reuse them to implement these fdt_n_addr_cells() and fdt_n_size_cells() functions because they don't return an accurate error if the #address-cells and #size-cells are not found, therefore it's impossible to decide when to climb further up the tree.

OK but I have one more question. I thought that dtc gave a warning when you don't explicitly specify these values in the parent node?

It doesn't explicitly warn about the properties being absent. Rather it will fallback to the default (#address-cells = <2>, #size-cells = <1> in the version that I have) and warn if those don't match what's expected.

Interestingly as opposed to what the Linux kernel does, DTC doesn't seem to climb further up the tree if it can't find the properties in a device tree node. Instead, it seems to always use the default values instead.

Quoted 5 lines

Adding the [email protected] mailing list. Maybe somebody there can help iron out this inconsistency. ePAPR explicitly says that both
"... #address-cells and #size-cells properties are not inherited from
ancestors in the device tree. They shall be explicitly defined." (see
2.3.5 "#address-cells and #size-cells").

That's my understanding too. So should we drop this patch?

Regards,
Simon
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in the body of a message to [email protected] More majordomo info at http://vger.kernel.org/majordomo-info.html

A message that is not in the archive (sent off-list or not yet received): CAPnjgZ06b3UeeXra5STLht15jU00yAKCwM+UYuqc=50Th9Jd_g-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org

#8 lore raw

Re: [PATCH 01/23] fdt: Add functions to query a node's #address- and #size-cells

Quoted 93 lines · Simon Glass

Hi Thierry,

Quoted 90 lines · Thierry Reding
Quoted 72 lines · Simon Glass

Hi Theirry,

Quoted 67 lines · Thierry Reding
Quoted 3 lines · Simon Glass

Hi Thierry,

On 18 August 2014 01:16, Thierry Reding <[email protected]>

Quoted 20 lines · wrote:
Quoted 20 lines

From: Thierry Reding <[email protected]>

Given a device tree node, the fdt_n_addr_cells() function will walk up the device tree and search for an #address-cells property. It returns the number of cells required by the device tree node to represent an address.

Similarly the fdt_n_size_cells() function returns the number of cells required by the given device tree node to represent a size. It achieves that by walking up the device tree in seach for a #size-cells property.

If no #address-cells or #size-cells property can be found, both of the functions return 1.

---
 include/libfdt.h    | 28 ++++++++++++++++++++++++++++
 lib/libfdt/fdt_ro.c | 36 ++++++++++++++++++++++++++++++++++++
 2 files changed, 64 insertions(+)
Quoted 5 lines

include/libfdt.h int fdt_find_regions(const void *fdt, char *

Quoted 5 lines
include/libfdt.h +0 -0
index a1ef1e15df3d..e7f991b388cf 100644
@@ -1638,4 +1638,32 @@ int fdt_find_regions(const void *fdt, char *

const inc[], int inc_count,

Quoted 5 lines

include/libfdt.h int fdt_find_regions(const void *fdt, char * · line 1642

Quoted 5 lines
include/libfdt.h +2 -0
                     struct fdt_region region[], int max_regions,
                     char *path, int path_len, int add_string_tab);
 
+/**
+ * fdt_n_addr_cells() - find the number of address cells required by

a node

Quoted 2 lines

include/libfdt.h int fdt_find_regions(const void *fdt, char * · line 1644

Quoted 2 lines
include/libfdt.h +2 -0
+ *
+ * Looks up the #address-cells property of the node to examine. If

that has

Quoted 1 line

include/libfdt.h int fdt_find_regions(const void *fdt, char * · line 1645

Quoted 1 line
include/libfdt.h +1 -0
+ * no such property, walks up the device tree until it finds one in

one of

Quoted 9 lines

include/libfdt.h int fdt_find_regions(const void *fdt, char * · line 1653

Quoted 8 lines
include/libfdt.h +8 -0
+ * the device's parents. If no #address-cells property is found, it is
+ * assumed to be 1.
+ *
+ * @param fdt          FDT blob
+ * @param node         node to examine
+ * @return number of address cells
+ */
+int fdt_n_addr_cells(const void *fdt, int node);
Quoted 5 lines

There is a new fdt_address_cells() recently that looks suitable.

include/libfdt.h int fdt_find_regions(const void *fdt, char * · line 1656

Quoted 3 lines
include/libfdt.h +3 -0
+
+/**
+ * fdt_n_size_cells() - find the number of size cells required by a

node

Quoted 2 lines

Also fdt_size_cells().

Neither of those seem to walk up the tree, so inheriting #address-cells or #size-cells from a parent will not work.

According to the comments in the code they're also supposed to return the number of cells represented by a bus, not a device (which might explain why it doesn't walk up the tree).

Quoted 8 lines
Quoted 5 lines

I also can't reuse them to implement these fdt_n_addr_cells() and fdt_n_size_cells() functions because they don't return an accurate error if the #address-cells and #size-cells are not found, therefore it's impossible to decide when to climb further up the tree.

OK but I have one more question. I thought that dtc gave a warning when you don't explicitly specify these values in the parent node?

It doesn't explicitly warn about the properties being absent. Rather it will fallback to the default (#address-cells = <2>, #size-cells = <1> in the version that I have) and warn if those don't match what's expected.

Interestingly as opposed to what the Linux kernel does, DTC doesn't seem to climb further up the tree if it can't find the properties in a device tree node. Instead, it seems to always use the default values instead.

Quoted 7 lines
Quoted 5 lines

Adding the [email protected] mailing list. Maybe somebody there can help iron out this inconsistency. ePAPR explicitly says that both
"... #address-cells and #size-cells properties are not inherited from
ancestors in the device tree. They shall be explicitly defined." (see
2.3.5 "#address-cells and #size-cells").

That's my understanding too. So should we drop this patch?

Yes, in this particular case it works fine using the existing fdt_address_cells() and fdt_size_cells() functions so I've dropped this patch.

Thierry

#9 lore raw

PATCH 2/23 fdt: Add a function to get the index of a string

In reply to Thierry Reding

From: Thierry Reding <[email protected]>

Given a device tree node and a property name, the fdt_get_string_index() function will look up a given string in the string list contained in the property's value and return its index.

---
 include/libfdt.h    | 11 +++++++++++
 lib/libfdt/fdt_ro.c | 28 ++++++++++++++++++++++++++++
 2 files changed, 39 insertions(+)
include/libfdt.h +11 -0
index e7f991b388cf..4d7fb2681669 100644
@@ -857,6 +857,17 @@ int fdt_node_offset_by_compatible(const void *fdt, int startoffset,
  */
 int fdt_stringlist_contains(const char *strlist, int listlen, const char *str);
 
+/**
+ * fdt_get_string_index - get the index of a string in a string list
+ * @fdt: pointer to the device tree blob
+ * @node: offset of the node
+ * @property: name of the property containing the string list
+ * @string: string to look up in the string list
+ * @return the index of the string or negative on error
+ */
+int fdt_get_string_index(const void *fdt, int node, const char *property,
+			 const char *string);
+
 /**********************************************************************/
 /* Read-only functions (addressing related)                           */
 /**********************************************************************/
lib/libfdt/fdt_ro.c +28 -0
index 17cd11333c1e..f211c64ca7ca 100644
@@ -14,6 +14,8 @@
 
 #include "libfdt_internal.h"
 
+#define max(x, y) (((x) < (y)) ? (y) : (x))
+
 static int _fdt_nodename_eq(const void *fdt, int offset,
 			    const char *s, int len)
 {
@@ -491,6 +493,32 @@ int fdt_stringlist_contains(const char *strlist, int listlen, const char *str)
 	return 0;
 }
 
+int fdt_get_string_index(const void *fdt, int node, const char *property,
+			 const char *string)
+{
+	const char *list, *end;
+	int len, index = 0;
+
+	list = fdt_getprop(fdt, node, property, &len);
+	if (!list)
+		return len;
+
+	end = list + len;
+
+	while (list < end) {
+		int n = strlen(string);
+		int m = strlen(list);
+
+		if (n == m && memcmp(list, string, n) == 0)
+			return index;
+
+		list += max(n, m) + 1;
+		index++;
+	}
+
+	return -FDT_ERR_NOTFOUND;
+}
+
 int fdt_node_check_compatible(const void *fdt, int nodeoffset,
 			      const char *compatible)
 {
Signature · 1 line
2.0.4
#10 lore raw

PATCH 2/23 fdt: Add a function to get the index of a string

Hi Thierry,

Quoted 55 lines · Thierry Reding

From: Thierry Reding <[email protected]>

Given a device tree node and a property name, the fdt_get_string_index() function will look up a given string in the string list contained in the property's value and return its index.

---
 include/libfdt.h    | 11 +++++++++++
 lib/libfdt/fdt_ro.c | 28 ++++++++++++++++++++++++++++
 2 files changed, 39 insertions(+)
include/libfdt.h +11 -0
index e7f991b388cf..4d7fb2681669 100644
@@ -857,6 +857,17 @@ int fdt_node_offset_by_compatible(const void *fdt, int startoffset,
  */
 int fdt_stringlist_contains(const char *strlist, int listlen, const char *str);
 
+/**
+ * fdt_get_string_index - get the index of a string in a string list
+ * @fdt: pointer to the device tree blob
+ * @node: offset of the node
+ * @property: name of the property containing the string list
+ * @string: string to look up in the string list
+ * @return the index of the string or negative on error
+ */
+int fdt_get_string_index(const void *fdt, int node, const char *property,
+                        const char *string);
+
 /**********************************************************************/
 /* Read-only functions (addressing related)                           */
 /**********************************************************************/
lib/libfdt/fdt_ro.c +6 -0
index 17cd11333c1e..f211c64ca7ca 100644
@@ -14,6 +14,8 @@
 
 #include "libfdt_internal.h"
 
+#define max(x, y) (((x) < (y)) ? (y) : (x))
+
 static int _fdt_nodename_eq(const void *fdt, int offset,
                            const char *s, int len)
 {
@@ -491,6 +493,32 @@ int fdt_stringlist_contains(const char *strlist, int listlen, const char *str)
        return 0;
 }
 
+int fdt_get_string_index(const void *fdt, int node, const char *property,
+                        const char *string)
+{
+       const char *list, *end;

lib/libfdt/fdt_ro.c int fdt_stringlist_contains(const char *strlist, int listlen, const char *str) · line 509

Quoted 10 lines
lib/libfdt/fdt_ro.c +10 -0
+       int len, index = 0;
+
+       list = fdt_getprop(fdt, node, property, &len);
+       if (!list)
+               return len;
+
+       end = list + len;
+
+       while (list < end) {
+               int n = strlen(string);

This can go outside the loop.

lib/libfdt/fdt_ro.c int fdt_stringlist_contains(const char *strlist, int listlen, const char *str) · line 515

Quoted 6 lines
lib/libfdt/fdt_ro.c +6 -0
+               int m = strlen(list);
+
+               if (n == m && memcmp(list, string, n) == 0)
+                       return index;
+
+               list += max(n, m) + 1;

I worry that if n > m this will end up in the middle of a the next string in the list. What is the intention here?

Quoted 10 lines
lib/libfdt/fdt_ro.c +6 -1
+               index++;
+       }
+
+       return -FDT_ERR_NOTFOUND;
+}
+
 int fdt_node_check_compatible(const void *fdt, int nodeoffset,
                              const char *compatible)
 {
--
Quoted 2 lines

2.0.4

Regards,
Simon

#11 lore raw

PATCH 2/23 fdt: Add a function to get the index of a string

Quoted 1 line · Simon Glass

On 18 August 2014 01:16, Thierry Reding <[email protected]> wrote:

[...]

Quoted 8 lines
Quoted 8 lines
lib/libfdt/fdt_ro.c +8 -0
+int fdt_get_string_index(const void *fdt, int node, const char *property,
+                        const char *string)
+{
+       const char *list, *end;
+       int len, index = 0;
+
+       list = fdt_getprop(fdt, node, property, &len);
+       if (!list)
Quoted 8 lines

lib/libfdt/fdt_ro.c int fdt_stringlist_contains(const char *strlist, int listlen, const char *str) · line 509

Quoted 6 lines
lib/libfdt/fdt_ro.c +6 -0
+               return len;
+
+       end = list + len;
+
+       while (list < end) {
+               int n = strlen(string);

This can go outside the loop.

Indeed.

Quoted 9 lines

lib/libfdt/fdt_ro.c int fdt_stringlist_contains(const char *strlist, int listlen, const char *str) · line 515

Quoted 6 lines
lib/libfdt/fdt_ro.c +6 -0
+               int m = strlen(list);
+
+               if (n == m && memcmp(list, string, n) == 0)
+                       return index;
+
+               list += max(n, m) + 1;

I worry that if n > m this will end up in the middle of a the next string in the list. What is the intention here?

I can no longer recall why that's there. It certainly seems wrong since if the current substring isn't what we're looking for the function should proceed to the next one, which is always m + 1 characters away.

I'll replace this with list += m + 1.

Thierry
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 819 bytes
Desc: not available
URL: <http://lists.denx.de/pipermail/u-boot/attachments/20140819/b1683e5b/attachment.pgp>

#12 lore raw

PATCH 3/23 fdt: Add resource parsing functions

In reply to Thierry Reding

From: Thierry Reding <[email protected]>

Add the fdt_get_resource() and fdt_get_named_resource() functions which can be used to parse resources (memory regions) from an FDT. A helper to compute the size of a region is also provided.

---
 include/fdtdec.h | 48 ++++++++++++++++++++++++++++++++++++++++++++++++
 lib/fdtdec.c     | 43 +++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 91 insertions(+)
include/fdtdec.h +48 -0
index 856e6cf766de..e9091eee6bae 100644
@@ -40,6 +40,23 @@ struct fdt_memory {
 	fdt_addr_t end;
 };
 
+/* information about a resource */
+struct fdt_resource {
+	fdt_addr_t start;
+	fdt_addr_t end;
+};
+
+/**
+ * Compute the size of a resource.
+ *
+ * @param res	the resource to operate on
+ * @return the size of the resource
+ */
+static inline fdt_size_t fdt_resource_size(const struct fdt_resource *res)
+{
+	return res->end - res->start + 1;
+}
+
 /**
  * Compat types that we know about and for which we might have drivers.
  * Each is named COMPAT_<dir>_<filename> where <dir> is the directory
@@ -583,4 +600,35 @@ struct fmap_entry {
  */
 int fdtdec_read_fmap_entry(const void *blob, int node, const char *name,
 			   struct fmap_entry *entry);
+
+/**
+ * Obtain an indexed resource from a device property.
+ *
+ * @param fdt		FDT blob
+ * @param node		node to examine
+ * @param property	name of the property to parse
+ * @param index		index of the resource to retrieve
+ * @param res		returns the resource
+ * @return 0 if ok, negative on error
+ */
+int fdt_get_resource(const void *fdt, int node, const char *property,
+		     unsigned int index, struct fdt_resource *res);
+
+/**
+ * Obtain a named resource from a device property.
+ *
+ * Look up the index of the name in a list of strings and return the resource
+ * at that index.
+ *
+ * @param fdt		FDT blob
+ * @param node		node to examine
+ * @param property	name of the property to parse
+ * @param names		name of the property to obtain the match the name to
+ * @param name		the name of the entry to look up
+ * @param res		returns the resource
+ */
+int fdt_get_named_resource(const void *fdt, int node, const char *property,
+			   const char *names, const char *name,
+			   struct fdt_resource *res);
+
 #endif
lib/fdtdec.c +43 -0

47 lines not on this page · raw message

Signature · 1 line
2.0.4
#13 lore raw

PATCH 3/23 fdt: Add resource parsing functions

Hi Thierry,

Quoted 17 lines · Thierry Reding

From: Thierry Reding <[email protected]>

Add the fdt_get_resource() and fdt_get_named_resource() functions which can be used to parse resources (memory regions) from an FDT. A helper to compute the size of a region is also provided.

---
 include/fdtdec.h | 48 ++++++++++++++++++++++++++++++++++++++++++++++++
 lib/fdtdec.c     | 43 +++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 91 insertions(+)
include/fdtdec.h +0 -0
index 856e6cf766de..e9091eee6bae 100644

include/fdtdec.h struct fdt_memory { · line 43

Quoted 4 lines
include/fdtdec.h +1 -0
@@ -40,6 +40,23 @@ struct fdt_memory {
        fdt_addr_t end;
 };
 
+/* information about a resource */

Please add comments, e.g. that end is inclusive.

Quoted 38 lines
include/fdtdec.h +31 -0
+struct fdt_resource {
+       fdt_addr_t start;
+       fdt_addr_t end;
+};
+
+/**
+ * Compute the size of a resource.
+ *
+ * @param res  the resource to operate on
+ * @return the size of the resource
+ */
+static inline fdt_size_t fdt_resource_size(const struct fdt_resource *res)
+{
+       return res->end - res->start + 1;
+}
+
 /**
  * Compat types that we know about and for which we might have drivers.
  * Each is named COMPAT_<dir>_<filename> where <dir> is the directory
@@ -583,4 +600,35 @@ struct fmap_entry {
  */
 int fdtdec_read_fmap_entry(const void *blob, int node, const char *name,
                           struct fmap_entry *entry);
+
+/**
+ * Obtain an indexed resource from a device property.
+ *
+ * @param fdt          FDT blob
+ * @param node         node to examine
+ * @param property     name of the property to parse
+ * @param index                index of the resource to retrieve
+ * @param res          returns the resource
+ * @return 0 if ok, negative on error
+ */
+int fdt_get_resource(const void *fdt, int node, const char *property,
+                    unsigned int index, struct fdt_resource *res);
+
+/**

include/fdtdec.h struct fmap_entry { · line 627

Quoted 10 lines
include/fdtdec.h +10 -0
+ * Obtain a named resource from a device property.
+ *
+ * Look up the index of the name in a list of strings and return the resource
+ * at that index.
+ *
+ * @param fdt          FDT blob
+ * @param node         node to examine
+ * @param property     name of the property to parse
+ * @param names                name of the property to obtain the match the name to
+ * @param name         the name of the entry to look up

These two parameters are confusing. Perhaps rename names to something better?

Quoted 12 lines
include/fdtdec.h +6 -0
+ * @param res          returns the resource
+ */
+int fdt_get_named_resource(const void *fdt, int node, const char *property,
+                          const char *names, const char *name,
+                          struct fdt_resource *res);
+
 #endif
lib/fdtdec.c +0 -0
index eb5aa20526fd..fbfae4a7cbaf 100644

lib/fdtdec.c int fdtdec_read_fmap_entry(const void *blob, int node, const char *name, · line 696

Quoted 6 lines
lib/fdtdec.c +3 -0
@@ -691,4 +691,47 @@ int fdtdec_read_fmap_entry(const void *blob, int node, const char *name,
 
        return 0;
 }
+
+int fdt_get_resource(const void *fdt, int node, const char *property,
+                    unsigned int index, struct fdt_resource *res)

s/index/find_index/

lib/fdtdec.c int fdtdec_read_fmap_entry(const void *blob, int node, const char *name, · line 709

Quoted 13 lines
lib/fdtdec.c +13 -0
+{
+       const fdt32_t *ptr, *end;
+       unsigned int i = 0;
+       int na, ns, len;
+
+       na = fdt_n_addr_cells(fdt, node);
+       ns = fdt_n_size_cells(fdt, node);
+
+       ptr = fdt_getprop(fdt, node, property, &len);
+       if (!ptr)
+               return len;
+
+       end = ptr + len / 4;

sizeof(*ptr) might be better than 4.

lib/fdtdec.c int fdtdec_read_fmap_entry(const void *blob, int node, const char *name, · line 713

Quoted 4 lines
lib/fdtdec.c +4 -0
+
+       while (ptr + na + ns <= end) {
+               if (i == index) {
+                       res->start = fdt_addr_to_cpu(*ptr);

This doesn't deal with 64-bit addresses. There is a half-hearted attempt with fdt_addr_t, but I wonder if we need a helper function like fdt_get_addr(ptr, num_cells)?

Quoted 25 lines
lib/fdtdec.c +23 -1
+                       res->end = res->start + fdt_size_to_cpu(ptr[na]) - 1;
+                       return 0;
+               }
+
+               ptr += na + ns;
+               i++;
+       }
+
+       return -FDT_ERR_NOTFOUND;
+}
+
+int fdt_get_named_resource(const void *fdt, int node, const char *property,
+                          const char *names, const char *name,
+                          struct fdt_resource *res)
+{
+       int index;
+
+       index = fdt_get_string_index(fdt, node, names, name);
+       if (index < 0)
+               return index;
+
+       return fdt_get_resource(fdt, node, property, index, res);
+}
 #endif
--
Quoted 2 lines

2.0.4

Regards,
Simon

#14 lore raw

PATCH 3/23 fdt: Add resource parsing functions

Quoted 23 lines · Simon Glass

Hi Thierry,

Quoted 20 lines · Thierry Reding

From: Thierry Reding <[email protected]>

Add the fdt_get_resource() and fdt_get_named_resource() functions which can be used to parse resources (memory regions) from an FDT. A helper to compute the size of a region is also provided.

---
 include/fdtdec.h | 48 ++++++++++++++++++++++++++++++++++++++++++++++++
 lib/fdtdec.c     | 43 +++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 91 insertions(+)
include/fdtdec.h +0 -0
index 856e6cf766de..e9091eee6bae 100644
@@ -40,6 +40,23 @@ struct fdt_memory {
        fdt_addr_t end;
 };
 
Quoted 3 lines

include/fdtdec.h struct fdt_memory { · line 43

Quoted 1 line
include/fdtdec.h +1 -0
+/* information about a resource */

Please add comments, e.g. that end is inclusive.

I've added this comment:

/*
* Information about a resource. start is the first address of the resource
* and end is the last address (inclusive). The length of the resource will
* be equal to: end - start + 1.
*/

Is that enough or do you want me to be more verbose?

Quoted 12 lines

include/fdtdec.h struct fmap_entry { · line 627

Quoted 11 lines
include/fdtdec.h +11 -0
+/**
+ * Obtain a named resource from a device property.
+ *
+ * Look up the index of the name in a list of strings and return the resource
+ * at that index.
+ *
+ * @param fdt          FDT blob
+ * @param node         node to examine
+ * @param property     name of the property to parse
+ * @param names                name of the property to obtain the match the name to
+ * @param name         the name of the entry to look up
Quoted 1 line

These two parameters are confusing. Perhaps rename names to something better?

How about "prop_names" so that it indicates it is the name of a property? I've also adjusted the comment a bit:

* @param prop_names name of the property containing the list of names

Hopefully that will make it more obvious.

Quoted 4 lines

include/fdtdec.h struct fdt_memory { · line 56

Quoted 2 lines
include/fdtdec.h +2 -0
+int fdt_get_resource(const void *fdt, int node, const char *property,
+                    unsigned int index, struct fdt_resource *res)

s/index/find_index/

In my opinion the find_ prefix is redundant. After all the function name already indicates that we're looking for a resource inside a property. And index would be the offset in that property.

Quoted 6 lines

include/fdtdec.h struct fdt_memory { · line 60

Quoted 4 lines
include/fdtdec.h +4 -0
+       if (!ptr)
+               return len;
+
+       end = ptr + len / 4;

sizeof(*ptr) might be better than 4.

Device tree explicitly specifies that cells are 32-bit, so this can't ever be anything other than 4. But I'll change it anyway if you prefer.

Quoted 8 lines

include/fdtdec.h struct fdt_memory {

Quoted 4 lines
include/fdtdec.h +4 -0
+
+       while (ptr + na + ns <= end) {
+               if (i == index) {
+                       res->start = fdt_addr_to_cpu(*ptr);

This doesn't deal with 64-bit addresses. There is a half-hearted attempt with fdt_addr_t, but I wonder if we need a helper function like fdt_get_addr(ptr, num_cells)?

The Linux kernel handles this by wrapping it in an of_read_number() helper and always returning u64, like this:

	static inline u64 of_read_number(const __be32 *cell, int size)
	{
		u64 r = 0;

		while (size--)
			r = (r << 32) | be32_to_cpu(*(cell++));

		return r;
	}

It obviously only works for size in { 0, 1, 2 }, but I can add a helper like that if you want.

Thierry
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 819 bytes
Desc: not available
URL: <http://lists.denx.de/pipermail/u-boot/attachments/20140819/92553822/attachment.pgp>

#15 lore raw

PATCH 3/23 fdt: Add resource parsing functions

Hi Thierry,

Quoted 31 lines · Thierry Reding
Quoted 23 lines · Simon Glass

Hi Thierry,

Quoted 20 lines · Thierry Reding

From: Thierry Reding <[email protected]>

Add the fdt_get_resource() and fdt_get_named_resource() functions which can be used to parse resources (memory regions) from an FDT. A helper to compute the size of a region is also provided.

---
 include/fdtdec.h | 48 ++++++++++++++++++++++++++++++++++++++++++++++++
 lib/fdtdec.c     | 43 +++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 91 insertions(+)
include/fdtdec.h +0 -0
index 856e6cf766de..e9091eee6bae 100644
@@ -40,6 +40,23 @@ struct fdt_memory {
        fdt_addr_t end;
 };
 
Quoted 3 lines

include/fdtdec.h struct fdt_memory { · line 43

Quoted 1 line
include/fdtdec.h +1 -0
+/* information about a resource */

Please add comments, e.g. that end is inclusive.

I've added this comment:

Quoted 7 lines

/*
* Information about a resource. start is the first address of the resource
* and end is the last address (inclusive). The length of the resource will
* be equal to: end - start + 1.
*/

Is that enough or do you want me to be more verbose?

LGTM

Quoted 14 lines
Quoted 14 lines
Quoted 13 lines
include/fdtdec.h +11 -0
+/**
+ * Obtain a named resource from a device property.
+ *
+ * Look up the index of the name in a list of strings and return the resource
+ * at that index.
+ *
+ * @param fdt          FDT blob
+ * @param node         node to examine
+ * @param property     name of the property to parse
+ * @param names                name of the property to obtain the match the name to
+ * @param name         the name of the entry to look up
Quoted 8 lines
Quoted 1 line

These two parameters are confusing. Perhaps rename names to something better?

How about "prop_names" so that it indicates it is the name of a property? I've also adjusted the comment a bit:

* @param prop_names name of the property containing the list of names

Hopefully that will make it more obvious.

OK

Quoted 10 lines
Quoted 6 lines

include/fdtdec.h struct fdt_memory { · line 56

Quoted 4 lines
include/fdtdec.h +2 -0
+int fdt_get_resource(const void *fdt, int node, const char *property,
+                    unsigned int index, struct fdt_resource *res)

s/index/find_index/

In my opinion the find_ prefix is redundant. After all the function name already indicates that we're looking for a resource inside a property. And index would be the offset in that property.

OK

Quoted 11 lines
Quoted 8 lines

include/fdtdec.h struct fdt_memory { · line 60

Quoted 6 lines
include/fdtdec.h +4 -0
+       if (!ptr)
+               return len;
+
+       end = ptr + len / 4;

sizeof(*ptr) might be better than 4.

Device tree explicitly specifies that cells are 32-bit, so this can't ever be anything other than 4. But I'll change it anyway if you prefer.

I see sizeof() used in the lifdt code, so this might not go upstream as is.

Quoted 23 lines
Quoted 9 lines

include/fdtdec.h struct fdt_memory {

Quoted 5 lines
include/fdtdec.h +4 -0
+
+       while (ptr + na + ns <= end) {
+               if (i == index) {
+                       res->start = fdt_addr_to_cpu(*ptr);

This doesn't deal with 64-bit addresses. There is a half-hearted attempt with fdt_addr_t, but I wonder if we need a helper function like fdt_get_addr(ptr, num_cells)?

The Linux kernel handles this by wrapping it in an of_read_number() helper and always returning u64, like this:

        static inline u64 of_read_number(const __be32 *cell, int size)
        {
                u64 r = 0;

                while (size--)
                        r = (r << 32) | be32_to_cpu(*(cell++));

                return r;
        }
Quoted 2 lines

It obviously only works for size in { 0, 1, 2 }, but I can add a helper like that if you want.

That looks good. It works for the cases we need and it's obvious later where the logic is if we want to extend it.

Regards,
Simon

#16 lore raw

PATCH 3/23 fdt: Add resource parsing functions

Quoted 1 line · Simon Glass

On 19 August 2014 05:35, Thierry Reding <[email protected]> wrote:

[...]

Quoted 13 lines
Quoted 13 lines

The Linux kernel handles this by wrapping it in an of_read_number() helper and always returning u64, like this:

        static inline u64 of_read_number(const __be32 *cell, int size)
        {
                u64 r = 0;

                while (size--)
                        r = (r << 32) | be32_to_cpu(*(cell++));

                return r;
        }
Quoted 6 lines
Quoted 2 lines

It obviously only works for size in { 0, 1, 2 }, but I can add a helper like that if you want.

That looks good. It works for the cases we need and it's obvious later where the logic is if we want to extend it.

This is what I have for U-Boot currently.

static fdt_addr_t fdtdec_get_address(const fdt32_t *ptr, unsigned int cells)

{
	fdt_addr_t addr = 0;

	while (cells--)
		/* do the shift in two steps to avoid warning on 32-bit */
		addr = (addr << 16) << 16 | fdt32_to_cpu(*ptr++);

	return addr;
}

I use the same function to parse the size field of reg entries, even though the types aren't technically the same. But making the types consistent would duplicate the above exactly, so I'm not sure it's worth it.

Alternatively perhaps something like this could be done:

	static u64 fdtdec_get_number(const fdt32_t *ptr, unsigned int cells)
	{
		/* the above */
	}

	static fdt_addr_t fdtdec_get_address(const fdt32_t *ptr, unsigned int cells)
	{
		return fdtdec_get_number(ptr, cells);
	}

	static fdt_size_t fdtdec_get_size(const fdt32_t *ptr, unsigned int cells)
	{
		return fdtdec_get_number(ptr, cells);
	}

Again, I'm not sure it's really worth the trouble since fdt_addr_t and fdt_size_t are both always either u32 or u64.

Thierry
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 819 bytes
Desc: not available
URL: <http://lists.denx.de/pipermail/u-boot/attachments/20140819/d7247af7/attachment.pgp>

#17 lore raw

PATCH 3/23 fdt: Add resource parsing functions

Hi Thierry,

Quoted 25 lines · Thierry Reding
Quoted 1 line · Simon Glass

On 19 August 2014 05:35, Thierry Reding <[email protected]> wrote:

[...]

Quoted 13 lines
Quoted 13 lines

The Linux kernel handles this by wrapping it in an of_read_number() helper and always returning u64, like this:

        static inline u64 of_read_number(const __be32 *cell, int size)
        {
                u64 r = 0;

                while (size--)
                        r = (r << 32) | be32_to_cpu(*(cell++));

                return r;
        }
Quoted 6 lines
Quoted 2 lines

It obviously only works for size in { 0, 1, 2 }, but I can add a helper like that if you want.

That looks good. It works for the cases we need and it's obvious later where the logic is if we want to extend it.

This is what I have for U-Boot currently.

Quoted 7 lines

static fdt_addr_t fdtdec_get_address(const fdt32_t *ptr, unsigned int cells)

{
        fdt_addr_t addr = 0;

        while (cells--)
                /* do the shift in two steps to avoid warning on 32-bit */
                addr = (addr << 16) << 16 | fdt32_to_cpu(*ptr++);

Odd warning! Does 32UL help?

Quoted 8 lines
        return addr;
}

I use the same function to parse the size field of reg entries, even though the types aren't technically the same. But making the types consistent would duplicate the above exactly, so I'm not sure it's worth it.

Seems fine.

Quoted 18 lines

Alternatively perhaps something like this could be done:

        static u64 fdtdec_get_number(const fdt32_t *ptr, unsigned int cells)
        {
                /* the above */
        }

        static fdt_addr_t fdtdec_get_address(const fdt32_t *ptr, unsigned int cells)
        {
                return fdtdec_get_number(ptr, cells);
        }

        static fdt_size_t fdtdec_get_size(const fdt32_t *ptr, unsigned int cells)
        {
                return fdtdec_get_number(ptr, cells);
        }
Quoted 2 lines

Again, I'm not sure it's really worth the trouble since fdt_addr_t and fdt_size_t are both always either u32 or u64.

Yes, although I suppose ultimately these might be 64-bit always, Perhaps we should merge the types?

Regards,
Simon

#18 lore raw

PATCH 3/23 fdt: Add resource parsing functions

Quoted 32 lines · Simon Glass

Hi Thierry,

Quoted 29 lines · Thierry Reding
Quoted 1 line · Simon Glass

On 19 August 2014 05:35, Thierry Reding <[email protected]> wrote:

[...]

Quoted 13 lines
Quoted 13 lines

The Linux kernel handles this by wrapping it in an of_read_number() helper and always returning u64, like this:

        static inline u64 of_read_number(const __be32 *cell, int size)
        {
                u64 r = 0;

                while (size--)
                        r = (r << 32) | be32_to_cpu(*(cell++));

                return r;
        }
Quoted 6 lines
Quoted 2 lines

It obviously only works for size in { 0, 1, 2 }, but I can add a helper like that if you want.

That looks good. It works for the cases we need and it's obvious later where the logic is if we want to extend it.

This is what I have for U-Boot currently.

static fdt_addr_t fdtdec_get_address(const fdt32_t *ptr, unsigned int cells)

{
        fdt_addr_t addr = 0;
Quoted 5 lines
Quoted 3 lines
        while (cells--)
                /* do the shift in two steps to avoid warning on 32-bit */
                addr = (addr << 16) << 16 | fdt32_to_cpu(*ptr++);

Odd warning! Does 32UL help?

The exact warning that I get is this:

warning: left shift count >= width of type

So the problem is that since addr is of type fdt_addr_t which is 32-bit, we're effectively shifting all bits out of the variable. The compiler will generate the same assembly code whether or not I use the single 32- bit shift or two 16-bit shifts, but using the latter the warning is gone. That's on both 32-bit and 64-bit ARM.

Quoted 17 lines
Quoted 17 lines

Alternatively perhaps something like this could be done:

        static u64 fdtdec_get_number(const fdt32_t *ptr, unsigned int cells)
        {
                /* the above */
        }

        static fdt_addr_t fdtdec_get_address(const fdt32_t *ptr, unsigned int cells)
        {
                return fdtdec_get_number(ptr, cells);
        }

        static fdt_size_t fdtdec_get_size(const fdt32_t *ptr, unsigned int cells)
        {
                return fdtdec_get_number(ptr, cells);
        }
Quoted 5 lines
Quoted 2 lines

Again, I'm not sure it's really worth the trouble since fdt_addr_t and fdt_size_t are both always either u32 or u64.

Yes, although I suppose ultimately these might be 64-bit always, Perhaps we should merge the types?

That's one other possibility. On Linux there's one common type for these:

	typedef phys_addr_t resource_size_t;

where phys_addr_t is defined as follows:

	#ifdef CONFIG_PHYS_ADDR_T_64BIT
	typedef u64 phys_addr_t;
	#else
	typedef u32 phys_addr_t;
	#endif

Perhaps we should simply copy that. I take it CONFIG_PHYS_64BIT is U-Boot's equivalent of CONFIG_PHYS_ADDR_T_64BIT? It doesn't seem to be documented anywhere but its usage would indicate that it is. I don't think U-Boot supports things like LPAE, so there's probably no need to control this more fine-grainedly than with a single CONFIG_PHYS_64BIT setting.

Thierry
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 819 bytes
Desc: not available
URL: <http://lists.denx.de/pipermail/u-boot/attachments/20140820/4233234c/attachment.pgp>

#19 lore raw

PATCH 3/23 fdt: Add resource parsing functions

Hi Thierry,

Quoted 41 lines · Thierry Reding
Quoted 32 lines · Simon Glass

Hi Thierry,

Quoted 29 lines · Thierry Reding
Quoted 1 line · Simon Glass

On 19 August 2014 05:35, Thierry Reding <[email protected]> wrote:

[...]

Quoted 13 lines
Quoted 13 lines

The Linux kernel handles this by wrapping it in an of_read_number() helper and always returning u64, like this:

        static inline u64 of_read_number(const __be32 *cell, int size)
        {
                u64 r = 0;

                while (size--)
                        r = (r << 32) | be32_to_cpu(*(cell++));

                return r;
        }
Quoted 6 lines
Quoted 2 lines

It obviously only works for size in { 0, 1, 2 }, but I can add a helper like that if you want.

That looks good. It works for the cases we need and it's obvious later where the logic is if we want to extend it.

This is what I have for U-Boot currently.

static fdt_addr_t fdtdec_get_address(const fdt32_t *ptr, unsigned int cells)

{
        fdt_addr_t addr = 0;
Quoted 5 lines
Quoted 3 lines
        while (cells--)
                /* do the shift in two steps to avoid warning on 32-bit */
                addr = (addr << 16) << 16 | fdt32_to_cpu(*ptr++);

Odd warning! Does 32UL help?

The exact warning that I get is this:

Quoted 7 lines

warning: left shift count >= width of type

So the problem is that since addr is of type fdt_addr_t which is 32-bit, we're effectively shifting all bits out of the variable. The compiler will generate the same assembly code whether or not I use the single 32- bit shift or two 16-bit shifts, but using the latter the warning is gone. That's on both 32-bit and 64-bit ARM.

Well if fdt_addr_t is 32-bit then you are don't going to get a better result with your change - the warning is correct. So I think you need to have an #ifdef for the case where CONFIG_PHYS_64BIT is not defined and deal with it separate. Yes would could just move to 64-bit everwhere, but that will bloat the code I suspect (as we can always do it later anyway).

Quoted 37 lines
Quoted 18 lines
Quoted 18 lines

Alternatively perhaps something like this could be done:

        static u64 fdtdec_get_number(const fdt32_t *ptr, unsigned int cells)
        {
                /* the above */
        }

        static fdt_addr_t fdtdec_get_address(const fdt32_t *ptr, unsigned int cells)
        {
                return fdtdec_get_number(ptr, cells);
        }

        static fdt_size_t fdtdec_get_size(const fdt32_t *ptr, unsigned int cells)
        {
                return fdtdec_get_number(ptr, cells);
        }
Quoted 5 lines
Quoted 2 lines

Again, I'm not sure it's really worth the trouble since fdt_addr_t and fdt_size_t are both always either u32 or u64.

Yes, although I suppose ultimately these might be 64-bit always, Perhaps we should merge the types?

That's one other possibility. On Linux there's one common type for these:

        typedef phys_addr_t resource_size_t;

where phys_addr_t is defined as follows:

        #ifdef CONFIG_PHYS_ADDR_T_64BIT
        typedef u64 phys_addr_t;
        #else
        typedef u32 phys_addr_t;
        #endif
Quoted 6 lines

Perhaps we should simply copy that. I take it CONFIG_PHYS_64BIT is U-Boot's equivalent of CONFIG_PHYS_ADDR_T_64BIT? It doesn't seem to be documented anywhere but its usage would indicate that it is. I don't think U-Boot supports things like LPAE, so there's probably no need to control this more fine-grainedly than with a single CONFIG_PHYS_64BIT setting.

U-Boot does have LPAE on x86 at least. I think using resource_size_t is a good approach.

Regards,
Simon

#20 lore raw

PATCH 4/23 fdt: Add a function to return PCI BDF triplet

In reply to Thierry Reding

From: Thierry Reding <[email protected]>

The fdtdec_pci_get_bdf() function returns the bus, device, function triplet of a PCI device by parsing the "reg" property according to the PCI device tree binding.

---
 include/fdtdec.h | 11 +++++++++++
 lib/fdtdec.c     | 14 ++++++++++++++
 2 files changed, 25 insertions(+)
include/fdtdec.h +11 -0
index e9091eee6bae..56bc29375128 100644
@@ -631,4 +631,15 @@ int fdt_get_named_resource(const void *fdt, int node, const char *property,
 			   const char *names, const char *name,
 			   struct fdt_resource *res);
 
+/**
+ * Look at the reg property of a device node that represents a PCI device
+ * and parse the bus, device and function number from it.
+ *
+ * @param fdt		FDT blob
+ * @param node		node to examine
+ * @param bdf		returns bus, device, function triplet
+ * @return 0 if ok, negative on error
+ */
+int fdtdec_pci_get_bdf(const void *fdt, int node, int *bdf);
+
 #endif
lib/fdtdec.c +14 -0
index fbfae4a7cbaf..d2f2c9164b37 100644
@@ -734,4 +734,18 @@ int fdt_get_named_resource(const void *fdt, int node, const char *property,
 
 	return fdt_get_resource(fdt, node, property, index, res);
 }
+
+int fdtdec_pci_get_bdf(const void *fdt, int node, int *bdf)
+{
+	const fdt32_t *prop;
+	int len;
+
+	prop = fdt_getprop(fdt, node, "reg", &len);
+	if (!prop)
+		return len;
+
+	*bdf = fdt32_to_cpu(*prop) & 0xffffff;
+
+	return 0;
+}
 #endif
Signature · 1 line
2.0.4
#22 lore raw

PATCH 5/23 fdt: Add a subnodes iterator macro

In reply to Thierry Reding

From: Thierry Reding <[email protected]>

The fdt_for_each_subnode() iterator macro provided by this patch can be used to iterate over a device tree node's subnodes. At each iteration a loop variable will be set to the next subnode.

---
 include/libfdt.h | 20 ++++++++++++++++++++
 1 file changed, 20 insertions(+)
include/libfdt.h +20 -0
index 4d7fb2681669..0330d7a29a58 100644
@@ -163,6 +163,26 @@ int fdt_first_subnode(const void *fdt, int offset);
  */
 int fdt_next_subnode(const void *fdt, int offset);
 
+/**
+ * fdt_for_each_subnode - iterate over all subnodes of a parent
+ *
+ * This is actually a wrapper around a for loop and would be used like so:
+ *
+ *	fdt_for_each_subnode(fdt, node, parent) {
+ *		...
+ *		use node
+ *		...
+ *	}
+ *
+ * @fdt:	FDT blob
+ * @node:	child node
+ * @parent:	parent node
+ */
+#define fdt_for_each_subnode(fdt, node, parent)		\
+	for (node = fdt_first_subnode(fdt, parent);	\
+	     node >= 0;					\
+	     node = fdt_next_subnode(fdt, node))
+
 /**********************************************************************/
 /* General functions                                                  */
 /**********************************************************************/
Signature · 1 line
2.0.4
#23 lore raw

PATCH 5/23 fdt: Add a subnodes iterator macro

Quoted 7 lines · Thierry Reding

From: Thierry Reding <[email protected]>

The fdt_for_each_subnode() iterator macro provided by this patch can be used to iterate over a device tree node's subnodes. At each iteration a loop variable will be set to the next subnode.

Will this go upstream to dtc at some point?

Quoted 16 lines
---
 include/libfdt.h | 20 ++++++++++++++++++++
 1 file changed, 20 insertions(+)
include/libfdt.h +4 -0
index 4d7fb2681669..0330d7a29a58 100644
@@ -163,6 +163,26 @@ int fdt_first_subnode(const void *fdt, int offset);
  */
 int fdt_next_subnode(const void *fdt, int offset);
 
+/**
+ * fdt_for_each_subnode - iterate over all subnodes of a parent
+ *
+ * This is actually a wrapper around a for loop and would be used like so:

include/libfdt.h int fdt_first_subnode(const void *fdt, int offset); · line 179

Quoted 10 lines
include/libfdt.h +10 -0
+ *
+ *     fdt_for_each_subnode(fdt, node, parent) {
+ *             ...
+ *             use node
+ *             ...
+ *     }
+ *
+ * @fdt:       FDT blob
+ * @node:      child node
+ * @parent:    parent node

It might be worth mentioning the type of each of these since it is not in the macro.

Quoted 10 lines
include/libfdt.h +6 -1
+ */
+#define fdt_for_each_subnode(fdt, node, parent)                \
+       for (node = fdt_first_subnode(fdt, parent);     \
+            node >= 0;                                 \
+            node = fdt_next_subnode(fdt, node))
+
 /**********************************************************************/
 /* General functions                                                  */
 /**********************************************************************/
--
Quoted 2 lines

2.0.4

Regards,
Simon

#24 lore raw

PATCH 5/23 fdt: Add a subnodes iterator macro

Quoted 7 lines · Simon Glass
Quoted 6 lines · Thierry Reding

From: Thierry Reding <[email protected]>

The fdt_for_each_subnode() iterator macro provided by this patch can be used to iterate over a device tree node's subnodes. At each iteration a loop variable will be set to the next subnode.

Quoted 5 lines
Quoted 1 line

Will this go upstream to dtc at some point?

I suppose it could. I don't know anything about how code flows back and forth between dtc and U-Boot.

Quoted 21 lines
Quoted 21 lines
---
 include/libfdt.h | 20 ++++++++++++++++++++
 1 file changed, 20 insertions(+)
include/libfdt.h +9 -0
index 4d7fb2681669..0330d7a29a58 100644
@@ -163,6 +163,26 @@ int fdt_first_subnode(const void *fdt, int offset);
  */
 int fdt_next_subnode(const void *fdt, int offset);
 
+/**
+ * fdt_for_each_subnode - iterate over all subnodes of a parent
+ *
+ * This is actually a wrapper around a for loop and would be used like so:
+ *
+ *     fdt_for_each_subnode(fdt, node, parent) {
+ *             ...
+ *             use node
+ *             ...
Quoted 8 lines

include/libfdt.h int fdt_first_subnode(const void *fdt, int offset); · line 179

Quoted 5 lines
include/libfdt.h +5 -0
+ *     }
+ *
+ * @fdt:       FDT blob
+ * @node:      child node
+ * @parent:    parent node

It might be worth mentioning the type of each of these since it is not in the macro.

Will do.

Thierry
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 819 bytes
Desc: not available
URL: <http://lists.denx.de/pipermail/u-boot/attachments/20140819/ee8fab39/attachment.pgp>

#25 lore raw

PATCH 5/23 fdt: Add a subnodes iterator macro

Hi Thierry,

Quoted 8 lines · Thierry Reding
Quoted 7 lines · Simon Glass
Quoted 6 lines · Thierry Reding

From: Thierry Reding <[email protected]>

The fdt_for_each_subnode() iterator macro provided by this patch can be used to iterate over a device tree node's subnodes. At each iteration a loop variable will be set to the next subnode.

Quoted 8 lines
Quoted 5 lines
Quoted 1 line

Will this go upstream to dtc at some point?

I suppose it could. I don't know anything about how code flows back and forth between dtc and U-Boot.

Well normally we try to send changes upstream to minimise the diff between libfdt and U-Boot. You can join devicetree-compiler at vger.kernel.org and send patches. If they get modified upstream then I can apply a diff to U-Boot when they are applied.

Regards,
Simon

#26 lore raw

PATCH 5/23 fdt: Add a subnodes iterator macro

Quoted 17 lines · Simon Glass

Hi Thierry,

Quoted 14 lines · Thierry Reding
Quoted 12 lines · Simon Glass
Quoted 7 lines · Thierry Reding

From: Thierry Reding <[email protected]>

The fdt_for_each_subnode() iterator macro provided by this patch can be used to iterate over a device tree node's subnodes. At each iteration a loop variable will be set to the next subnode.

Will this go upstream to dtc at some point?

Quoted 8 lines
Quoted 2 lines

I suppose it could. I don't know anything about how code flows back and forth between dtc and U-Boot.

Well normally we try to send changes upstream to minimise the diff between libfdt and U-Boot. You can join devicetree-compiler at vger.kernel.org and send patches. If they get modified upstream then I can apply a diff to U-Boot when they are applied.

Okay, I'll prepare a patch against upstream dtc then.

Thierry
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 819 bytes
Desc: not available
URL: <http://lists.denx.de/pipermail/u-boot/attachments/20140819/b7b20d59/attachment.pgp>

#27 lore raw

PATCH 6/23 pci: Abort early if bus does not exist

In reply to Thierry Reding

From: Thierry Reding <[email protected]>

When listing the devices on a PCI bus, the current code will blindly try to access all devices. Internally this causes pci_bus_to_hose() to be repeatedly called and output an error message every time. Prevent this by calling pci_bus_to_hose() once and abort early if no bus was found.

---
 common/cmd_pci.c | 4 ++++
 1 file changed, 4 insertions(+)
common/cmd_pci.c +4 -0
index a1ba42e2f3a2..5a6048c92604 100644
@@ -42,12 +42,16 @@ void pci_header_show_brief(pci_dev_t dev);
  */
 void pciinfo(int BusNum, int ShortPCIListing)
 {
+	struct pci_controller *hose = pci_bus_to_hose(BusNum);
 	int Device;
 	int Function;
 	unsigned char HeaderType;
 	unsigned short VendorID;
 	pci_dev_t dev;
 
+	if (!hose)
+		return;
+
 	printf("Scanning PCI devices on bus %d\n", BusNum);
 
 	if (ShortPCIListing) {
Signature · 1 line
2.0.4
#28 lore raw

PATCH 7/23 pci: Honour pci_skip_dev()

In reply to Thierry Reding

From: Thierry Reding <[email protected]>

When enumerating devices, honour the pci_skip_dev() function. This can be used by PCI controller drivers to restrict which devices will be probed.

This is required by the NVIDIA Tegra PCIe controller driver, which will fail with a data abort exception if an access is attempted to a device number larger than 0 outside of bus 0. pci_skip_dev() is therefore implemented to prevent any such accesses.

---
 common/cmd_pci.c  | 3 +++
 drivers/pci/pci.c | 3 +++
 include/pci.h     | 1 +
 3 files changed, 7 insertions(+)
common/cmd_pci.c +3 -0
index 5a6048c92604..e3a77e35820c 100644
@@ -71,6 +71,9 @@ void pciinfo(int BusNum, int ShortPCIListing)
 
 			dev = PCI_BDF(BusNum, Device, Function);
 
+			if (pci_skip_dev(hose, dev))
+				continue;
+
 			pci_read_config_word(dev, PCI_VENDOR_ID, &VendorID);
 			if ((VendorID == 0xFFFF) || (VendorID == 0x0000))
 				continue;
drivers/pci/pci.c +3 -0
index ed113bf4022f..61882ba1462f 100644
@@ -195,6 +195,9 @@ pci_dev_t pci_find_devices(struct pci_device_id *ids, int index)
 			     bdf < PCI_BDF(bus + 1, 0, 0);
 #endif
 			     bdf += PCI_BDF(0, 0, 1)) {
+				if (pci_skip_dev(hose, bdf))
+					continue;
+
 				if (!PCI_FUNC(bdf)) {
 					pci_read_config_byte(bdf,
 							     PCI_HEADER_TYPE,
include/pci.h +1 -0
index 461f17c05895..133fff4957b1 100644
@@ -623,6 +623,7 @@ extern void pci_register_hose(struct pci_controller* hose);
 extern struct pci_controller* pci_bus_to_hose(int bus);
 extern struct pci_controller *find_hose_by_cfg_addr(void *cfg_addr);
 
+extern int pci_skip_dev(struct pci_controller *hose, pci_dev_t dev);
 extern int pci_hose_scan(struct pci_controller *hose);
 extern int pci_hose_scan_bus(struct pci_controller *hose, int bus);
 
Signature · 1 line
2.0.4
#29 lore raw

PATCH 8/23 Add pr_fmt() macro

In reply to Thierry Reding

From: Thierry Reding <[email protected]>

This macro can be overridden in source files (before including common.h) and can be used to specify a prefix for debug and error messages. An example of how to use this is shown below:

	#define pr_fmt(fmt) "foo: " fmt

	#include <common.h>

	...
	debug("bar");

The resulting message will read:

foo: bar

---
 include/common.h | 14 +++++++++-----
 1 file changed, 9 insertions(+), 5 deletions(-)
include/common.h +9 -5
index 1d6cb48ff078..65db04b452d7 100644
@@ -99,15 +99,19 @@ typedef volatile unsigned char	vu_char;
 #define _DEBUG	0
 #endif
 
+#ifndef pr_fmt
+#define pr_fmt(fmt) fmt
+#endif
+
 /*
  * Output a debug text when condition "cond" is met. The "cond" should be
  * computed by a preprocessor in the best case, allowing for the best
  * optimization.
  */
-#define debug_cond(cond, fmt, args...)		\
-	do {					\
-		if (cond)			\
-			printf(fmt, ##args);	\
+#define debug_cond(cond, fmt, args...)			\
+	do {						\
+		if (cond)				\
+			printf(pr_fmt(fmt), ##args);	\
 	} while (0)
 
 #define debug(fmt, args...)			\
@@ -129,7 +133,7 @@ void __assert_fail(const char *assertion, const char *file, unsigned line,
 		__assert_fail(#x, __FILE__, __LINE__, __func__); })
 
 #define error(fmt, args...) do {					\
-		printf("ERROR: " fmt "\nat %s:%d/%s()\n",		\
+		printf("ERROR: " pr_fmt(fmt) "\nat %s:%d/%s()\n",	\
 			##args, __FILE__, __LINE__, __func__);		\
 } while (0)
 
Signature · 1 line
2.0.4
#30 lore raw

PATCH 8/23 Add pr_fmt() macro

Quoted 13 lines · Thierry Reding

From: Thierry Reding <[email protected]>

This macro can be overridden in source files (before including common.h) and can be used to specify a prefix for debug and error messages. An example of how to use this is shown below:

        #define pr_fmt(fmt) "foo: " fmt

        #include <common.h>

        ...
        debug("bar");
Quoted 5 lines

The resulting message will read:

foo: bar

Seems OK. But I wonder if a string might be simpler?

#define DEBUG_PREFIX "foo: "

+#ifndef DEBUG_PREFIX
+#define DEBUG_PREFIX ""
+#endif

...

                     printf(DEBUG_PREFIX ##args);    \
Quoted 42 lines
---
 include/common.h | 14 +++++++++-----
 1 file changed, 9 insertions(+), 5 deletions(-)
include/common.h +9 -6
index 1d6cb48ff078..65db04b452d7 100644
@@ -99,15 +99,19 @@ typedef volatile unsigned char      vu_char;
 #define _DEBUG 0
 #endif
 
+#ifndef pr_fmt
+#define pr_fmt(fmt) fmt
+#endif
+
 /*
  * Output a debug text when condition "cond" is met. The "cond" should be
  * computed by a preprocessor in the best case, allowing for the best
  * optimization.
  */
-#define debug_cond(cond, fmt, args...)         \
-       do {                                    \
-               if (cond)                       \
-                       printf(fmt, ##args);    \
+#define debug_cond(cond, fmt, args...)                 \
+       do {                                            \
+               if (cond)                               \
+                       printf(pr_fmt(fmt), ##args);    \
        } while (0)
 
 #define debug(fmt, args...)                    \
@@ -129,7 +133,7 @@ void __assert_fail(const char *assertion, const char *file, unsigned line,
                __assert_fail(#x, __FILE__, __LINE__, __func__); })
 
 #define error(fmt, args...) do {                                       \
-               printf("ERROR: " fmt "\nat %s:%d/%s()\n",               \
+               printf("ERROR: " pr_fmt(fmt) "\nat %s:%d/%s()\n",       \
                        ##args, __FILE__, __LINE__, __func__);          \
 } while (0)
 
--
Quoted 2 lines

2.0.4

Regards,
Simon

#31 lore raw

PATCH 8/23 Add pr_fmt() macro

Quoted 26 lines · Simon Glass
Quoted 13 lines · Thierry Reding

From: Thierry Reding <[email protected]>

This macro can be overridden in source files (before including common.h) and can be used to specify a prefix for debug and error messages. An example of how to use this is shown below:

        #define pr_fmt(fmt) "foo: " fmt

        #include <common.h>

        ...
        debug("bar");
Quoted 5 lines

The resulting message will read:

foo: bar

Seems OK. But I wonder if a string might be simpler?

#define DEBUG_PREFIX "foo: "

Review

Quoted 3 lines
(quoted diff) +3 -0
+#ifndef DEBUG_PREFIX
+#define DEBUG_PREFIX ""
+#endif

The advantage of using the macro is that it can perform more complicated transformations on the format string, like this for example:

	#define pr_fmt(fmt) "foo: %s():" fmt, __func__

Thierry
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 819 bytes
Desc: not available
URL: <http://lists.denx.de/pipermail/u-boot/attachments/20140819/c2923e13/attachment.pgp>

#32 lore raw

PATCH 8/23 Add pr_fmt() macro

Hi Thierry,

Quoted 27 lines · Thierry Reding
Quoted 26 lines · Simon Glass
Quoted 13 lines · Thierry Reding

From: Thierry Reding <[email protected]>

This macro can be overridden in source files (before including common.h) and can be used to specify a prefix for debug and error messages. An example of how to use this is shown below:

        #define pr_fmt(fmt) "foo: " fmt

        #include <common.h>

        ...
        debug("bar");
Quoted 5 lines

The resulting message will read:

foo: bar

Seems OK. But I wonder if a string might be simpler?

#define DEBUG_PREFIX "foo: "

Quoted 8 lines

Review

Quoted 3 lines
(quoted diff) +3 -0
+#ifndef DEBUG_PREFIX
+#define DEBUG_PREFIX ""
+#endif

The advantage of using the macro is that it can perform more complicated transformations on the format string, like this for example:

        #define pr_fmt(fmt) "foo: %s():" fmt, __func__

OK, I figured you might want something like that.

Quoted 2 lines

Thierry

Regards,
Simon

#33 lore raw

PATCH 9/23 ARM: tegra: Implement tegra_plle_enable()

In reply to Thierry Reding

From: Thierry Reding <[email protected]>

This function is required by PCIe and SATA. This patch implements it on Tegra20, Tegra30 and Tegra124. It isn't implemented for Tegra114 because it doesn't support PCIe or SATA.

---
 arch/arm/cpu/tegra124-common/clock.c       | 109 ++++++++++++++++++++
 arch/arm/cpu/tegra20-common/clock.c        | 137 +++++++++++++++++++++++++
 arch/arm/cpu/tegra30-common/clock.c        | 154 +++++++++++++++++++++++++++++
 arch/arm/include/asm/arch-tegra124/clock.h |   2 +
 arch/arm/include/asm/arch-tegra20/clock.h  |   2 +
 arch/arm/include/asm/arch-tegra30/clock.h  |   2 +
 6 files changed, 406 insertions(+)
arch/arm/cpu/tegra124-common/clock.c +109 -0
index 739436326eca..fc8bd194ddc9 100644
@@ -824,3 +824,112 @@ void arch_timer_init(void)
 	writel(val, &sysctr->cntcr);
 	debug("%s: TSC CNTCR = 0x%08X\n", __func__, val);
 }
+
+#define PLLE_SS_CNTL 0x68
+#define  PLLE_SS_CNTL_SSCINCINTR(x) (((x) & 0x3f) << 24)
+#define  PLLE_SS_CNTL_SSCINC(x) (((x) & 0xff) << 16)
+#define  PLLE_SS_CNTL_SSCINVERT (1 << 15)
+#define  PLLE_SS_CNTL_SSCCENTER (1 << 14)
+#define  PLLE_SS_CNTL_SSCBYP (1 << 12)
+#define  PLLE_SS_CNTL_INTERP_RESET (1 << 11)
+#define  PLLE_SS_CNTL_BYPASS_SS (1 << 10)
+#define  PLLE_SS_CNTL_SSCMAX(x) (((x) & 0x1ff) << 0)
+
+#define PLLE_BASE 0x0e8
+#define  PLLE_BASE_ENABLE (1 << 30)
+#define  PLLE_BASE_LOCK_OVERRIDE (1 << 29)
+#define  PLLE_BASE_PLDIV_CML(x) (((x) & 0xf) << 24)
+#define  PLLE_BASE_NDIV(x) (((x) & 0xff) << 8)
+#define  PLLE_BASE_MDIV(x) (((x) & 0xff) << 0)
+
+#define PLLE_MISC 0x0ec
+#define  PLLE_MISC_IDDQ_SWCTL (1 << 14)
+#define  PLLE_MISC_IDDQ_OVERRIDE (1 << 13)
+#define  PLLE_MISC_LOCK_ENABLE (1 << 9)
+#define  PLLE_MISC_PTS (1 << 8)
+#define  PLLE_MISC_VREG_BG_CTRL(x) (((x) & 0x3) << 4)
+#define  PLLE_MISC_VREG_CTRL(x) (((x) & 0x3) << 2)
+
+#define PLLE_AUX 0x48c
+#define  PLLE_AUX_SEQ_ENABLE (1 << 24)
+#define  PLLE_AUX_ENABLE_SWCTL (1 << 4)
+
+int tegra_plle_enable(void)
+{
+	unsigned int m = 1, n = 200, cpcon = 13;
+	u32 value;
+
+	value = readl(NV_PA_CLK_RST_BASE + PLLE_BASE);
+	value &= ~PLLE_BASE_LOCK_OVERRIDE;
+	writel(value, NV_PA_CLK_RST_BASE + PLLE_BASE);
+
+	value = readl(NV_PA_CLK_RST_BASE + PLLE_AUX);
+	value |= PLLE_AUX_ENABLE_SWCTL;
+	value &= ~PLLE_AUX_SEQ_ENABLE;
+	writel(value, NV_PA_CLK_RST_BASE + PLLE_AUX);
+
+	udelay(1);
+
+	value = readl(NV_PA_CLK_RST_BASE + PLLE_MISC);
+	value |= PLLE_MISC_IDDQ_SWCTL;
+	value &= ~PLLE_MISC_IDDQ_OVERRIDE;
+	value |= PLLE_MISC_LOCK_ENABLE;
+	value |= PLLE_MISC_PTS;
+	value |= PLLE_MISC_VREG_BG_CTRL(3);
+	value |= PLLE_MISC_VREG_CTRL(2);
+	writel(value, NV_PA_CLK_RST_BASE + PLLE_MISC);
+
+	udelay(5);
+
+	value = readl(NV_PA_CLK_RST_BASE + PLLE_SS_CNTL);
+	value |= PLLE_SS_CNTL_SSCBYP | PLLE_SS_CNTL_INTERP_RESET |
+		 PLLE_SS_CNTL_BYPASS_SS;
+	writel(value, NV_PA_CLK_RST_BASE + PLLE_SS_CNTL);
+
+	value = readl(NV_PA_CLK_RST_BASE + PLLE_BASE);
+	value &= ~PLLE_BASE_PLDIV_CML(0xf);
+	value &= ~PLLE_BASE_NDIV(0xff);
+	value &= ~PLLE_BASE_MDIV(0xff);
+	value |= PLLE_BASE_PLDIV_CML(cpcon);
+	value |= PLLE_BASE_NDIV(n);
+	value |= PLLE_BASE_MDIV(m);
+	writel(value, NV_PA_CLK_RST_BASE + PLLE_BASE);
+
+	udelay(1);
+
+	value = readl(NV_PA_CLK_RST_BASE + PLLE_BASE);
+	value |= PLLE_BASE_ENABLE;
+	writel(value, NV_PA_CLK_RST_BASE + PLLE_BASE);
+
+	/* wait for lock */
+	udelay(300);
+
+	value = readl(NV_PA_CLK_RST_BASE + PLLE_SS_CNTL);
+	value &= ~PLLE_SS_CNTL_SSCINVERT;
+	value &= ~PLLE_SS_CNTL_SSCCENTER;
+
+	value &= ~PLLE_SS_CNTL_SSCINCINTR(0x3f);
+	value &= ~PLLE_SS_CNTL_SSCINC(0xff);
+	value &= ~PLLE_SS_CNTL_SSCMAX(0x1ff);
+
+	value |= PLLE_SS_CNTL_SSCINCINTR(0x20);
+	value |= PLLE_SS_CNTL_SSCINC(0x01);
+	value |= PLLE_SS_CNTL_SSCMAX(0x25);
+
+	writel(value, NV_PA_CLK_RST_BASE + PLLE_SS_CNTL);
+
+	value = readl(NV_PA_CLK_RST_BASE + PLLE_SS_CNTL);
+	value &= ~PLLE_SS_CNTL_SSCBYP;
+	value &= ~PLLE_SS_CNTL_BYPASS_SS;
+	writel(value, NV_PA_CLK_RST_BASE + PLLE_SS_CNTL);
+
+	udelay(1);
+
+	value = readl(NV_PA_CLK_RST_BASE + PLLE_SS_CNTL);
+	value &= ~PLLE_SS_CNTL_INTERP_RESET;
+	writel(value, NV_PA_CLK_RST_BASE + PLLE_SS_CNTL);
+
+	udelay(1);
+
+	return 0;
+}
arch/arm/cpu/tegra20-common/clock.c +137 -0

146 lines not on this page · raw message

arch/arm/cpu/tegra30-common/clock.c +154 -0

163 lines not on this page · raw message

arch/arm/include/asm/arch-tegra124/clock.h +2 -0
index 8e39d21a7b5e..8e650862529e 100644
@@ -16,4 +16,6 @@
 #define OSC_FREQ_SHIFT          28
 #define OSC_FREQ_MASK           (0xF << OSC_FREQ_SHIFT)
 
+int tegra_plle_enable(void);
+
 #endif	/* _TEGRA124_CLOCK_H_ */
arch/arm/include/asm/arch-tegra20/clock.h +2 -0
index 889c65a16f1f..4df8da96e2a3 100644
@@ -15,4 +15,6 @@
 #define OSC_FREQ_SHIFT          30
 #define OSC_FREQ_MASK           (3U << OSC_FREQ_SHIFT)
 
+int tegra_plle_enable(void);
+
 #endif	/* _TEGRA20_CLOCK_H */
arch/arm/include/asm/arch-tegra30/clock.h +2 -0
index 2f24a75cc4c3..410c35289978 100644
@@ -25,4 +25,6 @@
 #define OSC_FREQ_SHIFT          28
 #define OSC_FREQ_MASK           (0xF << OSC_FREQ_SHIFT)
 
+int tegra_plle_enable(void);
+
 #endif	/* _TEGRA30_CLOCK_H_ */
Signature · 1 line
2.0.4
#34 lore raw

PATCH 9/23 ARM: tegra: Implement tegra_plle_enable()

Quoted 5 lines · Thierry Reding

From: Thierry Reding <[email protected]>

This function is required by PCIe and SATA. This patch implements it on Tegra20, Tegra30 and Tegra124. It isn't implemented for Tegra114 because it doesn't support PCIe or SATA.

I see no issue with the structure of the code so,

I know too little about the CAR/PLLE to comment on the actual register IO performed here; someone like Peter De Schrijver should review this really...

#35 lore raw

PATCH 10/23 ARM: tegra: Provide PCIEXCLK reset ID

In reply to Thierry Reding

From: Thierry Reding <[email protected]>

This reset is required for PCIe and the corresponding ID therefore needs to be defined.

---
 arch/arm/cpu/tegra20-common/clock.c              | 4 ++--
 arch/arm/cpu/tegra30-common/clock.c              | 1 +
 arch/arm/include/asm/arch-tegra20/clock-tables.h | 2 +-
 3 files changed, 4 insertions(+), 3 deletions(-)
arch/arm/cpu/tegra20-common/clock.c +2 -2
index d55fbc87c340..7b9e10cd93ae 100644
@@ -333,7 +333,7 @@ static s8 periph_id_to_internal_id[PERIPH_ID_COUNT] = {
 	/* 0x48 */
 	NONE(AFI),
 	NONE(CORESIGHT),
-	NONE(RESERVED74),
+	NONE(PCIEXCLK),
 	NONE(AVPUCQ),
 	NONE(RESERVED76),
 	NONE(RESERVED77),
@@ -495,7 +495,7 @@ enum periph_id clk_id_to_periph_id(int clk_id)
 	case PERIPH_ID_RESERVED30:
 	case PERIPH_ID_RESERVED35:
 	case PERIPH_ID_RESERVED56:
-	case PERIPH_ID_RESERVED74:
+	case PERIPH_ID_PCIEXCLK:
 	case PERIPH_ID_RESERVED76:
 	case PERIPH_ID_RESERVED77:
 	case PERIPH_ID_RESERVED78:
arch/arm/cpu/tegra30-common/clock.c +1 -0
index 8e5c49888219..0eb0f0ade37c 100644
@@ -564,6 +564,7 @@ enum periph_id clk_id_to_periph_id(int clk_id)
 	case PERIPH_ID_RESERVED43:
 	case PERIPH_ID_RESERVED45:
 	case PERIPH_ID_RESERVED56:
+	case PERIPH_ID_PCIEXCLK:
 	case PERIPH_ID_RESERVED76:
 	case PERIPH_ID_RESERVED77:
 	case PERIPH_ID_RESERVED78:
arch/arm/include/asm/arch-tegra20/clock-tables.h +1 -1
index a09cb0197863..894be088cde2 100644
@@ -131,7 +131,7 @@ enum periph_id {
 	/* 72 */
 	PERIPH_ID_AFI,
 	PERIPH_ID_CORESIGHT,
-	PERIPH_ID_RESERVED74,
+	PERIPH_ID_PCIEXCLK,
 	PERIPH_ID_AVPUCQ,
 	PERIPH_ID_RESERVED76,
 	PERIPH_ID_RESERVED77,
Signature · 1 line
2.0.4
#36 lore raw

PATCH 10/23 ARM: tegra: Provide PCIEXCLK reset ID

Quoted 4 lines · Thierry Reding

From: Thierry Reding <[email protected]>

This reset is required for PCIe and the corresponding ID therefore needs to be defined.

It might be worth mentioning in the commit description why this patch does different things for each SoC; namely that some SoCs already define this ID, and the code already contains the parts you're adding here.

Aside from that,

#37 lore raw

PATCH 10/23 ARM: tegra: Provide PCIEXCLK reset ID

Quoted 9 lines · Stephen Warren
Quoted 4 lines · Thierry Reding

From: Thierry Reding <[email protected]>

This reset is required for PCIe and the corresponding ID therefore needs to be defined.

It might be worth mentioning in the commit description why this patch does different things for each SoC; namely that some SoCs already define this ID, and the code already contains the parts you're adding here.

Done.

Quoted 2 lines

Aside from that,

Thanks,
Thierry
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 819 bytes
Desc: not available
URL: <http://lists.denx.de/pipermail/u-boot/attachments/20140822/ec69ee32/attachment.pgp>

#38 lore raw

PATCH 11/23 ARM: tegra: Implement powergate support

In reply to Thierry Reding

From: Thierry Reding <[email protected]>

Implement the powergate API that allows various power partitions to be power up and down.

---
 arch/arm/cpu/tegra-common/Makefile             |  1 +
 arch/arm/cpu/tegra-common/powergate.c          | 80 ++++++++++++++++++++++++++
 arch/arm/include/asm/arch-tegra/powergate.h    | 27 +++++++++
 arch/arm/include/asm/arch-tegra114/powergate.h |  6 ++
 arch/arm/include/asm/arch-tegra124/powergate.h |  6 ++
 arch/arm/include/asm/arch-tegra20/powergate.h  |  6 ++
 arch/arm/include/asm/arch-tegra30/powergate.h  |  6 ++
 7 files changed, 132 insertions(+)
 create mode 100644 arch/arm/cpu/tegra-common/powergate.c
 create mode 100644 arch/arm/include/asm/arch-tegra/powergate.h
 create mode 100644 arch/arm/include/asm/arch-tegra114/powergate.h
 create mode 100644 arch/arm/include/asm/arch-tegra124/powergate.h
 create mode 100644 arch/arm/include/asm/arch-tegra20/powergate.h
 create mode 100644 arch/arm/include/asm/arch-tegra30/powergate.h
arch/arm/cpu/tegra-common/Makefile +1 -0
index 892556e64451..fed618ba8fc9 100644
@@ -13,4 +13,5 @@ obj-y += cache.o
 obj-y += clock.o
 obj-y += lowlevel_init.o
 obj-y += pinmux-common.o
+obj-y += powergate.o
 obj-$(CONFIG_DISPLAY_CPUINFO) += sys_info.o
arch/arm/cpu/tegra-common/powergate.c new file +80 -0

80 lines not on this page · raw message

arch/arm/include/asm/arch-tegra/powergate.h new file +27 -0
new file mode 100644
index 000000000000..53bed37d42c1
@@ -0,0 +1,27 @@
+#ifndef _TEGRA_POWERGATE_H_
+#define _TEGRA_POWERGATE_H_
+
+#include <asm/arch/clock.h>
+
+enum tegra_powergate {
+	TEGRA_POWERGATE_CPU,
+	TEGRA_POWERGATE_3D,
+	TEGRA_POWERGATE_VENC,
+	TEGRA_POWERGATE_PCIE,
+	TEGRA_POWERGATE_VDEC,
+	TEGRA_POWERGATE_L2,
+	TEGRA_POWERGATE_MPE,
+	TEGRA_POWERGATE_HEG,
+	TEGRA_POWERGATE_SATA,
+	TEGRA_POWERGATE_CPU1,
+	TEGRA_POWERGATE_CPU2,
+	TEGRA_POWERGATE_CPU3,
+	TEGRA_POWERGATE_CELP,
+	TEGRA_POWERGATE_3D1,
+};
+
+int tegra_powergate_sequence_power_up(enum tegra_powergate id,
+				      enum periph_id periph);
+int tegra_powergate_power_off(enum tegra_powergate id);
+
+#endif
arch/arm/include/asm/arch-tegra114/powergate.h new file +6 -0
new file mode 100644
index 000000000000..260ea801b81b
@@ -0,0 +1,6 @@
+#ifndef _TEGRA114_POWERGATE_H_
+#define _TEGRA114_POWERGATE_H_
+
+#include <asm/arch-tegra/powergate.h>
+
+#endif /* _TEGRA114_POWERGATE_H_ */
arch/arm/include/asm/arch-tegra124/powergate.h new file +6 -0
new file mode 100644
index 000000000000..8a0cfbaf9665
@@ -0,0 +1,6 @@
+#ifndef _TEGRA124_POWERGATE_H_
+#define _TEGRA124_POWERGATE_H_
+
+#include <asm/arch-tegra/powergate.h>
+
+#endif /* _TEGRA124_POWERGATE_H_ */
arch/arm/include/asm/arch-tegra20/powergate.h new file +6 -0
new file mode 100644
index 000000000000..439d88b7022a
@@ -0,0 +1,6 @@
+#ifndef _TEGRA20_POWERGATE_H_
+#define _TEGRA20_POWERGATE_H_
+
+#include <asm/arch-tegra/powergate.h>
+
+#endif /* _TEGRA20_POWERGATE_H_ */
arch/arm/include/asm/arch-tegra30/powergate.h new file +6 -0
new file mode 100644
index 000000000000..c70e44b6216d
@@ -0,0 +1,6 @@
+#ifndef _TEGRA30_POWERGATE_H_
+#define _TEGRA30_POWERGATE_H_
+
+#include <asm/arch-tegra/powergate.h>
+
+#endif /* _TEGRA30_POWERGATE_H_ */
Signature · 1 line
2.0.4
#39 lore raw

PATCH 11/23 ARM: tegra: Implement powergate support

arch/arm/cpu/tegra-common/powergate.c line 25

Quoted 10 lines · Thierry Reding

From: Thierry Reding <[email protected]>

Implement the powergate API that allows various power partitions to be power up and down.

arch/arm/cpu/tegra-common/powergate.c +2 -0
 
+static int tegra_powergate_set(enum tegra_powergate id, bool state)
 
+	writel(PWRGATE_TOGGLE_START | id, NV_PA_PMC_BASE + PWRGATE_TOGGLE);

Since the power-down/up is an asynchronous operation, don't you need to wait for it to complete here?

arch/arm/cpu/tegra-common/powergate.c line 49

Quoted 13 lines
arch/arm/cpu/tegra-common/powergate.c +12 -0
+	return 0;
+}
 
+static int tegra_powergate_remove_clamping(enum tegra_powergate id)
+{
+	unsigned long value;
+
+	if (id == TEGRA_POWERGATE_VDEC)
+		value = 1 << TEGRA_POWERGATE_PCIE;
+	else if (id == TEGRA_POWERGATE_PCIE)
+		value = 1 << TEGRA_POWERGATE_VDEC;
+	else
+		value = 1 << id;

A comment indicating why there's a special case here would be useful.

Isn't the special-case (HW design bug) restricted to Tegra20, or did it carry over into later chips in order to maintain HW register compatibility?

Quoted 8 lines
arch/arm/include/asm/arch-tegra/powergate.h +6 -0
 
+enum tegra_powergate {
+	TEGRA_POWERGATE_CPU,
+	TEGRA_POWERGATE_3D,
+	TEGRA_POWERGATE_VENC,
+	TEGRA_POWERGATE_PCIE,
+	TEGRA_POWERGATE_VDEC,

arch/arm/include/asm/arch-tegra/powergate.h line 21

Quoted 10 lines
arch/arm/include/asm/arch-tegra/powergate.h +10 -0
+	TEGRA_POWERGATE_L2,
+	TEGRA_POWERGATE_MPE,
+	TEGRA_POWERGATE_HEG,
+	TEGRA_POWERGATE_SATA,
+	TEGRA_POWERGATE_CPU1,
+	TEGRA_POWERGATE_CPU2,
+	TEGRA_POWERGATE_CPU3,
+	TEGRA_POWERGATE_CELP,
+	TEGRA_POWERGATE_3D1,
+};

I thought the list of partitions varied a bit by chip?

Overall the code structure looks good, and on the condition I'm wrong about the variations between chips,

#40 lore raw

PATCH 11/23 ARM: tegra: Implement powergate support

Quoted 6 lines · Stephen Warren
Quoted 4 lines · Thierry Reding

From: Thierry Reding <[email protected]>

Implement the powergate API that allows various power partitions to be power up and down.

Quoted 8 lines

arch/arm/cpu/tegra-common/powergate.c line 25

Quoted 5 lines
arch/arm/cpu/tegra-common/powergate.c +2 -0
 
+static int tegra_powergate_set(enum tegra_powergate id, bool state)
 
+	writel(PWRGATE_TOGGLE_START | id, NV_PA_PMC_BASE + PWRGATE_TOGGLE);

Since the power-down/up is an asynchronous operation, don't you need to wait for it to complete here?

It seems like the PWRGATE_STATUS register can be polled to determine when the operation is finished. I'll implement a loop with a small timeout here. We probably need to do the same in the kernel.

Apparently for newer SoCs (starting with Tegra114) the meaning of the PWRGATE_TOGGLE_START bit has also changed. It should be polled until cleared before starting a new operation and once an operation has been started (PWRGATE_TOGGLE_START set) the bit should be polled until it is cleared again to check that the request was accepted by the PMC.

Quoted 16 lines

arch/arm/cpu/tegra-common/powergate.c line 49

Quoted 13 lines
arch/arm/cpu/tegra-common/powergate.c +12 -0
+	return 0;
+}
 
+static int tegra_powergate_remove_clamping(enum tegra_powergate id)
+{
+	unsigned long value;
+
+	if (id == TEGRA_POWERGATE_VDEC)
+		value = 1 << TEGRA_POWERGATE_PCIE;
+	else if (id == TEGRA_POWERGATE_PCIE)
+		value = 1 << TEGRA_POWERGATE_VDEC;
+	else
+		value = 1 << id;

A comment indicating why there's a special case here would be useful.

Quoted 2 lines

Isn't the special-case (HW design bug) restricted to Tegra20, or did it carry over into later chips in order to maintain HW register compatibility?

As far as I can tell this was carried over for register compatibility. The bits for the PCIE and VDEC partitions are still reversed in Tegra124.

Quoted 12 lines
Quoted 12 lines
arch/arm/include/asm/arch-tegra/powergate.h +10 -0
 
+enum tegra_powergate {
+	TEGRA_POWERGATE_CPU,
+	TEGRA_POWERGATE_3D,
+	TEGRA_POWERGATE_VENC,
+	TEGRA_POWERGATE_PCIE,
+	TEGRA_POWERGATE_VDEC,
+	TEGRA_POWERGATE_L2,
+	TEGRA_POWERGATE_MPE,
+	TEGRA_POWERGATE_HEG,
+	TEGRA_POWERGATE_SATA,
Quoted 8 lines

arch/arm/include/asm/arch-tegra/powergate.h line 21

Quoted 6 lines
arch/arm/include/asm/arch-tegra/powergate.h +6 -0
+	TEGRA_POWERGATE_CPU1,
+	TEGRA_POWERGATE_CPU2,
+	TEGRA_POWERGATE_CPU3,
+	TEGRA_POWERGATE_CELP,
+	TEGRA_POWERGATE_3D1,
+};

I thought the list of partitions varied a bit by chip?

The list of valid partitions varies per chip, but the list of values remains compatible. For the same reason we have a list of partitions in the Linux kernel, but they are checked for validity against the per-SoC list. Not sure if we need to go that far with U-Boot.

Thierry
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 819 bytes
Desc: not available
URL: <http://lists.denx.de/pipermail/u-boot/attachments/20140822/6313133b/attachment.pgp>

#41 lore raw

PATCH 12/23 ARM: tegra: Implement XUSB pad controller

In reply to Thierry Reding

From: Thierry Reding <[email protected]>

This controller was introduced on Tegra114 to handle XUSB pads. On Tegra124 it is also used for PCIe and SATA pin muxing and PHY control. Only the Tegra124 PCIe and SATA functionality is currently implemented, with weak symbols on Tegra114.

Tegra20 and Tegra30 also provide weak symbols for these functions so that drivers can use the same API irrespective of which SoC they're being built for.

---
 arch/arm/cpu/tegra-common/Makefile               |   1 +
 arch/arm/cpu/tegra-common/xusb-padctl.c          |  39 ++
 arch/arm/cpu/tegra124-common/Makefile            |   1 +
 arch/arm/cpu/tegra124-common/xusb-padctl.c       | 766 +++++++++++++++++++++++
 arch/arm/include/asm/arch-tegra/xusb-padctl.h    |  14 +
 arch/arm/include/asm/arch-tegra114/xusb-padctl.h |   6 +
 arch/arm/include/asm/arch-tegra124/xusb-padctl.h |   6 +
 arch/arm/include/asm/arch-tegra20/xusb-padctl.h  |   6 +
 arch/arm/include/asm/arch-tegra30/xusb-padctl.h  |   6 +
 board/nvidia/common/board.c                      |   3 +
 include/dt-bindings/pinctrl/pinctrl-tegra-xusb.h |   7 +
 include/fdtdec.h                                 |   2 +
 lib/fdtdec.c                                     |   1 +
 13 files changed, 858 insertions(+)
 create mode 100644 arch/arm/cpu/tegra-common/xusb-padctl.c
 create mode 100644 arch/arm/cpu/tegra124-common/xusb-padctl.c
 create mode 100644 arch/arm/include/asm/arch-tegra/xusb-padctl.h
 create mode 100644 arch/arm/include/asm/arch-tegra114/xusb-padctl.h
 create mode 100644 arch/arm/include/asm/arch-tegra124/xusb-padctl.h
 create mode 100644 arch/arm/include/asm/arch-tegra20/xusb-padctl.h
 create mode 100644 arch/arm/include/asm/arch-tegra30/xusb-padctl.h
 create mode 100644 include/dt-bindings/pinctrl/pinctrl-tegra-xusb.h
arch/arm/cpu/tegra-common/Makefile +1 -0
index fed618ba8fc9..528ffe0a2fcc 100644
@@ -14,4 +14,5 @@ obj-y += clock.o
 obj-y += lowlevel_init.o
 obj-y += pinmux-common.o
 obj-y += powergate.o
+obj-y += xusb-padctl.o
 obj-$(CONFIG_DISPLAY_CPUINFO) += sys_info.o
arch/arm/cpu/tegra-common/xusb-padctl.c new file +39 -0
new file mode 100644
index 000000000000..2a1d860844c7
@@ -0,0 +1,39 @@
+/*
+ * Copyright (c) 2014, NVIDIA CORPORATION.  All rights reserved.
+ *
+ * SPDX-License-Identifier: GPL-2.0
+ */
+
+#include <common.h>
+#include <errno.h>
+
+#include <asm/arch/xusb-padctl.h>
+
+struct tegra_xusb_phy * __weak tegra_xusb_phy_get(unsigned int type)
+{
+	return NULL;
+}
+
+int __weak tegra_xusb_phy_prepare(struct tegra_xusb_phy *phy)
+{
+	return -ENOSYS;
+}
+
+int __weak tegra_xusb_phy_enable(struct tegra_xusb_phy *phy)
+{
+	return -ENOSYS;
+}
+
+int __weak tegra_xusb_phy_disable(struct tegra_xusb_phy *phy)
+{
+	return -ENOSYS;
+}
+
+int __weak tegra_xusb_phy_unprepare(struct tegra_xusb_phy *phy)
+{
+	return -ENOSYS;
+}
+
+void __weak tegra_xusb_padctl_init(const void *fdt)
+{
+}
arch/arm/cpu/tegra124-common/Makefile +1 -0
index ff77992b330c..7b59fb121614 100644
@@ -8,3 +8,4 @@
 obj-y	+= clock.o
 obj-y	+= funcmux.o
 obj-y	+= pinmux.o
+obj-y	+= xusb-padctl.o
arch/arm/cpu/tegra124-common/xusb-padctl.c new file +766 -0

766 lines not on this page · raw message

arch/arm/include/asm/arch-tegra/xusb-padctl.h new file +14 -0
new file mode 100644
index 000000000000..39d01ae0132e
@@ -0,0 +1,14 @@
+#ifndef _TEGRA_XUSB_PADCTL_H_
+#define _TEGRA_XUSB_PADCTL_H_
+
+struct tegra_xusb_phy;
+
+struct tegra_xusb_phy *tegra_xusb_phy_get(unsigned int type);
+
+void tegra_xusb_padctl_init(const void *fdt);
+int tegra_xusb_phy_prepare(struct tegra_xusb_phy *phy);
+int tegra_xusb_phy_enable(struct tegra_xusb_phy *phy);
+int tegra_xusb_phy_disable(struct tegra_xusb_phy *phy);
+int tegra_xusb_phy_unprepare(struct tegra_xusb_phy *phy);
+
+#endif
arch/arm/include/asm/arch-tegra114/xusb-padctl.h new file +6 -0
new file mode 100644
index 000000000000..2b5c5ff4c912
@@ -0,0 +1,6 @@
+#ifndef _TEGRA114_XUSB_PADCTL_H_
+#define _TEGRA114_XUSB_PADCTL_H_
+
+#include <asm/arch-tegra/xusb-padctl.h>
+
+#endif /* _TEGRA114_XUSB_PADCTL_H_ */
arch/arm/include/asm/arch-tegra124/xusb-padctl.h new file +6 -0
new file mode 100644
index 000000000000..90a9d8042391
@@ -0,0 +1,6 @@
+#ifndef _TEGRA124_XUSB_PADCTL_H_
+#define _TEGRA124_XUSB_PADCTL_H_
+
+#include <asm/arch-tegra/xusb-padctl.h>
+
+#endif /* _TEGRA124_XUSB_PADCTL_H_ */
arch/arm/include/asm/arch-tegra20/xusb-padctl.h new file +6 -0
new file mode 100644
index 000000000000..8204dcdc696b
@@ -0,0 +1,6 @@
+#ifndef _TEGRA20_XUSB_PADCTL_H_
+#define _TEGRA20_XUSB_PADCTL_H_
+
+#include <asm/arch-tegra/xusb-padctl.h>
+
+#endif /* _TEGRA20_XUSB_PADCTL_H_ */
arch/arm/include/asm/arch-tegra30/xusb-padctl.h new file +6 -0
new file mode 100644
index 000000000000..ed429963a3a5
@@ -0,0 +1,6 @@
+#ifndef _TEGRA30_XUSB_PADCTL_H_
+#define _TEGRA30_XUSB_PADCTL_H_
+
+#include <asm/arch-tegra/xusb-padctl.h>
+
+#endif /* _TEGRA30_XUSB_PADCTL_H_ */
board/nvidia/common/board.c +3 -0
index d01abcee13c1..ba6417c5f535 100644
@@ -37,6 +37,7 @@
 #include <asm/arch-tegra/tegra_mmc.h>
 #include <asm/arch-tegra/mmc.h>
 #endif
+#include <asm/arch/xusb-padctl.h>
 #include <i2c.h>
 #include <spi.h>
 #include "emc.h"
@@ -161,6 +162,8 @@ int board_init(void)
 	pin_mux_nand();
 #endif
 
+	tegra_xusb_padctl_init(gd->fdt_blob);
+
 #ifdef CONFIG_TEGRA_LP0
 	/* save Sdram params to PMC 2, 4, and 24 for WB0 */
 	warmboot_save_sdram_params();
include/dt-bindings/pinctrl/pinctrl-tegra-xusb.h new file +7 -0
new file mode 100644
index 000000000000..914d56da9324
@@ -0,0 +1,7 @@
+#ifndef _DT_BINDINGS_PINCTRL_TEGRA_XUSB_H
+#define _DT_BINDINGS_PINCTRL_TEGRA_XUSB_H 1
+
+#define TEGRA_XUSB_PADCTL_PCIE 0
+#define TEGRA_XUSB_PADCTL_SATA 1
+
+#endif /* _DT_BINDINGS_PINCTRL_TEGRA_XUSB_H */
include/fdtdec.h +2 -0
index 56bc29375128..c0464f07961d 100644
@@ -82,6 +82,8 @@ enum fdt_compat_id {
 	COMPAT_NVIDIA_TEGRA20_SFLASH,	/* Tegra 2 SPI flash controller */
 	COMPAT_NVIDIA_TEGRA20_SLINK,	/* Tegra 2 SPI SLINK controller */
 	COMPAT_NVIDIA_TEGRA114_SPI,	/* Tegra 114 SPI controller */
+	COMPAT_NVIDIA_TEGRA124_XUSB_PADCTL,
+					/* Tegra124 XUSB pad controller */
 	COMPAT_SMSC_LAN9215,		/* SMSC 10/100 Ethernet LAN9215 */
 	COMPAT_SAMSUNG_EXYNOS5_SROMC,	/* Exynos5 SROMC */
 	COMPAT_SAMSUNG_S3C2440_I2C,	/* Exynos I2C Controller */
lib/fdtdec.c +1 -0
index d2f2c9164b37..16e0714b0fed 100644
@@ -41,6 +41,7 @@ static const char * const compat_names[COMPAT_COUNT] = {
 	COMPAT(NVIDIA_TEGRA20_SFLASH, "nvidia,tegra20-sflash"),
 	COMPAT(NVIDIA_TEGRA20_SLINK, "nvidia,tegra20-slink"),
 	COMPAT(NVIDIA_TEGRA114_SPI, "nvidia,tegra114-spi"),
+	COMPAT(NVIDIA_TEGRA124_XUSB_PADCTL, "nvidia,tegra124-xusb-padctl"),
 	COMPAT(SMSC_LAN9215, "smsc,lan9215"),
 	COMPAT(SAMSUNG_EXYNOS5_SROMC, "samsung,exynos-sromc"),
 	COMPAT(SAMSUNG_S3C2440_I2C, "samsung,s3c2440-i2c"),
Signature · 1 line
2.0.4
#42 lore raw

PATCH 12/23 ARM: tegra: Implement XUSB pad controller

Quoted 11 lines · Thierry Reding

From: Thierry Reding <[email protected]>

This controller was introduced on Tegra114 to handle XUSB pads. On Tegra124 it is also used for PCIe and SATA pin muxing and PHY control. Only the Tegra124 PCIe and SATA functionality is currently implemented, with weak symbols on Tegra114.

Tegra20 and Tegra30 also provide weak symbols for these functions so that drivers can use the same API irrespective of which SoC they're being built for.

Quoted 5 lines
  arch/arm/include/asm/arch-tegra/xusb-padctl.h    |  14 +
  arch/arm/include/asm/arch-tegra114/xusb-padctl.h |   6 +
  arch/arm/include/asm/arch-tegra124/xusb-padctl.h |   6 +
  arch/arm/include/asm/arch-tegra20/xusb-padctl.h  |   6 +
  arch/arm/include/asm/arch-tegra30/xusb-padctl.h  |   6 +

These per-SoC headers do nothing but include the common header. Why not just have the code include the common header directly? IIRC, that's what we do now for some other modules that are identical. We only need SoC-specific headers if we have SoC-specific information to represent.

arch/arm/cpu/tegra124-common/Makefile line 11

Quoted 6 lines
arch/arm/cpu/tegra124-common/Makefile +1 -0
 
  obj-y	+= clock.o
  obj-y	+= funcmux.o
  obj-y	+= pinmux.o
+obj-y	+= xusb-padctl.o

It looks like there's indentation inconsistency there?

arch/arm/cpu/tegra124-common/xusb-padctl.c line 438

Quoted 8 lines
arch/arm/cpu/tegra124-common/xusb-padctl.c +4 -0
 
+int fdtdec_count_strings(const void *fdt, int node, const char *prop_name)
 
+int fdtdec_get_string_index(const void *fdt, int node, const char *prop_name,
+			    int index, const char **output)
 
+int fdtdec_get_string(const void *fdt, int node, const char *prop_name,

Shouldn't those be in libfdt or similar? I thought I saw a patch to do that.

arch/arm/include/asm/arch-tegra/xusb-padctl.h

Quoted 3 lines
arch/arm/include/asm/arch-tegra/xusb-padctl.h +1 -0
 
+struct tegra_xusb_phy *tegra_xusb_phy_get(unsigned int type);

What is "type"? A comment would be useful, or using an enum type instead.

With those fixed, I don't see anything obviously wrong, so,

#43 lore raw

PATCH 12/23 ARM: tegra: Implement XUSB pad controller

Quoted 18 lines · Stephen Warren
Quoted 11 lines · Thierry Reding

From: Thierry Reding <[email protected]>

This controller was introduced on Tegra114 to handle XUSB pads. On Tegra124 it is also used for PCIe and SATA pin muxing and PHY control. Only the Tegra124 PCIe and SATA functionality is currently implemented, with weak symbols on Tegra114.

Tegra20 and Tegra30 also provide weak symbols for these functions so that drivers can use the same API irrespective of which SoC they're being built for.

Quoted 5 lines
 arch/arm/include/asm/arch-tegra/xusb-padctl.h    |  14 +
 arch/arm/include/asm/arch-tegra114/xusb-padctl.h |   6 +
 arch/arm/include/asm/arch-tegra124/xusb-padctl.h |   6 +
 arch/arm/include/asm/arch-tegra20/xusb-padctl.h  |   6 +
 arch/arm/include/asm/arch-tegra30/xusb-padctl.h  |   6 +
Quoted 4 lines

These per-SoC headers do nothing but include the common header. Why not just have the code include the common header directly? IIRC, that's what we do now for some other modules that are identical. We only need SoC-specific headers if we have SoC-specific information to represent.

Done.

Quoted 8 lines

arch/arm/cpu/tegra124-common/Makefile line 11

Quoted 6 lines
arch/arm/cpu/tegra124-common/Makefile +1 -0
 
 obj-y	+= clock.o
 obj-y	+= funcmux.o
 obj-y	+= pinmux.o
+obj-y	+= xusb-padctl.o

It looks like there's indentation inconsistency there?

I don't have it in my local tree. But perhaps I've fixed it meanwhile without remembering?

Quoted 10 lines

arch/arm/cpu/tegra124-common/xusb-padctl.c line 438

Quoted 8 lines
arch/arm/cpu/tegra124-common/xusb-padctl.c +4 -0
 
+int fdtdec_count_strings(const void *fdt, int node, const char *prop_name)
 
+int fdtdec_get_string_index(const void *fdt, int node, const char *prop_name,
+			    int index, const char **output)
 
+int fdtdec_get_string(const void *fdt, int node, const char *prop_name,

Shouldn't those be in libfdt or similar? I thought I saw a patch to do that.

I'm not sure where exactly to put them. They are slightly different from the fdt_get_string_index() that's implemented in an earlier patch in that they return a pointer to the string at a given index whereas the fdt_get_string_index() function looks up a string in a list and returns its index. The naming is horrible, I know, but I'm open to suggestions.

Quoted 5 lines

arch/arm/include/asm/arch-tegra/xusb-padctl.h

Quoted 3 lines
arch/arm/include/asm/arch-tegra/xusb-padctl.h +1 -0
 
+struct tegra_xusb_phy *tegra_xusb_phy_get(unsigned int type);

What is "type"? A comment would be useful, or using an enum type instead.

The value should come directly from DT, so an enum won't be very useful. It's also very much SoC dependent, so it's difficult to give an example that works for all SoCs. I'll try what I can come up with for a comment.

Thierry
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 819 bytes
Desc: not available
URL: <http://lists.denx.de/pipermail/u-boot/attachments/20140822/6312c0fe/attachment.pgp>

#44 lore raw

PATCH 12/23 ARM: tegra: Implement XUSB pad controller

In reply to Stephen Warren
Quoted 1 line · Stephen Warren

On 08/18/2014 01:16 AM, Thierry Reding wrote:

[...]

Quoted 10 lines

arch/arm/cpu/tegra124-common/xusb-padctl.c line 438

Quoted 8 lines
arch/arm/cpu/tegra124-common/xusb-padctl.c +4 -0
 
+int fdtdec_count_strings(const void *fdt, int node, const char *prop_name)
 
+int fdtdec_get_string_index(const void *fdt, int node, const char *prop_name,
+			    int index, const char **output)
 
+int fdtdec_get_string(const void *fdt, int node, const char *prop_name,

Shouldn't those be in libfdt or similar? I thought I saw a patch to do that.

I renamed the current fdt_get_string_index() to fdt_find_string() in the hope of removing the naming ambiguity and added these two as fdt_get_string_index() and fdt_get_string(). And I moved the fdtdec_count_strings() into libfdt as well and named it fdt_count_strings().

Thierry
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 819 bytes
Desc: not available
URL: <http://lists.denx.de/pipermail/u-boot/attachments/20140822/336fd5c7/attachment.pgp>

#45 lore raw

PATCH 13/23 ARM: tegra: Add XUSB pad controller on Tegra124

In reply to Thierry Reding

From: Thierry Reding <[email protected]>

The XUSB pad controller is used for pinmuxing of the XUSB, PCIe and SATA lanes.

---
 arch/arm/dts/tegra124.dtsi | 10 ++++++++++
 1 file changed, 10 insertions(+)
arch/arm/dts/tegra124.dtsi +10 -0
index 4561c5f83943..d48f1a34ec3c 100644
@@ -1,5 +1,6 @@
 #include <dt-bindings/gpio/tegra-gpio.h>
 #include <dt-bindings/interrupt-controller/arm-gic.h>
+#include <dt-bindings/pinctrl/pinctrl-tegra-xusb.h>
 
 #include "skeleton.dtsi"
 
@@ -192,6 +193,15 @@
 		clocks = <&tegra_car 105>;
 	};
 
+	padctl: padctl at 7009f000 {
+		compatible = "nvidia,tegra124-xusb-padctl";
+		reg = <0x7009f000 0x1000>;
+		resets = <&tegra_car 142>;
+		reset-names = "padctl";
+
+		#phy-cells = <1>;
+	};
+
 	sdhci at 700b0000 {
 		compatible = "nvidia,tegra124-sdhci";
 		reg = <0x700b0000 0x200>;
Signature · 1 line
2.0.4
#46 lore raw

PATCH 13/23 ARM: tegra: Add XUSB pad controller on Tegra124

Quoted 4 lines · Thierry Reding

From: Thierry Reding <[email protected]>

The XUSB pad controller is used for pinmuxing of the XUSB, PCIe and SATA lanes.

Aside from the differing #address-cells at the top-level of the DT, this matches what's been proposed for the Linux kernel, so,

#47 lore raw

PATCH 14/23 ARM: tegra: Enable XUSB pad controller on Jetson TK1

In reply to Thierry Reding

From: Thierry Reding <[email protected]>

Add the PCIe and SATA lane configuration to the Jetson TK1 device tree, so that the XUSB pad controller can be appropriately configured.

---
 arch/arm/dts/tegra124-jetson-tk1.dts | 26 ++++++++++++++++++++++++++
 1 file changed, 26 insertions(+)
arch/arm/dts/tegra124-jetson-tk1.dts +26 -0
index 464287e03ecf..f61736f0ef0f 100644
@@ -66,6 +66,32 @@
 		spi-max-frequency = <25000000>;
 	};
 
+	padctl at 7009f000 {
+		pinctrl-0 = <&padctl_default>;
+		pinctrl-names = "default";
+
+		padctl_default: pinmux {
+			usb3 {
+				nvidia,lanes = "pcie-0", "pcie-1";
+				nvidia,function = "usb3";
+				nvidia,iddq = <0>;
+			};
+
+			pcie {
+				nvidia,lanes = "pcie-2", "pcie-3",
+					       "pcie-4";
+				nvidia,function = "pcie";
+				nvidia,iddq = <0>;
+			};
+
+			sata {
+				nvidia,lanes = "sata-0";
+				nvidia,function = "sata";
+				nvidia,iddq = <0>;
+			};
+		};
+	};
+
 	sdhci at 700b0400 {
 		status = "okay";
 		cd-gpios = <&gpio 170 1>; /* gpio PV2 */
Signature · 1 line
2.0.4
#48 lore raw

PATCH 14/23 ARM: tegra: Enable XUSB pad controller on Jetson TK1

Quoted 4 lines · Thierry Reding

From: Thierry Reding <[email protected]>

Add the PCIe and SATA lane configuration to the Jetson TK1 device tree, so that the XUSB pad controller can be appropriately configured.

Aside from the differing #address-cells at the top-level of the DT, this matches what's been proposed for the Linux kernel, so,

#49 lore raw

PATCH 15/23 pci: tegra: Add Tegra PCIe driver

In reply to Thierry Reding

From: Thierry Reding <[email protected]>

Add support for the PCIe controller found on some generations of Tegra. Tegra20 has 2 root ports with a total of 4 lanes, Tegra30 has 3 root ports with a total of 6 lanes and Tegra124 has 2 root ports with a total of 5 lanes.

---
 drivers/pci/Makefile    |    1 +
 drivers/pci/pci_tegra.c | 1133 +++++++++++++++++++++++++++++++++++++++++++++++
 include/fdtdec.h        |    3 +
 lib/fdtdec.c            |    3 +
 4 files changed, 1140 insertions(+)
 create mode 100644 drivers/pci/pci_tegra.c
drivers/pci/Makefile +1 -0
index e73a49861983..8eb2320539f9 100644
@@ -15,5 +15,6 @@ obj-$(CONFIG_FTPCI100) += pci_ftpci100.o
 obj-$(CONFIG_SH4_PCI) += pci_sh4.o
 obj-$(CONFIG_SH7751_PCI) +=pci_sh7751.o
 obj-$(CONFIG_SH7780_PCI) +=pci_sh7780.o
+obj-$(CONFIG_PCI_TEGRA) += pci_tegra.o
 obj-$(CONFIG_TSI108_PCI) += tsi108_pci.o
 obj-$(CONFIG_WINBOND_83C553) += w83c553f.o
drivers/pci/pci_tegra.c new file +1133 -0

1,133 lines not on this page · raw message

include/fdtdec.h +3 -0
index c0464f07961d..2869cd0ae206 100644
@@ -82,6 +82,9 @@ enum fdt_compat_id {
 	COMPAT_NVIDIA_TEGRA20_SFLASH,	/* Tegra 2 SPI flash controller */
 	COMPAT_NVIDIA_TEGRA20_SLINK,	/* Tegra 2 SPI SLINK controller */
 	COMPAT_NVIDIA_TEGRA114_SPI,	/* Tegra 114 SPI controller */
+	COMPAT_NVIDIA_TEGRA124_PCIE,	/* Tegra 124 PCIe controller */
+	COMPAT_NVIDIA_TEGRA30_PCIE,	/* Tegra 30 PCIe controller */
+	COMPAT_NVIDIA_TEGRA20_PCIE,	/* Tegra 20 PCIe controller */
 	COMPAT_NVIDIA_TEGRA124_XUSB_PADCTL,
 					/* Tegra124 XUSB pad controller */
 	COMPAT_SMSC_LAN9215,		/* SMSC 10/100 Ethernet LAN9215 */
lib/fdtdec.c +3 -0
index 16e0714b0fed..3e41b0c99683 100644
@@ -41,6 +41,9 @@ static const char * const compat_names[COMPAT_COUNT] = {
 	COMPAT(NVIDIA_TEGRA20_SFLASH, "nvidia,tegra20-sflash"),
 	COMPAT(NVIDIA_TEGRA20_SLINK, "nvidia,tegra20-slink"),
 	COMPAT(NVIDIA_TEGRA114_SPI, "nvidia,tegra114-spi"),
+	COMPAT(NVIDIA_TEGRA124_PCIE, "nvidia,tegra124-pcie"),
+	COMPAT(NVIDIA_TEGRA30_PCIE, "nvidia,tegra30-pcie"),
+	COMPAT(NVIDIA_TEGRA20_PCIE, "nvidia,tegra20-pcie"),
 	COMPAT(NVIDIA_TEGRA124_XUSB_PADCTL, "nvidia,tegra124-xusb-padctl"),
 	COMPAT(SMSC_LAN9215, "smsc,lan9215"),
 	COMPAT(SAMSUNG_EXYNOS5_SROMC, "samsung,exynos-sromc"),
Signature · 1 line
2.0.4
#50 lore raw

PATCH 15/23 pci: tegra: Add Tegra PCIe driver

Quoted 8 lines · Thierry Reding

From: Thierry Reding <[email protected]>

Add support for the PCIe controller found on some generations of Tegra. Tegra20 has 2 root ports with a total of 4 lanes, Tegra30 has 3 root ports with a total of 6 lanes and Tegra124 has 2 root ports with a total of 5 lanes.

drivers/pci/pci_tegra.c line 6

Quoted 6 lines
drivers/pci/pci_tegra.c +5 -0
 
+ * Copyright (c) 2010, CompuLab, Ltd.
+ * Author: Mike Rapoport <[email protected]>
+ *
+ * Based on NVIDIA PCIe driver
+ * Copyright (c) 2008-2009, NVIDIA Corporation.

Presumably also at least (c) 2013-2014 NVIDIA too?

Do you have Mike's S-o-b for the initial work?

drivers/pci/pci_tegra.c line 295

Quoted 12 lines
drivers/pci/pci_tegra.c +12 -0
+static int tegra_pcie_read_conf(struct pci_controller *hose, pci_dev_t bdf,
+				int where, u32 *value)
+{
+	struct tegra_pcie *pcie = to_tegra_pcie(hose);
+	unsigned long address;
+	int err;
+
+	err = tegra_pcie_conf_address(pcie, bdf, where, &address);
+	if (err < 0) {
+		*value = 0xffffffff;
+		return 1;
+	}

In the kernel, don't we have to play games to dynamically map/unmap memory regions and/or map pages in a non-linear fashion since the config space is so large, and bus/device ID -> address mapping is odd? I don't see that here.

Quoted 7 lines
drivers/pci/pci_tegra.c +7 -0
+static bool tegra_pcie_port_check_link(struct tegra_pcie_port *port)
+{
+	unsigned int retries = 3;
+	unsigned long value;
+
+	value = rp_readl(port, RP_PRIV_MISC);
+	value &= ~RP_PRIV_MISC_PRSNT_MAP_EP_ABSNT;

drivers/pci/pci_tegra.c line 886

Quoted 10 lines
drivers/pci/pci_tegra.c +10 -0
+	value |= RP_PRIV_MISC_PRSNT_MAP_EP_PRSNT;
+	rp_writel(port, value, RP_PRIV_MISC);
+
+	do {
+		unsigned int timeout = 200;
+
+		do {
+			value = rp_readl(port, RP_VEND_XP);
+			if (value & RP_VEND_XP_DL_UP)
+				break;

On my board, this almost never succeeds for Jetson TK1's built-in NIC, although it works fine for the mini-PCIe slot. On the other two boards I borrowed, this succeeds almost always. I'd prefer if we could get to the bottom of this before we actually apply this, although the bug is proving quite perplexing. The mainline kernel PCIe patches have the same issue.

drivers/pci/pci_tegra.c line 1097

Quoted 10 lines
drivers/pci/pci_tegra.c +9 -0
+static int process_nodes(const void *fdt, int nodes[], unsigned int count)
 
+#ifdef CONFIG_PCI_SCAN_SHOW
+		printf("PCI: Enumerating devices...\n");
+		printf("---------------------------------------\n");
+		printf("  Device        ID          Description\n");
+		printf("  ------        --          -----------\n");
+#endif
+
+		pcie->hose.last_busno = pci_hose_scan(&pcie->hose);

Shouldn't that ifdef'd block be part of pci_hose_scan()?

#51 lore raw

PATCH 15/23 pci: tegra: Add Tegra PCIe driver

Quoted 10 lines · Stephen Warren
Quoted 8 lines · Thierry Reding

From: Thierry Reding <[email protected]>

Add support for the PCIe controller found on some generations of Tegra. Tegra20 has 2 root ports with a total of 4 lanes, Tegra30 has 3 root ports with a total of 6 lanes and Tegra124 has 2 root ports with a total of 5 lanes.

drivers/pci/pci_tegra.c +0 -0
Quoted 7 lines
Quoted 5 lines

+ * Copyright (c) 2010, CompuLab, Ltd.
+ * Author: Mike Rapoport <[email protected]>
+ *
+ * Based on NVIDIA PCIe driver
+ * Copyright (c) 2008-2009, NVIDIA Corporation.

Presumably also at least (c) 2013-2014 NVIDIA too?

Yes.

Quoted 1 line

Do you have Mike's S-o-b for the initial work?

Yes, I can take it from the kernel's git log.

Quoted 9 lines
Quoted 9 lines
drivers/pci/pci_tegra.c +9 -0
+static int tegra_pcie_read_conf(struct pci_controller *hose, pci_dev_t bdf,
+				int where, u32 *value)
+{
+	struct tegra_pcie *pcie = to_tegra_pcie(hose);
+	unsigned long address;
+	int err;
+
+	err = tegra_pcie_conf_address(pcie, bdf, where, &address);
+	if (err < 0) {
Quoted 8 lines

drivers/pci/pci_tegra.c line 295

Quoted 3 lines
drivers/pci/pci_tegra.c +3 -0
+		*value = 0xffffffff;
+		return 1;
+	}

In the kernel, don't we have to play games to dynamically map/unmap memory regions and/or map pages in a non-linear fashion since the config space is so large, and bus/device ID -> address mapping is odd? I don't see that here.

We do that in the kernel to avoid having to I/O remap a full 256 MiB of memory even if only a single PCI bus is needed. Since memory is mapped 1:1 in U-Boot and we access physical memory "directly", we don't have to worry about being wasteful. The tegra_pcie_conf_offset() function computes the proper offset:

	static unsigned long tegra_pcie_conf_offset(pci_dev_t bdf, int where)
	{
		return ((where & 0xf00) << 16) | (PCI_BUS(bdf) << 16) |
		       (PCI_DEV(bdf) << 11) | (PCI_FUNC(bdf) << 8) |
		       (where & 0xfc);
	}
Quoted 15 lines
Quoted 15 lines
drivers/pci/pci_tegra.c +15 -0
+static bool tegra_pcie_port_check_link(struct tegra_pcie_port *port)
+{
+	unsigned int retries = 3;
+	unsigned long value;
+
+	value = rp_readl(port, RP_PRIV_MISC);
+	value &= ~RP_PRIV_MISC_PRSNT_MAP_EP_ABSNT;
+	value |= RP_PRIV_MISC_PRSNT_MAP_EP_PRSNT;
+	rp_writel(port, value, RP_PRIV_MISC);
+
+	do {
+		unsigned int timeout = 200;
+
+		do {
+			value = rp_readl(port, RP_VEND_XP);
Quoted 8 lines

drivers/pci/pci_tegra.c line 886

Quoted 2 lines
drivers/pci/pci_tegra.c +2 -0
+			if (value & RP_VEND_XP_DL_UP)
+				break;

On my board, this almost never succeeds for Jetson TK1's built-in NIC, although it works fine for the mini-PCIe slot. On the other two boards I borrowed, this succeeds almost always. I'd prefer if we could get to the bottom of this before we actually apply this, although the bug is proving quite perplexing. The mainline kernel PCIe patches have the same issue.

That's indeed odd. It's possible that the powergate fix that I've applied (to wait for the partition to become powered) may improve things. I'll be pushing out my latest work shortly (I don't think I'll manage to send out the whole series for review, though), so in case you get the chance you may want to test it.

Quoted 12 lines

drivers/pci/pci_tegra.c line 1097

Quoted 10 lines
drivers/pci/pci_tegra.c +9 -0
+static int process_nodes(const void *fdt, int nodes[], unsigned int count)
 
+#ifdef CONFIG_PCI_SCAN_SHOW
+		printf("PCI: Enumerating devices...\n");
+		printf("---------------------------------------\n");
+		printf("  Device        ID          Description\n");
+		printf("  ------        --          -----------\n");
+#endif
+
+		pcie->hose.last_busno = pci_hose_scan(&pcie->hose);

Shouldn't that ifdef'd block be part of pci_hose_scan()?

Every driver does it this way, but I agree that it should presumably go in the core somewhere. I'll see if I can find a good place to do it.

Thierry
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 819 bytes
Desc: not available
URL: <http://lists.denx.de/pipermail/u-boot/attachments/20140822/c0069960/attachment.pgp>

#52 lore raw

PATCH 15/23 pci: tegra: Add Tegra PCIe driver

In reply to Stephen Warren
Quoted 26 lines · Stephen Warren
Quoted 25 lines · Thierry Reding

From: Thierry Reding <[email protected]>

Add support for the PCIe controller found on some generations of Tegra. Tegra20 has 2 root ports with a total of 4 lanes, Tegra30 has 3 root ports with a total of 6 lanes and Tegra124 has 2 root ports with a total of 5 lanes.

drivers/pci/pci_tegra.c +16 -0
 
+static bool tegra_pcie_port_check_link(struct tegra_pcie_port *port)
+{
+    unsigned int retries = 3;
+    unsigned long value;
+
+    value = rp_readl(port, RP_PRIV_MISC);
+    value &= ~RP_PRIV_MISC_PRSNT_MAP_EP_ABSNT;
+    value |= RP_PRIV_MISC_PRSNT_MAP_EP_PRSNT;
+    rp_writel(port, value, RP_PRIV_MISC);
+
+    do {
+        unsigned int timeout = 200;
+
+        do {
+            value = rp_readl(port, RP_VEND_XP);
+            if (value & RP_VEND_XP_DL_UP)
Quoted 8 lines
Quoted 1 line

+ break;

On my board, this almost never succeeds for Jetson TK1's built-in NIC, although it works fine for the mini-PCIe slot. On the other two boards I borrowed, this succeeds almost always. I'd prefer if we could get to the bottom of this before we actually apply this, although the bug is proving quite perplexing. The mainline kernel PCIe patches have the same issue.

I tracked the issue down to some missing pinmux configuration for the PCIe reset lane. With that in place, both U-Boot and the mainline Linux kernel PCIe support appear to work reliably. I'll work on patches to resolve that. So, I think we can go ahead and merge these patches without issue ASAP, as soon as any review comments are addressed.

#53 lore raw

PATCH 15/23 pci: tegra: Add Tegra PCIe driver

Quoted 36 lines · Stephen Warren
Quoted 26 lines · Stephen Warren
Quoted 25 lines · Thierry Reding

From: Thierry Reding <[email protected]>

Add support for the PCIe controller found on some generations of Tegra. Tegra20 has 2 root ports with a total of 4 lanes, Tegra30 has 3 root ports with a total of 6 lanes and Tegra124 has 2 root ports with a total of 5 lanes.

drivers/pci/pci_tegra.c +16 -0
 
+static bool tegra_pcie_port_check_link(struct tegra_pcie_port *port)
+{
+    unsigned int retries = 3;
+    unsigned long value;
+
+    value = rp_readl(port, RP_PRIV_MISC);
+    value &= ~RP_PRIV_MISC_PRSNT_MAP_EP_ABSNT;
+    value |= RP_PRIV_MISC_PRSNT_MAP_EP_PRSNT;
+    rp_writel(port, value, RP_PRIV_MISC);
+
+    do {
+        unsigned int timeout = 200;
+
+        do {
+            value = rp_readl(port, RP_VEND_XP);
+            if (value & RP_VEND_XP_DL_UP)
Quoted 8 lines
Quoted 1 line

+ break;

On my board, this almost never succeeds for Jetson TK1's built-in NIC, although it works fine for the mini-PCIe slot. On the other two boards I borrowed, this succeeds almost always. I'd prefer if we could get to the bottom of this before we actually apply this, although the bug is proving quite perplexing. The mainline kernel PCIe patches have the same issue.

Quoted 3 lines

I tracked the issue down to some missing pinmux configuration for the PCIe reset lane. With that in place, both U-Boot and the mainline Linux kernel PCIe support appear to work reliably. I'll work on patches to resolve that.

Hey, that's great news.

Quoted 2 lines

So, I think we can go ahead and merge these patches without issue ASAP, as soon as any review comments are addressed.

Okay, I have v2 pretty much ready with all the review comments addressed and just need some time to write up a cover letter and send the series out.

Thierry
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 819 bytes
Desc: not available
URL: <http://lists.denx.de/pipermail/u-boot/attachments/20140822/5b846a57/attachment.pgp>

#54 lore raw

PATCH 16/23 ARM: tegra: Add Tegra20 PCIe device tree node

In reply to Thierry Reding

From: Thierry Reding <[email protected]>

Add the device tree node for the PCIe controller found on Tegra20 SoCs.

---
 arch/arm/dts/tegra20.dtsi               |  56 +++++++++++
 include/dt-bindings/clock/tegra20-car.h | 158 ++++++++++++++++++++++++++++++++
 2 files changed, 214 insertions(+)
 create mode 100644 include/dt-bindings/clock/tegra20-car.h
arch/arm/dts/tegra20.dtsi +56 -0
index a524f6eed410..ac9aeeb76582 100644
@@ -1,3 +1,4 @@
+#include <dt-bindings/clock/tegra20-car.h>
 #include <dt-bindings/gpio/tegra-gpio.h>
 #include <dt-bindings/interrupt-controller/arm-gic.h>
 
@@ -301,6 +302,61 @@
 		reg = <0x7000f400 0x200>;
 	};
 
+	pcie-controller {
+		compatible = "nvidia,tegra20-pcie";
+		device_type = "pci";
+		reg = <0x80003000 0x00000800   /* PADS registers */
+		       0x80003800 0x00000200   /* AFI registers */
+		       0x90000000 0x10000000>; /* configuration space */
+		reg-names = "pads", "afi", "cs";
+		interrupts = <GIC_SPI 98 IRQ_TYPE_LEVEL_HIGH   /* controller interrupt */
+			      GIC_SPI 99 IRQ_TYPE_LEVEL_HIGH>; /* MSI interrupt */
+		interrupt-names = "intr", "msi";
+
+		bus-range = <0x00 0xff>;
+		#address-cells = <3>;
+		#size-cells = <2>;
+
+		ranges = <0x82000000 0 0x80000000 0x80000000 0 0x00001000   /* port 0 registers */
+			  0x82000000 0 0x80001000 0x80001000 0 0x00001000   /* port 1 registers */
+			  0x81000000 0 0          0x82000000 0 0x00010000   /* downstream I/O */
+			  0x82000000 0 0xa0000000 0xa0000000 0 0x08000000   /* non-prefetchable memory */
+			  0xc2000000 0 0xa8000000 0xa8000000 0 0x18000000>; /* prefetchable memory */
+
+		clocks = <&tegra_car TEGRA20_CLK_PEX>,
+			 <&tegra_car TEGRA20_CLK_AFI>,
+			 <&tegra_car TEGRA20_CLK_PCIE_XCLK>,
+			 <&tegra_car TEGRA20_CLK_PLL_E>;
+		clock-names = "pex", "afi", "pcie_xclk", "pll_e";
+		status = "disabled";
+
+		pci at 1,0 {
+			device_type = "pci";
+			assigned-addresses = <0x82000800 0 0x80000000 0 0x1000>;
+			reg = <0x000800 0 0 0 0>;
+			status = "disabled";
+
+			#address-cells = <3>;
+			#size-cells = <2>;
+			ranges;
+
+			nvidia,num-lanes = <2>;
+		};
+
+		pci at 2,0 {
+			device_type = "pci";
+			assigned-addresses = <0x82001000 0 0x80001000 0 0x1000>;
+			reg = <0x001000 0 0 0 0>;
+			status = "disabled";
+
+			#address-cells = <3>;
+			#size-cells = <2>;
+			ranges;
+
+			nvidia,num-lanes = <2>;
+		};
+	};
+
 	usb at c5000000 {
 		compatible = "nvidia,tegra20-ehci", "usb-ehci";
 		reg = <0xc5000000 0x4000>;
include/dt-bindings/clock/tegra20-car.h new file +158 -0

158 lines not on this page · raw message

Signature · 1 line
2.0.4
#56 lore raw

PATCH 17/23 ARM: tegra: Enable PCIe on TrimSlice

In reply to Thierry Reding

From: Thierry Reding <[email protected]>

The TrimSlice has an ethernet NIC connected to the PCIe bus. Enable the PCIe controller and the network driver so that the device can boot over the network.

---
 arch/arm/dts/tegra20-trimslice.dts   | 35 +++++++++++++++++++++++++++++++++++
 board/compulab/trimslice/trimslice.c |  8 ++++++++
 include/configs/trimslice.h          | 10 ++++++++++
 3 files changed, 53 insertions(+)
arch/arm/dts/tegra20-trimslice.dts +35 -0
index ee31476c1eb8..298a0379c591 100644
@@ -42,6 +42,16 @@
 		status = "disabled";
 	};
 
+	pcie-controller {
+		status = "okay";
+		pex-clk-supply = <&pci_clk_reg>;
+		vdd-supply = <&pci_vdd_reg>;
+
+		pci at 1,0 {
+			status = "okay";
+		};
+	};
+
 	usb at c5000000 {
 		nvidia,vbus-gpio = <&gpio 170 0>; /* PV2 */
 	};
@@ -61,4 +71,29 @@
 		wp-gpios = <&gpio 122 0>; /* gpio PP2 */
 		bus-width = <4>;
 	};
+
+	regulators {
+		compatible = "simple-bus";
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		pci_clk_reg: regulator at 3 {
+			compatible = "regulator-fixed";
+			reg = <3>;
+			regulator-name = "pci_clk";
+			regulator-min-microvolt = <3300000>;
+			regulator-max-microvolt = <3300000>;
+			regulator-always-on;
+		};
+
+		pci_vdd_reg: regulator at 4 {
+			compatible = "regulator-fixed";
+			reg = <4>;
+			regulator-name = "pci_vdd";
+			regulator-min-microvolt = <1050000>;
+			regulator-max-microvolt = <1050000>;
+			regulator-always-on;
+		};
+	};
+
 };
board/compulab/trimslice/trimslice.c +8 -0
index 723293fef35a..c9da80d5eb1c 100644
@@ -13,6 +13,7 @@
 #include <asm/arch/pinmux.h>
 #include <asm/gpio.h>
 #include <i2c.h>
+#include <netdev.h>
 
 void pin_mux_usb(void)
 {
@@ -40,3 +41,10 @@ void pin_mux_mmc(void)
 	/* For CD GPIO PP1 */
 	pinmux_tristate_disable(PMUX_PINGRP_DAP3);
 }
+
+#ifdef CONFIG_PCI
+int board_eth_init(bd_t *bis)
+{
+	return pci_eth_init(bis);
+}
+#endif
include/configs/trimslice.h +10 -0
index f81cfa2e354d..285dc7a9e660 100644
@@ -68,6 +68,16 @@
 #define CONFIG_USB_HOST_ETHER
 #define CONFIG_USB_ETHER_ASIX
 
+/* PCI host support */
+#define CONFIG_PCI
+#define CONFIG_PCI_TEGRA
+#define CONFIG_PCI_PNP
+#define CONFIG_CMD_PCI
+#define CONFIG_CMD_PCI_ENUM
+
+/* PCI networking support */
+#define CONFIG_RTL8169
+
 /* General networking support */
 #define CONFIG_CMD_NET
 #define CONFIG_CMD_DHCP
Signature · 1 line
2.0.4
#57 lore raw

PATCH 17/23 ARM: tegra: Enable PCIe on TrimSlice

Quoted 7 lines · Thierry Reding

From: Thierry Reding <[email protected]>

The TrimSlice has an ethernet NIC connected to the PCIe bus. Enable the PCIe controller and the network driver so that the device can boot over the network.

arch/arm/dts/tegra20-trimslice.dts line 53

Quoted 10 lines
arch/arm/dts/tegra20-trimslice.dts +9 -0
 
+	pcie-controller {
+		status = "okay";
+		pex-clk-supply = <&pci_clk_reg>;
+		vdd-supply = <&pci_vdd_reg>;
+
+		pci at 1,0 {
+			status = "okay";
+		};
+	};

There are many more regulators here in the kernel's DT. Is that just the legacy properties in order to support the old incorrect binding?

#58 lore raw

PATCH 17/23 ARM: tegra: Enable PCIe on TrimSlice

Quoted 9 lines · Stephen Warren
Quoted 7 lines · Thierry Reding

From: Thierry Reding <[email protected]>

The TrimSlice has an ethernet NIC connected to the PCIe bus. Enable the PCIe controller and the network driver so that the device can boot over the network.

arch/arm/dts/tegra20-trimslice.dts +0 -0
Quoted 12 lines

arch/arm/dts/tegra20-trimslice.dts line 53

Quoted 9 lines
arch/arm/dts/tegra20-trimslice.dts +9 -0
+	pcie-controller {
+		status = "okay";
+		pex-clk-supply = <&pci_clk_reg>;
+		vdd-supply = <&pci_vdd_reg>;
+
+		pci at 1,0 {
+			status = "okay";
+		};
+	};

There are many more regulators here in the kernel's DT. Is that just the legacy properties in order to support the old incorrect binding?

Yes, I actually wrote these patches (or at least the bulk of it) many moons ago when the new binding didn't exist yet. I've updated all DTS files in U-Boot to be up-to-date with the latest bindings.

Thierry
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 819 bytes
Desc: not available
URL: <http://lists.denx.de/pipermail/u-boot/attachments/20140822/424285d4/attachment.pgp>

#59 lore raw

PATCH 18/23 ARM: tegra: Add Tegra30 PCIe device tree node

In reply to Thierry Reding

From: Thierry Reding <[email protected]>

Add the device tree node for the PCIe controller found on Tegra30 SoCs.

---
 arch/arm/dts/tegra30.dtsi               |  71 +++++++++
 include/dt-bindings/clock/tegra30-car.h | 265 ++++++++++++++++++++++++++++++++
 2 files changed, 336 insertions(+)
 create mode 100644 include/dt-bindings/clock/tegra30-car.h
arch/arm/dts/tegra30.dtsi +71 -0
index 7be3791fc9a6..ae0abf055a78 100644
@@ -1,3 +1,4 @@
+#include <dt-bindings/clock/tegra30-car.h>
 #include <dt-bindings/gpio/tegra-gpio.h>
 #include <dt-bindings/interrupt-controller/arm-gic.h>
 
@@ -6,6 +7,76 @@
 / {
 	compatible = "nvidia,tegra30";
 
+	pcie-controller {
+		compatible = "nvidia,tegra30-pcie";
+		device_type = "pci";
+		reg = <0x00003000 0x00000800   /* PADS registers */
+		       0x00003800 0x00000200   /* AFI registers */
+		       0x10000000 0x10000000>; /* configuration space */
+		reg-names = "pads", "afi", "cs";
+		interrupts = <GIC_SPI 98 IRQ_TYPE_LEVEL_HIGH   /* controller interrupt */
+		              GIC_SPI 99 IRQ_TYPE_LEVEL_HIGH>; /* MSI interrupt */
+		interrupt-names = "intr", "msi";
+
+		bus-range = <0x00 0xff>;
+		#address-cells = <3>;
+		#size-cells = <2>;
+
+		ranges = <0x82000000 0 0x00000000 0x00000000 0 0x00001000   /* port 0 configuration space */
+			  0x82000000 0 0x00001000 0x00001000 0 0x00001000   /* port 1 configuration space */
+			  0x82000000 0 0x00004000 0x00004000 0 0x00001000   /* port 2 configuration space */
+			  0x81000000 0 0          0x02000000 0 0x00010000   /* downstream I/O */
+			  0x82000000 0 0x20000000 0x20000000 0 0x10000000   /* non-prefetchable memory */
+			  0xc2000000 0 0x30000000 0x30000000 0 0x10000000>; /* prefetchable memory */
+
+		clocks = <&tegra_car TEGRA30_CLK_PCIE>,
+			 <&tegra_car TEGRA30_CLK_AFI>,
+			 <&tegra_car TEGRA30_CLK_PCIEX>,
+			 <&tegra_car TEGRA30_CLK_PLL_E>,
+			 <&tegra_car TEGRA30_CLK_CML0>;
+		clock-names = "pex", "afi", "pcie_xclk", "pll_e", "cml";
+		status = "disabled";
+
+		pci at 1,0 {
+			device_type = "pci";
+			assigned-addresses = <0x82000800 0 0x00000000 0 0x1000>;
+			reg = <0x000800 0 0 0 0>;
+			status = "disabled";
+
+			#address-cells = <3>;
+			#size-cells = <2>;
+			ranges;
+
+			nvidia,num-lanes = <2>;
+		};
+
+		pci at 2,0 {
+			device_type = "pci";
+			assigned-addresses = <0x82001000 0 0x00001000 0 0x1000>;
+			reg = <0x001000 0 0 0 0>;
+			status = "disabled";
+
+			#address-cells = <3>;
+			#size-cells = <2>;
+			ranges;
+
+			nvidia,num-lanes = <2>;
+		};
+
+		pci at 3,0 {
+			device_type = "pci";
+			assigned-addresses = <0x82001800 0 0x00004000 0 0x1000>;
+			reg = <0x001800 0 0 0 0>;
+			status = "disabled";
+
+			#address-cells = <3>;
+			#size-cells = <2>;
+			ranges;
+
+			nvidia,num-lanes = <2>;
+		};
+	};
+
 	tegra_car: clock {
 		compatible = "nvidia,tegra30-car";
 		reg = <0x60006000 0x1000>;
include/dt-bindings/clock/tegra30-car.h new file +265 -0

265 lines not on this page · raw message

Signature · 1 line
2.0.4
#60 lore raw

PATCH 18/23 ARM: tegra: Add Tegra30 PCIe device tree node

Quoted 6 lines · Thierry Reding

From: Thierry Reding <[email protected]>

Add the device tree node for the PCIe controller found on Tegra30 SoCs.

arch/arm/dts/tegra30.dtsi +0 -0
 

arch/arm/dts/tegra30.dtsi line 19

Quoted 10 lines
arch/arm/dts/tegra30.dtsi +10 -0
+	pcie-controller {
+		compatible = "nvidia,tegra30-pcie";
+		device_type = "pci";
+		reg = <0x00003000 0x00000800   /* PADS registers */
+		       0x00003800 0x00000200   /* AFI registers */
+		       0x10000000 0x10000000>; /* configuration space */
+		reg-names = "pads", "afi", "cs";
+		interrupts = <GIC_SPI 98 IRQ_TYPE_LEVEL_HIGH   /* controller interrupt */
+		              GIC_SPI 99 IRQ_TYPE_LEVEL_HIGH>; /* MSI interrupt */
+		interrupt-names = "intr", "msi";

There are interrupt-map and interrupt-map-mask properties here in the kernel DT. Even if they aren't used, can we add them here to keep the two consistent?

#61 lore raw

PATCH 18/23 ARM: tegra: Add Tegra30 PCIe device tree node

Quoted 7 lines · Stephen Warren
Quoted 5 lines · Thierry Reding

From: Thierry Reding <[email protected]>

Add the device tree node for the PCIe controller found on Tegra30 SoCs.

arch/arm/dts/tegra30.dtsi +0 -0
Quoted 14 lines

arch/arm/dts/tegra30.dtsi line 19

Quoted 10 lines
arch/arm/dts/tegra30.dtsi +10 -0
+	pcie-controller {
+		compatible = "nvidia,tegra30-pcie";
+		device_type = "pci";
+		reg = <0x00003000 0x00000800   /* PADS registers */
+		       0x00003800 0x00000200   /* AFI registers */
+		       0x10000000 0x10000000>; /* configuration space */
+		reg-names = "pads", "afi", "cs";
+		interrupts = <GIC_SPI 98 IRQ_TYPE_LEVEL_HIGH   /* controller interrupt */
+		              GIC_SPI 99 IRQ_TYPE_LEVEL_HIGH>; /* MSI interrupt */
+		interrupt-names = "intr", "msi";

There are interrupt-map and interrupt-map-mask properties here in the kernel DT. Even if they aren't used, can we add them here to keep the two consistent?

I had omitted them to avoid having to bring in the GIC node, but I'll do that instead so that the device trees actually start converging.

Thierry
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 819 bytes
Desc: not available
URL: <http://lists.denx.de/pipermail/u-boot/attachments/20140822/a6a0a821/attachment.pgp>

#62 lore raw

PATCH 19/23 ARM: tegra: Enable PCIe on Beaver

In reply to Thierry Reding

From: Thierry Reding <[email protected]>

The Beaver has an ethernet NIC connected to the PCIe bus. Enable the PCIe controller and the network device driver so that the device can boot over the network.

In addition the board has a mini-PCIe expansion slot.

---
 arch/arm/dts/tegra30-beaver.dts | 166 ++++++++++++++++++++++++++++++++++++++++
 board/nvidia/cardhu/cardhu.c    |  56 ++++++++++++++
 include/configs/beaver.h        |  10 +++
 3 files changed, 232 insertions(+)
arch/arm/dts/tegra30-beaver.dts +166 -0
index 85e62e9db32e..e113801fdfb4 100644
@@ -23,6 +23,27 @@
 		reg = <0x80000000 0x7ff00000>;
 	};
 
+	pcie-controller {
+		status = "okay";
+		pex-clk-supply = <&sys_3v3_pexs_reg>;
+		vdd-supply = <&ldo1_reg>;
+		avdd-supply = <&ldo2_reg>;
+
+		pci at 1,0 {
+			status = "okay";
+			nvidia,num-lanes = <2>;
+		};
+
+		pci at 2,0 {
+			nvidia,num-lanes = <2>;
+		};
+
+		pci at 3,0 {
+			status = "okay";
+			nvidia,num-lanes = <2>;
+		};
+	};
+
 	i2c at 7000c000 {
 		status = "okay";
 		clock-frequency = <100000>;
@@ -46,6 +67,110 @@
 	i2c at 7000d000 {
 		status = "okay";
 		clock-frequency = <100000>;
+
+		pmic: tps65911 at 2d {
+			compatible = "ti,tps65911";
+			reg = <0x2d>;
+
+			interrupts = <GIC_SPI 86 IRQ_TYPE_LEVEL_HIGH>;
+			#interrupt-cells = <2>;
+			interrupt-controller;
+
+			ti,system-power-controller;
+
+			#gpio-cells = <2>;
+			gpio-controller;
+
+			vcc1-supply = <&vdd_5v_in_reg>;
+			vcc2-supply = <&vdd_5v_in_reg>;
+			vcc3-supply = <&vio_reg>;
+			vcc4-supply = <&vdd_5v_in_reg>;
+			vcc5-supply = <&vdd_5v_in_reg>;
+			vcc6-supply = <&vdd2_reg>;
+			vcc7-supply = <&vdd_5v_in_reg>;
+			vccio-supply = <&vdd_5v_in_reg>;
+
+			regulators {
+				#address-cells = <1>;
+				#size-cells = <0>;
+
+				vdd1_reg: vdd1 {
+					regulator-name = "vddio_ddr_1v2";
+					regulator-min-microvolt = <1200000>;
+					regulator-max-microvolt = <1200000>;
+					regulator-always-on;
+				};
+
+				vdd2_reg: vdd2 {
+					regulator-name = "vdd_1v5_gen";
+					regulator-min-microvolt = <1500000>;
+					regulator-max-microvolt = <1500000>;
+					regulator-always-on;
+				};
+
+				vddctrl_reg: vddctrl {
+					regulator-name = "vdd_cpu,vdd_sys";
+					regulator-min-microvolt = <1000000>;
+					regulator-max-microvolt = <1000000>;
+					regulator-always-on;
+				};
+
+				vio_reg: vio {
+					regulator-name = "vdd_1v8_gen";
+					regulator-min-microvolt = <1800000>;
+					regulator-max-microvolt = <1800000>;
+					regulator-always-on;
+				};
+
+				ldo1_reg: ldo1 {
+					regulator-name = "vdd_pexa,vdd_pexb";
+					regulator-min-microvolt = <1050000>;
+					regulator-max-microvolt = <1050000>;
+				};
+
+				ldo2_reg: ldo2 {
+					regulator-name = "vdd_sata,avdd_plle";
+					regulator-min-microvolt = <1050000>;
+					regulator-max-microvolt = <1050000>;
+				};
+
+				/* LDO3 is not connected to anything */
+
+				ldo4_reg: ldo4 {
+					regulator-name = "vdd_rtc";
+					regulator-min-microvolt = <1200000>;
+					regulator-max-microvolt = <1200000>;
+					regulator-always-on;
+				};
+
+				ldo5_reg: ldo5 {
+					regulator-name = "vddio_sdmmc,avdd_vdac";
+					regulator-min-microvolt = <3300000>;
+					regulator-max-microvolt = <3300000>;
+					regulator-always-on;
+				};
+
+				ldo6_reg: ldo6 {
+					regulator-name = "avdd_dsi_csi,pwrdet_mipi";
+					regulator-min-microvolt = <1200000>;
+					regulator-max-microvolt = <1200000>;
+				};
+
+				ldo7_reg: ldo7 {
+					regulator-name = "vdd_pllm,x,u,a_p_c_s";
+					regulator-min-microvolt = <1200000>;
+					regulator-max-microvolt = <1200000>;
+					regulator-always-on;
+				};
+
+				ldo8_reg: ldo8 {
+					regulator-name = "vdd_ddr_hs";
+					regulator-min-microvolt = <1000000>;
+					regulator-max-microvolt = <1000000>;
+					regulator-always-on;
+				};
+			};
+		};
 	};
 
 	spi at 7000da00 {
@@ -81,4 +206,45 @@
 		nvidia,vbus-gpio = <&gpio 236 0>; /* PDD4 */
 		status = "okay";
 	};
+
+	regulators {
+		compatible = "simple-bus";
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		vdd_5v_in_reg: regulator at 0 {
+			compatible = "regulator-fixed";
+			reg = <0>;
+			regulator-name = "vdd_5v_in";
+			regulator-min-microvolt = <5000000>;
+			regulator-max-microvolt = <5000000>;
+			regulator-always-on;
+		};
+
+		sys_3v3_reg: regulator at 6 {
+			compatible = "regulator-fixed";
+			reg = <6>;
+			regulator-name = "sys_3v3,vdd_3v3_alw";
+			regulator-min-microvolt = <3300000>;
+			regulator-max-microvolt = <3300000>;
+			regulator-always-on;
+			regulator-boot-on;
+			enable-active-high;
+			gpio = <&pmic 6 GPIO_ACTIVE_HIGH>;
+			vin-supply = <&vdd_5v_in_reg>;
+		};
+
+		sys_3v3_pexs_reg: regulator at 7 {
+			compatible = "regulator-fixed";
+			reg = <7>;
+			regulator-name = "sys_3v3_pexs";
+			regulator-min-microvolt = <3300000>;
+			regulator-max-microvolt = <3300000>;
+			regulator-always-on;
+			regulator-boot-on;
+			enable-active-high;
+			gpio = <&gpio TEGRA_GPIO(L, 7) GPIO_ACTIVE_HIGH>;
+			vin-supply = <&sys_3v3_reg>;
+		};
+	};
 };
board/nvidia/cardhu/cardhu.c +56 -0

67 lines not on this page · raw message

include/configs/beaver.h +10 -0
index ae831127985f..bc96f6438d3c 100644
@@ -84,6 +84,16 @@
 #define CONFIG_USB_HOST_ETHER
 #define CONFIG_USB_ETHER_ASIX
 
+/* PCI host support */
+#define CONFIG_PCI
+#define CONFIG_PCI_TEGRA
+#define CONFIG_PCI_PNP
+#define CONFIG_CMD_PCI
+#define CONFIG_CMD_PCI_ENUM
+
+/* PCI networking support */
+#define CONFIG_RTL8169
+
 /* General networking support */
 #define CONFIG_CMD_NET
 #define CONFIG_CMD_DHCP
Signature · 1 line
2.0.4
#63 lore raw

PATCH 19/23 ARM: tegra: Enable PCIe on Beaver

board/nvidia/cardhu/cardhu.c void pin_mux_mmc(void) · line 119

Quoted 5 lines
board/nvidia/cardhu/cardhu.c +5 -0
+	/* TPS659110: LDO2_REG = 1.05V, ACTIVE */
+	data[0] = 0x15;
+	addr = 0x31;
+
+	err = i2c_read(PMU_I2C_ADDRESS, addr, 1, data, 1);

You sure about that read?

Me wondering why it did not work on my shiny Apalis T30.

board/nvidia/cardhu/cardhu.c void pin_mux_mmc(void) · line 123

Quoted 4 lines
board/nvidia/cardhu/cardhu.c +4 -0
+	if (err) {
+		debug("failed to set AVDD supply\n");
+		return err;
+	}

Yeah, that one just did not wana set anything (;-p).

#64 lore raw

PATCH 19/23 ARM: tegra: Enable PCIe on Beaver

Quoted 8 lines · Marcel Ziswiler

board/nvidia/cardhu/cardhu.c void pin_mux_mmc(void) · line 119

Quoted 5 lines
board/nvidia/cardhu/cardhu.c +5 -0
+	/* TPS659110: LDO2_REG = 1.05V, ACTIVE */
+	data[0] = 0x15;
+	addr = 0x31;
+
+	err = i2c_read(PMU_I2C_ADDRESS, addr, 1, data, 1);

You sure about that read?

Quoted 8 lines

Me wondering why it did not work on my shiny Apalis T30.

board/nvidia/cardhu/cardhu.c void pin_mux_mmc(void) · line 123

Quoted 4 lines
board/nvidia/cardhu/cardhu.c +4 -0
+	if (err) {
+		debug("failed to set AVDD supply\n");
+		return err;
+	}

Yeah, that one just did not wana set anything (;-p).

Hehe... this should probably be i2c_write() instead. Perhaps this is on by default on Beaver and Cardhu but not on the particular revision that Apalis T30 uses?

Can you test whether things start working if you turn that into a write instead?

Thierry
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 819 bytes
Desc: not available
URL: <http://lists.denx.de/pipermail/u-boot/attachments/20140820/85080776/attachment.pgp>

#65 lore raw

PATCH 19/23 ARM: tegra: Enable PCIe on Beaver

Quoted 3 lines · Thierry Reding

Hehe... this should probably be i2c_write() instead. Perhaps this is on by default on Beaver and Cardhu but not on the particular revision that Apalis T30 uses?

Well, we anyway use a completely different rail configuration but me just copy-pasting your read and only changing register addresses resp. values happens to just not wana be working (;-p).

Quoted 2 lines

Can you test whether things start working if you turn that into a write instead?

Sure, already did and it works like a beauty! You're the man!

U-Boot SPL 2014.10-rc1-00110-gff50ce9-dirty (Aug 20 2014 - 10:14:49)

U-Boot 2014.10-rc1-00110-gff50ce9-dirty (Aug 20 2014 - 10:14:49)

TEGRA30

Board: Toradex Apalis T30
I2C:   ready 
DRAM:  1 GiB 
MMC:   Tegra SD/MMC: 0, Tegra SD/MMC: 1, Tegra SD/MMC: 2

*** Warning - bad CRC, using default environment

tegra-pcie: PCI regions:
tegra-pcie:   I/O: 0x2000000-0x2010000
tegra-pcie:   non-prefetchable memory: 0x20000000-0x30000000
tegra-pcie:   prefetchable memory: 0x30000000-0x40000000
tegra-pcie: 4x1, 1x2 configuration
tegra-pcie: probing port 0, using 4 lanes
tegra-pcie: link 0 down, retrying
tegra-pcie: link 0 down, retrying
tegra-pcie: link 0 down, retrying
tegra-pcie: link 0 down, ignoring
tegra-pcie: probing port 1, using 1 lanes
tegra-pcie: probing port 2, using 1 lanes
In:    serial
Out:   serial
Err:   serial
Net:   PCI device RTL8169#0: unknown chip version, assuming RTL-8169
PCI device: TxConfig = 0x3F4000C0

RTL8169#0
Warning: RTL8169#0 using MAC address from net device

Hit any key to stop autoboot: 0
Apalis T30 # dhcp
BOOTP broadcast 1
DHCP client bound to address 192.168.10.5
Using RTL8169#0 device
TFTP from server 192.168.10.1; our IP address is 192.168.10.5 Filename 'uImage-apalis_t30'.
Load address: 0x80408000
Loading:
#################################################################

#################################################################

#################################################################

#################################################################

         ####################################################
         3.9 MiB/s

done
Bytes transferred = 4569784 (45bab8 hex)
Apalis T30 #

#66 lore raw

PATCH 19/23 ARM: tegra: Enable PCIe on Beaver

Quoted 5 lines · Marcel Ziswiler
Quoted 3 lines · Thierry Reding

Hehe... this should probably be i2c_write() instead. Perhaps this is on by default on Beaver and Cardhu but not on the particular revision that Apalis T30 uses?

Quoted 8 lines

Well, we anyway use a completely different rail configuration but me just copy-pasting your read and only changing register addresses resp. values happens to just not wana be working (;-p).

Quoted 2 lines

Can you test whether things start working if you turn that into a write instead?

Sure, already did and it works like a beauty! You're the man!

Pretty cool.

Quoted 45 lines

U-Boot SPL 2014.10-rc1-00110-gff50ce9-dirty (Aug 20 2014 - 10:14:49)

U-Boot 2014.10-rc1-00110-gff50ce9-dirty (Aug 20 2014 - 10:14:49)

TEGRA30

Board: Toradex Apalis T30
I2C:   ready 
DRAM:  1 GiB 
MMC:   Tegra SD/MMC: 0, Tegra SD/MMC: 1, Tegra SD/MMC: 2

*** Warning - bad CRC, using default environment

tegra-pcie: PCI regions:
tegra-pcie:   I/O: 0x2000000-0x2010000
tegra-pcie:   non-prefetchable memory: 0x20000000-0x30000000
tegra-pcie:   prefetchable memory: 0x30000000-0x40000000
tegra-pcie: 4x1, 1x2 configuration
tegra-pcie: probing port 0, using 4 lanes
tegra-pcie: link 0 down, retrying
tegra-pcie: link 0 down, retrying
tegra-pcie: link 0 down, retrying
tegra-pcie: link 0 down, ignoring
tegra-pcie: probing port 1, using 1 lanes
tegra-pcie: probing port 2, using 1 lanes
In:    serial
Out:   serial
Err:   serial
Net:   PCI device RTL8169#0: unknown chip version, assuming RTL-8169
PCI device: TxConfig = 0x3F4000C0

RTL8169#0
Warning: RTL8169#0 using MAC address from net device

Hit any key to stop autoboot: 0
Apalis T30 # dhcp
BOOTP broadcast 1
DHCP client bound to address 192.168.10.5
Using RTL8169#0 device
TFTP from server 192.168.10.1; our IP address is 192.168.10.5 Filename 'uImage-apalis_t30'.
Load address: 0x80408000
Loading:
#################################################################

#################################################################

Quoted 8 lines

#################################################################

#################################################################

         ####################################################
         3.9 MiB/s

done
Bytes transferred = 4569784 (45bab8 hex)
Apalis T30 #

Wow, 3.9 MiB/s on average. I only get around 2.0 MiB/s on all my devices. TrimSlice is the exception with around 5.0 MiB/s. I wonder where exactly that comes from. It's the oldest device so I'd expect it to be the slowest too.

Thierry
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 819 bytes
Desc: not available
URL: <http://lists.denx.de/pipermail/u-boot/attachments/20140820/4c715422/attachment.pgp>

#67 lore raw

PATCH 19/23 ARM: tegra: Enable PCIe on Beaver

Quoted 4 lines · Thierry Reding

Wow, 3.9 MiB/s on average. I only get around 2.0 MiB/s on all my devices. TrimSlice is the exception with around 5.0 MiB/s. I wonder where exactly that comes from. It's the oldest device so I'd expect it to be the slowest too.

That's now with Marek's i210 patches plus some more fiddling on my side. Not perfect yet but already pretty blazing fast, sorry about that (;-p).

BTW: You do have our hw laying around as well don't you. So no need to play with this slow Jetson TK1 stuff any longer (;-p).

Apalis T30 # dhcp
e1000: e1000#0: ERROR: Hardware Initialization Failed BOOTP broadcast 1
DHCP client bound to address 192.168.10.5
Using e1000#0 device
TFTP from server 192.168.10.1; our IP address is 192.168.10.5 Filename 'uImage-apalis_t30'.
Load address: 0x80408000
Loading:
#################################################################

#################################################################

#################################################################

#################################################################

         ####################################################
         7.3 MiB/s

done
Bytes transferred = 4569784 (45bab8 hex)

#68 lore raw

PATCH 19/23 ARM: tegra: Enable PCIe on Beaver

In reply to Thierry Reding
Quoted 9 lines · Thierry Reding

From: Thierry Reding <[email protected]>

The Beaver has an ethernet NIC connected to the PCIe bus. Enable the PCIe controller and the network device driver so that the device can boot over the network.

In addition the board has a mini-PCIe expansion slot.

arch/arm/dts/tegra30-beaver.dts line 30

Quoted 6 lines
arch/arm/dts/tegra30-beaver.dts +5 -0
 
+	pcie-controller {
+		status = "okay";
+		pex-clk-supply = <&sys_3v3_pexs_reg>;
+		vdd-supply = <&ldo1_reg>;
+		avdd-supply = <&ldo2_reg>;

Just like TrimSlice, there are more regulator references in the kernel DT.

The same comment applies to the next patch (i.e. the Cardhu DT patch)

Quoted 1 line
arch/arm/dts/tegra30-beaver.dts +1 -0
+	regulators {

...

Quoted 1 line
arch/arm/dts/tegra30-beaver.dts +1 -0
+		vdd_5v_in_reg: regulator at 0 {

...

Quoted 1 line
arch/arm/dts/tegra30-beaver.dts +1 -0
+		sys_3v3_reg: regulator at 6 {

...

arch/arm/dts/tegra30-beaver.dts line 237

Quoted 1 line
arch/arm/dts/tegra30-beaver.dts +1 -0
+		sys_3v3_pexs_reg: regulator at 7 {

This only adds 3 of the regulators that are in the kernel DT. Can we just add the whole regulators node so the two are consistent?

board/nvidia/cardhu/cardhu.c

Quoted 1 line
board/nvidia/cardhu/cardhu.c +0 -0

The commit description says Beaver...

I guess this should be part of the next patch, and the two swapped?

#69 lore raw

PATCH 19/23 ARM: tegra: Enable PCIe on Beaver

Quoted 19 lines · Stephen Warren
Quoted 9 lines · Thierry Reding

From: Thierry Reding <[email protected]>

The Beaver has an ethernet NIC connected to the PCIe bus. Enable the PCIe controller and the network device driver so that the device can boot over the network.

In addition the board has a mini-PCIe expansion slot.

arch/arm/dts/tegra30-beaver.dts line 30

Quoted 6 lines
arch/arm/dts/tegra30-beaver.dts +5 -0
 
+	pcie-controller {
+		status = "okay";
+		pex-clk-supply = <&sys_3v3_pexs_reg>;
+		vdd-supply = <&ldo1_reg>;
+		avdd-supply = <&ldo2_reg>;

Just like TrimSlice, there are more regulator references in the kernel DT.

Quoted 1 line

The same comment applies to the next patch (i.e. the Cardhu DT patch)

Done. I also added the unit address to the PCIe controller node name for consistency.

Quoted 10 lines
Quoted 1 line
arch/arm/dts/tegra30-beaver.dts +1 -0
+	regulators {

...

Quoted 1 line
arch/arm/dts/tegra30-beaver.dts +1 -0
+		vdd_5v_in_reg: regulator at 0 {

...

Quoted 1 line
arch/arm/dts/tegra30-beaver.dts +1 -0
+		sys_3v3_reg: regulator at 6 {

...

arch/arm/dts/tegra30-beaver.dts line 237

Quoted 1 line
arch/arm/dts/tegra30-beaver.dts +1 -0
+		sys_3v3_pexs_reg: regulator at 7 {

This only adds 3 of the regulators that are in the kernel DT. Can we just add the whole regulators node so the two are consistent?

Done.

Quoted 5 lines

board/nvidia/cardhu/cardhu.c

Quoted 1 line
board/nvidia/cardhu/cardhu.c +0 -0

The commit description says Beaver...

I guess this should be part of the next patch, and the two swapped?

Done.

Thanks,
Thierry
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 819 bytes
Desc: not available
URL: <http://lists.denx.de/pipermail/u-boot/attachments/20140822/2d255c26/attachment.pgp>

#70 lore raw

PATCH 20/23 ARM: tegra: Enable PCIe on Cardhu

In reply to Thierry Reding

From: Thierry Reding <[email protected]>

The PCIe bus on Cardhu is routed to the dock connector. An ethernet NIC is available on the dock over the PCIe bus. Enable the PCIe controller and the network device driver so that the device can boot over the network.

---
 arch/arm/dts/tegra30-cardhu.dts | 357 ++++++++++++++++++++++++++++++++++++++++
 include/configs/cardhu.h        |  10 ++
 2 files changed, 367 insertions(+)
arch/arm/dts/tegra30-cardhu.dts +357 -0
index ea2cf76ff3a8..8d3e85ab263b 100644
@@ -22,6 +22,26 @@
 		reg = <0x80000000 0x40000000>;
 	};
 
+	pcie-controller {
+		status = "okay";
+		pex-clk-supply = <&pex_hvdd_3v3_reg>;
+		vdd-supply = <&ldo1_reg>;
+		avdd-supply = <&ldo2_reg>;
+
+		pci at 1,0 {
+			nvidia,num-lanes = <4>;
+		};
+
+		pci at 2,0 {
+			nvidia,num-lanes = <1>;
+		};
+
+		pci at 3,0 {
+			status = "okay";
+			nvidia,num-lanes = <1>;
+		};
+	};
+
 	i2c at 7000c000 {
 		status = "okay";
 		clock-frequency = <100000>;
@@ -45,6 +65,107 @@
 	i2c at 7000d000 {
 		status = "okay";
 		clock-frequency = <100000>;
+
+		pmic: tps65911 at 2d {
+			compatible = "ti,tps65911";
+			reg = <0x2d>;
+
+			interrupts = <GIC_SPI 86 IRQ_TYPE_LEVEL_HIGH>;
+			#interrupt-cells = <2>;
+			interrupt-controller;
+
+			ti,system-power-controller;
+
+			#gpio-cells = <2>;
+			gpio-controller;
+
+			vcc1-supply = <&vdd_ac_bat_reg>;
+			vcc2-supply = <&vdd_ac_bat_reg>;
+			vcc3-supply = <&vio_reg>;
+			vcc4-supply = <&vdd_5v0_reg>;
+			vcc5-supply = <&vdd_ac_bat_reg>;
+			vcc6-supply = <&vdd2_reg>;
+			vcc7-supply = <&vdd_ac_bat_reg>;
+			vccio-supply = <&vdd_ac_bat_reg>;
+
+			regulators {
+				vdd1_reg: vdd1 {
+					regulator-name = "vddio_ddr_1v2";
+					regulator-min-microvolt = <1200000>;
+					regulator-max-microvolt = <1200000>;
+					regulator-always-on;
+				};
+
+				vdd2_reg: vdd2 {
+					regulator-name = "vdd_1v5_gen";
+					regulator-min-microvolt = <1500000>;
+					regulator-max-microvolt = <1500000>;
+					regulator-always-on;
+				};
+
+				vddctrl_reg: vddctrl {
+					regulator-name = "vdd_cpu,vdd_sys";
+					regulator-min-microvolt = <1000000>;
+					regulator-max-microvolt = <1000000>;
+					regulator-always-on;
+				};
+
+				vio_reg: vio {
+					regulator-name = "vdd_1v8_gen";
+					regulator-min-microvolt = <1800000>;
+					regulator-max-microvolt = <1800000>;
+					regulator-always-on;
+				};
+
+				ldo1_reg: ldo1 {
+					regulator-name = "vdd_pexa,vdd_pexb";
+					regulator-min-microvolt = <1050000>;
+					regulator-max-microvolt = <1050000>;
+				};
+
+				ldo2_reg: ldo2 {
+					regulator-name = "vdd_sata,avdd_plle";
+					regulator-min-microvolt = <1050000>;
+					regulator-max-microvolt = <1050000>;
+				};
+
+				/* LDO3 is not connected to anything */
+
+				ldo4_reg: ldo4 {
+					regulator-name = "vdd_rtc";
+					regulator-min-microvolt = <1200000>;
+					regulator-max-microvolt = <1200000>;
+					regulator-always-on;
+				};
+
+				ldo5_reg: ldo5 {
+					regulator-name = "vddio_sdmmc,avdd_vdac";
+					regulator-min-microvolt = <3300000>;
+					regulator-max-microvolt = <3300000>;
+					regulator-always-on;
+				};
+
+				ldo6_reg: ldo6 {
+					regulator-name = "avdd_dsi_csi,pwrdet_mipi";
+					regulator-min-microvolt = <1200000>;
+					regulator-max-microvolt = <1200000>;
+				};
+
+				ldo7_reg: ldo7 {
+					regulator-name = "vdd_pllm,x,u,a_p_c_s";
+					regulator-min-microvolt = <1200000>;
+					regulator-max-microvolt = <1200000>;
+					regulator-always-on;
+				};
+
+				ldo8_reg: ldo8 {
+					regulator-name = "vdd_ddr_hs";
+					regulator-min-microvolt = <1000000>;
+					regulator-max-microvolt = <1000000>;
+					regulator-always-on;
+				};
+			};
+		};
 	};
 
 	spi at 7000da00 {
@@ -69,4 +190,240 @@
 		nvidia,vbus-gpio = <&gpio 236 0>;	/* PDD4 */
 		status = "okay";
 	};
+
+	regulators {
+		compatible = "simple-bus";
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		vdd_ac_bat_reg: regulator at 0 {
+			compatible = "regulator-fixed";
+			reg = <0>;
+			regulator-name = "vdd_ac_bat";
+			regulator-min-microvolt = <5000000>;
+			regulator-max-microvolt = <5000000>;
+			regulator-always-on;
+		};
+
+		cam_1v8_reg: regulator at 1 {
+			compatible = "regulator-fixed";
+			reg = <1>;
+			regulator-name = "cam_1v8";
+			regulator-min-microvolt = <1800000>;
+			regulator-max-microvolt = <1800000>;
+			enable-active-high;
+			gpio = <&gpio TEGRA_GPIO(BB, 4) GPIO_ACTIVE_HIGH>;
+			vin-supply = <&vio_reg>;
+		};
+
+		cp_5v_reg: regulator at 2 {
+			compatible = "regulator-fixed";
+			reg = <2>;
+			regulator-name = "cp_5v";
+			regulator-min-microvolt = <5000000>;
+			regulator-max-microvolt = <5000000>;
+			regulator-boot-on;
+			regulator-always-on;
+			enable-active-high;
+			gpio = <&pmic 0 GPIO_ACTIVE_HIGH>;
+		};
+
+		emmc_3v3_reg: regulator at 3 {
+			compatible = "regulator-fixed";
+			reg = <3>;
+			regulator-name = "emmc_3v3";
+			regulator-min-microvolt = <3300000>;
+			regulator-max-microvolt = <3300000>;
+			regulator-always-on;
+			regulator-boot-on;
+			enable-active-high;
+			gpio = <&gpio TEGRA_GPIO(D, 1) GPIO_ACTIVE_HIGH>;
+			vin-supply = <&sys_3v3_reg>;
+		};
+
+		modem_3v3_reg: regulator at 4 {
+			compatible = "regulator-fixed";
+			reg = <4>;
+			regulator-name = "modem_3v3";
+			regulator-min-microvolt = <3300000>;
+			regulator-max-microvolt = <3300000>;
+			enable-active-high;
+			gpio = <&gpio TEGRA_GPIO(D, 6) GPIO_ACTIVE_HIGH>;
+		};
+
+		pex_hvdd_3v3_reg: regulator at 5 {
+			compatible = "regulator-fixed";
+			reg = <5>;
+			regulator-name = "pex_hvdd_3v3";
+			regulator-min-microvolt = <3300000>;
+			regulator-max-microvolt = <3300000>;
+			enable-active-high;
+			gpio = <&gpio TEGRA_GPIO(L, 7) GPIO_ACTIVE_HIGH>;
+			vin-supply = <&sys_3v3_reg>;
+		};
+
+		vdd_cam1_ldo_reg: regulator at 6 {
+			compatible = "regulator-fixed";
+			reg = <6>;
+			regulator-name = "vdd_cam1_ldo";
+			regulator-min-microvolt = <2800000>;
+			regulator-max-microvolt = <2800000>;
+			enable-active-high;
+			gpio = <&gpio TEGRA_GPIO(R, 6) GPIO_ACTIVE_HIGH>;
+			vin-supply = <&sys_3v3_reg>;
+		};
+
+		vdd_cam2_ldo_reg: regulator at 7 {
+			compatible = "regulator-fixed";
+			reg = <7>;
+			regulator-name = "vdd_cam2_ldo";
+			regulator-min-microvolt = <2800000>;
+			regulator-max-microvolt = <2800000>;
+			enable-active-high;
+			gpio = <&gpio TEGRA_GPIO(R, 7) GPIO_ACTIVE_HIGH>;
+			vin-supply = <&sys_3v3_reg>;
+		};
+
+		vdd_cam3_ldo_reg: regulator at 8 {
+			compatible = "regulator-fixed";
+			reg = <8>;
+			regulator-name = "vdd_cam3_ldo";
+			regulator-min-microvolt = <3300000>;
+			regulator-max-microvolt = <3300000>;
+			enable-active-high;
+			gpio = <&gpio TEGRA_GPIO(S, 0) GPIO_ACTIVE_HIGH>;
+			vin-supply = <&sys_3v3_reg>;
+		};
+
+		vdd_com_reg: regulator at 9 {
+			compatible = "regulator-fixed";
+			reg = <9>;
+			regulator-name = "vdd_com";
+			regulator-min-microvolt = <3300000>;
+			regulator-max-microvolt = <3300000>;
+			regulator-always-on;
+			regulator-boot-on;
+			enable-active-high;
+			gpio = <&gpio TEGRA_GPIO(D, 0) GPIO_ACTIVE_HIGH>;
+			vin-supply = <&sys_3v3_reg>;
+		};
+
+		vdd_fuse_3v3_reg: regulator at 10 {
+			compatible = "regulator-fixed";
+			reg = <10>;
+			regulator-name = "vdd_fuse_3v3";
+			regulator-min-microvolt = <3300000>;
+			regulator-max-microvolt = <3300000>;
+			enable-active-high;
+			gpio = <&gpio TEGRA_GPIO(L, 6) GPIO_ACTIVE_HIGH>;
+			vin-supply = <&sys_3v3_reg>;
+		};
+
+		vdd_pnl1_reg: regulator at 11 {
+			compatible = "regulator-fixed";
+			reg = <11>;
+			regulator-name = "vdd_pnl1";
+			regulator-min-microvolt = <3300000>;
+			regulator-max-microvolt = <3300000>;
+			regulator-always-on;
+			regulator-boot-on;
+			enable-active-high;
+			gpio = <&gpio TEGRA_GPIO(L, 4) GPIO_ACTIVE_HIGH>;
+			vin-supply = <&sys_3v3_reg>;
+		};
+
+		vdd_vid_reg: regulator at 12 {
+			compatible = "regulator-fixed";
+			reg = <12>;
+			regulator-name = "vddio_vid";
+			regulator-min-microvolt = <5000000>;
+			regulator-max-microvolt = <5000000>;
+			enable-active-high;
+			gpio = <&gpio TEGRA_GPIO(T, 0) GPIO_ACTIVE_HIGH>;
+			gpio-open-drain;
+			vin-supply = <&vdd_5v0_reg>;
+		};
+
+		ddr_reg: regulator at 100 {
+			compatible = "regulator-fixed";
+			regulator-name = "ddr";
+			reg = <100>;
+			regulator-min-microvolt = <1500000>;
+			regulator-max-microvolt = <1500000>;
+			regulator-always-on;
+			regulator-boot-on;
+			enable-active-high;
+			gpio = <&pmic 7 GPIO_ACTIVE_HIGH>;
+		};
+
+		sys_3v3_reg: regulator at 101 {
+			compatible = "regulator-fixed";
+			reg = <101>;
+			regulator-name = "sys_3v3";
+			regulator-min-microvolt = <3300000>;
+			regulator-max-microvolt = <3300000>;
+			regulator-always-on;
+			regulator-boot-on;
+			enable-active-high;
+			gpio = <&pmic 6 GPIO_ACTIVE_HIGH>;
+		};
+
+		usb1_vbus_reg: regulator at 102 {
+			compatible = "regulator-fixed";
+			reg = <102>;
+			regulator-name = "usb1_vbus";
+			regulator-min-microvolt = <5000000>;
+			regulator-max-microvolt = <5000000>;
+			enable-active-high;
+			gpio = <&gpio TEGRA_GPIO(DD, 6) GPIO_ACTIVE_HIGH>;
+			gpio-open-drain;
+			vin-supply = <&vdd_5v0_reg>;
+		};
+
+		usb3_vbus_reg: regulator at 103 {
+			compatible = "regulator-fixed";
+			reg = <103>;
+			regulator-name = "usb3_vbus";
+			regulator-min-microvolt = <5000000>;
+			regulator-max-microvolt = <5000000>;
+			enable-active-high;
+			gpio = <&gpio TEGRA_GPIO(DD, 4) GPIO_ACTIVE_HIGH>;
+			gpio-open-drain;
+			vin-supply = <&vdd_5v0_reg>;
+		};
+
+		vdd_5v0_reg: regulator at 104 {
+			compatible = "regulator-fixed";
+			reg = <104>;
+			regulator-name = "5v0";
+			regulator-min-microvolt = <5000000>;
+			regulator-max-microvolt = <5000000>;
+			enable-active-high;
+			gpio = <&pmic 8 GPIO_ACTIVE_HIGH>;
+		};
+
+		vdd_bl_reg: regulator at 105 {
+			compatible = "regulator-fixed";
+			reg = <105>;
+			regulator-name = "vdd_bl";
+			regulator-min-microvolt = <5000000>;
+			regulator-max-microvolt = <5000000>;
+			regulator-always-on;
+			regulator-boot-on;
+			enable-active-high;
+			gpio = <&gpio TEGRA_GPIO(DD, 2) GPIO_ACTIVE_HIGH>;
+		};
+
+		vdd_bl2_reg: regulator at 106 {
+			compatible = "regulator-fixed";
+			reg = <106>;
+			regulator-name = "vdd_bl2";
+			regulator-min-microvolt = <5000000>;
+			regulator-max-microvolt = <5000000>;
+			regulator-always-on;
+			regulator-boot-on;
+			enable-active-high;
+			gpio = <&gpio TEGRA_GPIO(DD, 0) GPIO_ACTIVE_HIGH>;
+		};
+	};
 };
include/configs/cardhu.h +10 -0
index 59f429cf5784..f5f4a860f6a9 100644
@@ -88,6 +88,16 @@
 #define CONFIG_USB_HOST_ETHER
 #define CONFIG_USB_ETHER_ASIX
 
+/* PCI host support */
+#define CONFIG_PCI
+#define CONFIG_PCI_TEGRA
+#define CONFIG_PCI_PNP
+#define CONFIG_CMD_PCI
+#define CONFIG_CMD_PCI_ENUM
+
+/* PCI networking support */
+#define CONFIG_RTL8169
+
 /* General networking support */
 #define CONFIG_CMD_NET
 #define CONFIG_CMD_DHCP
Signature · 1 line
2.0.4
#71 lore raw

PATCH 21/23 ARM: tegra: Add GIC for Tegra124

In reply to Thierry Reding

From: Thierry Reding <[email protected]>

Add a device tree node for the GIC v2 found on the Cortex-A15 CPU complex of Tegra124. U-Boot doesn't use this but subsequent patches will add device tree nodes that reference it by phandle.

---
 arch/arm/dts/tegra124.dtsi | 13 +++++++++++++
 1 file changed, 13 insertions(+)
arch/arm/dts/tegra124.dtsi +13 -0
index d48f1a34ec3c..510fa332ef98 100644
@@ -6,6 +6,19 @@
 
 / {
 	compatible = "nvidia,tegra124";
+	interrupt-parent = <&gic>;
+
+	gic: interrupt-controller at 50041000 {
+		compatible = "arm,cortex-a15-gic";
+		#interrupt-cells = <3>;
+		interrupt-controller;
+		reg = <0x50041000 0x1000>,
+		      <0x50042000 0x2000>,
+		      <0x50044000 0x2000>,
+		      <0x50046000 0x2000>;
+		interrupts = <GIC_PPI 9
+			(GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_HIGH)>;
+	};
 
 	tegra_car: clock at 60006000 {
 		compatible = "nvidia,tegra124-car";
Signature · 1 line
2.0.4
#72 lore raw

PATCH 21/23 ARM: tegra: Add GIC for Tegra124

Quoted 5 lines · Thierry Reding

From: Thierry Reding <[email protected]>

Add a device tree node for the GIC v2 found on the Cortex-A15 CPU complex of Tegra124. U-Boot doesn't use this but subsequent patches will add device tree nodes that reference it by phandle.

Matches the kernel, so,

#73 lore raw

PATCH 22/23 ARM: tegra: Add Tegra124 PCIe device tree node

In reply to Thierry Reding

From: Thierry Reding <[email protected]>

Add the device tree node for the PCIe controller found on Tegra124 SoCs.

---
 arch/arm/dts/tegra124.dtsi               |  67 ++++++
 include/dt-bindings/clock/tegra124-car.h | 341 +++++++++++++++++++++++++++++++
 2 files changed, 408 insertions(+)
 create mode 100644 include/dt-bindings/clock/tegra124-car.h
arch/arm/dts/tegra124.dtsi +67 -0
index 510fa332ef98..d6dee96b12d6 100644
@@ -1,3 +1,4 @@
+#include <dt-bindings/clock/tegra124-car.h>
 #include <dt-bindings/gpio/tegra-gpio.h>
 #include <dt-bindings/interrupt-controller/arm-gic.h>
 #include <dt-bindings/pinctrl/pinctrl-tegra-xusb.h>
@@ -8,6 +9,72 @@
 	compatible = "nvidia,tegra124";
 	interrupt-parent = <&gic>;
 
+	pcie-controller at 01003000 {
+		compatible = "nvidia,tegra124-pcie";
+		device_type = "pci";
+		reg = <0x01003000 0x00000800   /* PADS registers */
+		       0x01003800 0x00000800   /* AFI registers */
+		       0x02000000 0x10000000>; /* configuration space */
+		reg-names = "pads", "afi", "cs";
+		interrupts = <GIC_SPI 98 IRQ_TYPE_LEVEL_HIGH>, /* controller interrupt */
+			     <GIC_SPI 99 IRQ_TYPE_LEVEL_HIGH>; /* MSI interrupt */
+		interrupt-names = "intr", "msi";
+
+		#interrupt-cells = <1>;
+		interrupt-map-mask = <0 0 0 0>;
+		interrupt-map = <0 0 0 0 &gic GIC_SPI 98 IRQ_TYPE_LEVEL_HIGH>;
+
+		bus-range = <0x00 0xff>;
+		#address-cells = <3>;
+		#size-cells = <2>;
+
+		ranges = <0x82000000 0 0x01000000 0x01000000 0 0x00001000   /* port 0 configuration space */
+			  0x82000000 0 0x01001000 0x01001000 0 0x00001000   /* port 1 configuration space */
+			  0x81000000 0 0x0        0x12000000 0 0x00010000   /* downstream I/O (64 KiB) */
+			  0x82000000 0 0x13000000 0x13000000 0 0x0d000000   /* non-prefetchable memory (208 MiB) */
+			  0xc2000000 0 0x20000000 0x20000000 0 0x20000000>; /* prefetchable memory (512 MiB) */
+
+		clocks = <&tegra_car TEGRA124_CLK_PCIE>,
+			 <&tegra_car TEGRA124_CLK_AFI>,
+			 <&tegra_car TEGRA124_CLK_PLL_E>,
+			 <&tegra_car TEGRA124_CLK_CML0>;
+		clock-names = "pex", "afi", "pll_e", "cml";
+		resets = <&tegra_car 70>,
+			 <&tegra_car 72>,
+			 <&tegra_car 74>;
+		reset-names = "pex", "afi", "pcie_x";
+		status = "disabled";
+
+		phys = <&padctl TEGRA_XUSB_PADCTL_PCIE>;
+		phy-names = "pcie";
+
+		pci at 1,0 {
+			device_type = "pci";
+			assigned-addresses = <0x82000800 0 0x01000000 0 0x1000>;
+			reg = <0x000800 0 0 0 0>;
+			status = "disabled";
+
+			#address-cells = <3>;
+			#size-cells = <2>;
+			ranges;
+
+			nvidia,num-lanes = <2>;
+		};
+
+		pci at 2,0 {
+			device_type = "pci";
+			assigned-addresses = <0x82001000 0 0x01001000 0 0x1000>;
+			reg = <0x001000 0 0 0 0>;
+			status = "disabled";
+
+			#address-cells = <3>;
+			#size-cells = <2>;
+			ranges;
+
+			nvidia,num-lanes = <1>;
+		};
+	};
+
 	gic: interrupt-controller at 50041000 {
 		compatible = "arm,cortex-a15-gic";
 		#interrupt-cells = <3>;
include/dt-bindings/clock/tegra124-car.h new file +341 -0

341 lines not on this page · raw message

Signature · 1 line
2.0.4
#75 lore raw

PATCH 23/23 ARM: tegra: Enable PCIe on Jetson TK1

In reply to Thierry Reding

From: Thierry Reding <[email protected]>

The Jetson TK1 has an ethernet NIC connected to the PCIe bus and routes the second root port to a miniPCIe slot. Enable the PCIe controller and the network driver to allow the device to boot over the network.

---
 arch/arm/dts/tegra124-jetson-tk1.dts | 347 +++++++++++++++++++++++++++++++++++
 board/nvidia/jetson-tk1/jetson-tk1.c | 218 ++++++++++++++++++++++
 include/configs/jetson-tk1.h         |  10 +
 3 files changed, 575 insertions(+)
arch/arm/dts/tegra124-jetson-tk1.dts +347 -0
index f61736f0ef0f..f594644de74e 100644
@@ -26,6 +26,26 @@
 		reg = <0x80000000 0x80000000>;
 	};
 
+	pcie-controller at 01003000 {
+		status = "okay";
+
+		avddio-pex-supply = <&vdd_1v05_run>;
+		vddio-pex-supply = <&vdd_1v05_run>;
+		avdd-pex-pll-supply = <&vdd_1v05_run>;
+		hvdd-pex-supply = <&vdd_3v3_lp0>;
+		hvdd-pex-plle-supply = <&vdd_3v3_lp0>;
+		vddio-pex-ctl-supply = <&vdd_3v3_lp0>;
+		avdd-plle-supply = <&avdd_1v05_run>;
+
+		pci at 1,0 {
+			status = "okay";
+		};
+
+		pci at 2,0 {
+			status = "okay";
+		};
+	};
+
 	i2c at 7000c000 {
 		status = "okay";
 		clock-frequency = <100000>;
@@ -46,9 +66,195 @@
 		clock-frequency = <100000>;
 	};
 
+	/* Expansion PWR_I2C_*, on-board components */
 	i2c at 7000d000 {
 		status = "okay";
 		clock-frequency = <400000>;
+
+		pmic: pmic at 40 {
+			compatible = "ams,as3722";
+			reg = <0x40>;
+			interrupts = <0 86 IRQ_TYPE_LEVEL_HIGH>;
+
+			ams,system-power-controller;
+
+			#interrupt-cells = <2>;
+			interrupt-controller;
+
+			gpio-controller;
+			#gpio-cells = <2>;
+
+			pinctrl-names = "default";
+			pinctrl-0 = <&as3722_default>;
+
+			as3722_default: pinmux {
+				gpio0 {
+					pins = "gpio0";
+					function = "gpio";
+					bias-pull-down;
+				};
+
+				gpio1_2_4_7 {
+					pins = "gpio1", "gpio2", "gpio4", "gpio7";
+					function = "gpio";
+					bias-pull-up;
+				};
+
+				gpio3_5_6 {
+					pins = "gpio3", "gpio5", "gpio6";
+					bias-high-impedance;
+				};
+			};
+
+			regulators {
+				vsup-sd2-supply = <&vdd_5v0_sys>;
+				vsup-sd3-supply = <&vdd_5v0_sys>;
+				vsup-sd4-supply = <&vdd_5v0_sys>;
+				vsup-sd5-supply = <&vdd_5v0_sys>;
+				vin-ldo0-supply = <&vdd_1v35_lp0>;
+				vin-ldo1-6-supply = <&vdd_3v3_run>;
+				vin-ldo2-5-7-supply = <&vddio_1v8>;
+				vin-ldo3-4-supply = <&vdd_3v3_sys>;
+				vin-ldo9-10-supply = <&vdd_5v0_sys>;
+				vin-ldo11-supply = <&vdd_3v3_run>;
+
+				sd0 {
+					regulator-name = "+VDD_CPU_AP";
+					regulator-min-microvolt = <700000>;
+					regulator-max-microvolt = <1400000>;
+					regulator-min-microamp = <3500000>;
+					regulator-max-microamp = <3500000>;
+					regulator-always-on;
+					regulator-boot-on;
+					ams,ext-control = <2>;
+				};
+
+				sd1 {
+					regulator-name = "+VDD_CORE";
+					regulator-min-microvolt = <700000>;
+					regulator-max-microvolt = <1350000>;
+					regulator-min-microamp = <2500000>;
+					regulator-max-microamp = <2500000>;
+					regulator-always-on;
+					regulator-boot-on;
+					ams,ext-control = <1>;
+				};
+
+				vdd_1v35_lp0: sd2 {
+					regulator-name = "+1.35V_LP0(sd2)";
+					regulator-min-microvolt = <1350000>;
+					regulator-max-microvolt = <1350000>;
+					regulator-always-on;
+					regulator-boot-on;
+				};
+
+				sd3 {
+					regulator-name = "+1.35V_LP0(sd3)";
+					regulator-min-microvolt = <1350000>;
+					regulator-max-microvolt = <1350000>;
+					regulator-always-on;
+					regulator-boot-on;
+				};
+
+				vdd_1v05_run: sd4 {
+					regulator-name = "+1.05V_RUN";
+					regulator-min-microvolt = <1050000>;
+					regulator-max-microvolt = <1050000>;
+				};
+
+				vddio_1v8: sd5 {
+					regulator-name = "+1.8V_VDDIO";
+					regulator-min-microvolt = <1800000>;
+					regulator-max-microvolt = <1800000>;
+					regulator-boot-on;
+					regulator-always-on;
+				};
+
+				vdd_gpu: sd6 {
+					regulator-name = "+VDD_GPU_AP";
+					regulator-min-microvolt = <650000>;
+					regulator-max-microvolt = <1200000>;
+					regulator-min-microamp = <3500000>;
+					regulator-max-microamp = <3500000>;
+					regulator-boot-on;
+					regulator-always-on;
+				};
+
+				avdd_1v05_run: ldo0 {
+					regulator-name = "+1.05V_RUN_AVDD";
+					regulator-min-microvolt = <1050000>;
+					regulator-max-microvolt = <1050000>;
+					regulator-boot-on;
+					regulator-always-on;
+					ams,ext-control = <1>;
+				};
+
+				ldo1 {
+					regulator-name = "+1.8V_RUN_CAM";
+					regulator-min-microvolt = <1800000>;
+					regulator-max-microvolt = <1800000>;
+				};
+
+				ldo2 {
+					regulator-name = "+1.2V_GEN_AVDD";
+					regulator-min-microvolt = <1200000>;
+					regulator-max-microvolt = <1200000>;
+					regulator-boot-on;
+					regulator-always-on;
+				};
+
+				ldo3 {
+					regulator-name = "+1.05V_LP0_VDD_RTC";
+					regulator-min-microvolt = <1000000>;
+					regulator-max-microvolt = <1000000>;
+					regulator-boot-on;
+					regulator-always-on;
+					ams,enable-tracking;
+				};
+
+				ldo4 {
+					regulator-name = "+2.8V_RUN_CAM";
+					regulator-min-microvolt = <2800000>;
+					regulator-max-microvolt = <2800000>;
+				};
+
+				ldo5 {
+					regulator-name = "+1.2V_RUN_CAM_FRONT";
+					regulator-min-microvolt = <1200000>;
+					regulator-max-microvolt = <1200000>;
+				};
+
+				vddio_sdmmc3: ldo6 {
+					regulator-name = "+VDDIO_SDMMC3";
+					regulator-min-microvolt = <1800000>;
+					regulator-max-microvolt = <3300000>;
+				};
+
+				ldo7 {
+					regulator-name = "+1.05V_RUN_CAM_REAR";
+					regulator-min-microvolt = <1050000>;
+					regulator-max-microvolt = <1050000>;
+				};
+
+				ldo9 {
+					regulator-name = "+3.3V_RUN_TOUCH";
+					regulator-min-microvolt = <2800000>;
+					regulator-max-microvolt = <2800000>;
+				};
+
+				ldo10 {
+					regulator-name = "+2.8V_RUN_CAM_AF";
+					regulator-min-microvolt = <2800000>;
+					regulator-max-microvolt = <2800000>;
+				};
+
+				ldo11 {
+					regulator-name = "+1.8V_RUN_VPP_FUSE";
+					regulator-min-microvolt = <1800000>;
+					regulator-max-microvolt = <1800000>;
+				};
+			};
+		};
 	};
 
 	i2c at 7000d100 {
@@ -114,4 +320,145 @@
 		status = "okay";
 		nvidia,vbus-gpio = <&gpio 109 0>; /* gpio PN5, USB_VBUS_EN1 */
 	};
+
+	regulators {
+		compatible = "simple-bus";
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		vdd_mux: regulator at 0 {
+			compatible = "regulator-fixed";
+			reg = <0>;
+			regulator-name = "+VDD_MUX";
+			regulator-min-microvolt = <12000000>;
+			regulator-max-microvolt = <12000000>;
+			regulator-always-on;
+			regulator-boot-on;
+		};
+
+		vdd_5v0_sys: regulator at 1 {
+			compatible = "regulator-fixed";
+			reg = <1>;
+			regulator-name = "+5V_SYS";
+			regulator-min-microvolt = <5000000>;
+			regulator-max-microvolt = <5000000>;
+			regulator-always-on;
+			regulator-boot-on;
+			vin-supply = <&vdd_mux>;
+		};
+
+		vdd_3v3_sys: regulator at 2 {
+			compatible = "regulator-fixed";
+			reg = <2>;
+			regulator-name = "+3.3V_SYS";
+			regulator-min-microvolt = <3300000>;
+			regulator-max-microvolt = <3300000>;
+			regulator-always-on;
+			regulator-boot-on;
+			vin-supply = <&vdd_mux>;
+		};
+
+		vdd_3v3_run: regulator at 3 {
+			compatible = "regulator-fixed";
+			reg = <3>;
+			regulator-name = "+3.3V_RUN";
+			regulator-min-microvolt = <3300000>;
+			regulator-max-microvolt = <3300000>;
+			regulator-always-on;
+			regulator-boot-on;
+			gpio = <&pmic 1 GPIO_ACTIVE_HIGH>;
+			enable-active-high;
+			vin-supply = <&vdd_3v3_sys>;
+		};
+
+		vdd_3v3_hdmi: regulator at 4 {
+			compatible = "regulator-fixed";
+			reg = <4>;
+			regulator-name = "+3.3V_AVDD_HDMI_AP_GATED";
+			regulator-min-microvolt = <3300000>;
+			regulator-max-microvolt = <3300000>;
+			vin-supply = <&vdd_3v3_run>;
+		};
+
+		vdd_usb1_vbus: regulator at 7 {
+			compatible = "regulator-fixed";
+			reg = <7>;
+			regulator-name = "+USB0_VBUS_SW";
+			regulator-min-microvolt = <5000000>;
+			regulator-max-microvolt = <5000000>;
+			gpio = <&gpio TEGRA_GPIO(N, 4) GPIO_ACTIVE_HIGH>;
+			enable-active-high;
+			gpio-open-drain;
+			vin-supply = <&vdd_5v0_sys>;
+		};
+
+		vdd_usb3_vbus: regulator at 8 {
+			compatible = "regulator-fixed";
+			reg = <8>;
+			regulator-name = "+5V_USB_HS";
+			regulator-min-microvolt = <5000000>;
+			regulator-max-microvolt = <5000000>;
+			gpio = <&gpio TEGRA_GPIO(N, 5) GPIO_ACTIVE_HIGH>;
+			enable-active-high;
+			gpio-open-drain;
+			vin-supply = <&vdd_5v0_sys>;
+		};
+
+		vdd_3v3_lp0: regulator at 10 {
+			compatible = "regulator-fixed";
+			reg = <10>;
+			regulator-name = "+3.3V_LP0";
+			regulator-min-microvolt = <3300000>;
+			regulator-max-microvolt = <3300000>;
+			regulator-always-on;
+			regulator-boot-on;
+			gpio = <&pmic 2 GPIO_ACTIVE_HIGH>;
+			enable-active-high;
+			vin-supply = <&vdd_3v3_sys>;
+		};
+
+		vdd_hdmi_pll: regulator at 11 {
+			compatible = "regulator-fixed";
+			reg = <11>;
+			regulator-name = "+1.05V_RUN_AVDD_HDMI_PLL";
+			regulator-min-microvolt = <1050000>;
+			regulator-max-microvolt = <1050000>;
+			gpio = <&gpio TEGRA_GPIO(H, 7) GPIO_ACTIVE_LOW>;
+			vin-supply = <&vdd_1v05_run>;
+		};
+
+		vdd_5v0_hdmi: regulator at 12 {
+			compatible = "regulator-fixed";
+			reg = <12>;
+			regulator-name = "+5V_HDMI_CON";
+			regulator-min-microvolt = <5000000>;
+			regulator-max-microvolt = <5000000>;
+			gpio = <&gpio TEGRA_GPIO(K, 6) GPIO_ACTIVE_HIGH>;
+			enable-active-high;
+			vin-supply = <&vdd_5v0_sys>;
+		};
+
+		/* Molex power connector */
+		vdd_5v0_sata: regulator at 13 {
+			compatible = "regulator-fixed";
+			reg = <13>;
+			regulator-name = "+5V_SATA";
+			regulator-min-microvolt = <5000000>;
+			regulator-max-microvolt = <5000000>;
+			gpio = <&gpio TEGRA_GPIO(EE, 2) GPIO_ACTIVE_HIGH>;
+			enable-active-high;
+			vin-supply = <&vdd_5v0_sys>;
+		};
+
+		vdd_12v0_sata: regulator at 14 {
+			compatible = "regulator-fixed";
+			reg = <14>;
+			regulator-name = "+12V_SATA";
+			regulator-min-microvolt = <12000000>;
+			regulator-max-microvolt = <12000000>;
+			gpio = <&gpio TEGRA_GPIO(EE, 2) GPIO_ACTIVE_HIGH>;
+			enable-active-high;
+			vin-supply = <&vdd_mux>;
+		};
+	};
 };
board/nvidia/jetson-tk1/jetson-tk1.c +218 -0

230 lines not on this page · raw message

include/configs/jetson-tk1.h +10 -0
index 0b9e5b699fa6..b0393509681c 100644
@@ -71,6 +71,16 @@
 #define CONFIG_USB_HOST_ETHER
 #define CONFIG_USB_ETHER_ASIX
 
+/* PCI host support */
+#define CONFIG_PCI
+#define CONFIG_PCI_TEGRA
+#define CONFIG_PCI_PNP
+#define CONFIG_CMD_PCI
+#define CONFIG_CMD_PCI_ENUM
+
+/* PCI networking support */
+#define CONFIG_RTL8169
+
 /* General networking support */
 #define CONFIG_CMD_NET
 #define CONFIG_CMD_DHCP
Signature · 1 line
2.0.4
#76 lore raw

PATCH 23/23 ARM: tegra: Enable PCIe on Jetson TK1

Hi Thierry,

Quoted 7 lines · Thierry Reding

From: Thierry Reding <[email protected]>

The Jetson TK1 has an ethernet NIC connected to the PCIe bus and routes the second root port to a miniPCIe slot. Enable the PCIe controller and the network driver to allow the device to boot over the network.

Cool, I'll have to give this a try! Shouldn't the as3722 code be in its own driver?

Regards,
Simon

#77 lore raw

PATCH 23/23 ARM: tegra: Enable PCIe on Jetson TK1

Quoted 5 lines · Simon Glass

Hi Thierry,

Quoted 2 lines · Thierry Reding

From: Thierry Reding <[email protected]>

Quoted 8 lines
Quoted 5 lines

The Jetson TK1 has an ethernet NIC connected to the PCIe bus and routes the second root port to a miniPCIe slot. Enable the PCIe controller and the network driver to allow the device to boot over the network.

Cool, I'll have to give this a try! Shouldn't the as3722 code be in its own driver?

I suppose it could. My intention was to move it out at some point when we needed it for another device. But if you prefer I can move it out in this series already.

Thierry
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 819 bytes
Desc: not available
URL: <http://lists.denx.de/pipermail/u-boot/attachments/20140819/acd9bd3f/attachment.pgp>

#78 lore raw

PATCH 23/23 ARM: tegra: Enable PCIe on Jetson TK1

Hi Thierry,

Quoted 10 lines · Thierry Reding
Quoted 9 lines · Simon Glass

Hi Thierry,

Quoted 6 lines · Thierry Reding

From: Thierry Reding <[email protected]>

The Jetson TK1 has an ethernet NIC connected to the PCIe bus and routes the second root port to a miniPCIe slot. Enable the PCIe controller and the network driver to allow the device to boot over the network.

Quoted 8 lines
Quoted 4 lines
Quoted 1 line

Cool, I'll have to give this a try! Shouldn't the as3722 code be in its own driver?

I suppose it could. My intention was to move it out at some point when we needed it for another device. But if you prefer I can move it out in this series already.

Yes I think we should avoid putting driver code in board files.

BTW there is:

  i2c_bus = i2c_get_bus_num_fdt(parent);

where parent is the fdt node of the parent. So you don't have to hard-code the bus number. See tpm_decode_config() for an example.

Regards,
Simon

#79 lore raw

PATCH 23/23 ARM: tegra: Enable PCIe on Jetson TK1

In reply to Thierry Reding
Quoted 11 lines · Thierry Reding

From: Thierry Reding <[email protected]>

The Jetson TK1 has an ethernet NIC connected to the PCIe bus and routes the second root port to a miniPCIe slot. Enable the PCIe controller and

arch/arm/dts/tegra124-jetson-tk1.dts +3 -0
 
+	regulators {
 
+		/* Molex power connector */
+		vdd_5v0_sata: regulator at 13 {

...

arch/arm/dts/tegra124-jetson-tk1.dts line 453

Quoted 1 line
arch/arm/dts/tegra124-jetson-tk1.dts +1 -0
+		vdd_12v0_sata: regulator at 14 {

Those two aren't in the kernel DT yet. I'll assume they match what's been proposed for the SATA patches:-)

board/nvidia/jetson-tk1/jetson-tk1.c

Quoted 1 line
board/nvidia/jetson-tk1/jetson-tk1.c +0 -0

A lot of the AS3722 code here duplicates what's in board/nvidia/venice2/as3722_init.[ch]. It'd be good to put it all in one place. Personally I'd be OK with putting it into the existing Venice2 code, but I suppose as Simon mentioned, a "real" AS3722 driver in drivers/power/pmic would be a good idea.

#80 lore raw

PATCH 23/23 ARM: tegra: Enable PCIe on Jetson TK1

Quoted 18 lines · Stephen Warren
Quoted 11 lines · Thierry Reding

From: Thierry Reding <[email protected]>

The Jetson TK1 has an ethernet NIC connected to the PCIe bus and routes the second root port to a miniPCIe slot. Enable the PCIe controller and

arch/arm/dts/tegra124-jetson-tk1.dts +3 -0
 
+	regulators {
 
+		/* Molex power connector */
+		vdd_5v0_sata: regulator at 13 {

...

arch/arm/dts/tegra124-jetson-tk1.dts line 453

Quoted 1 line
arch/arm/dts/tegra124-jetson-tk1.dts +1 -0
+		vdd_12v0_sata: regulator at 14 {

Those two aren't in the kernel DT yet. I'll assume they match what's been proposed for the SATA patches:-)

Quoted 7 lines

board/nvidia/jetson-tk1/jetson-tk1.c

Quoted 1 line
board/nvidia/jetson-tk1/jetson-tk1.c +0 -0

A lot of the AS3722 code here duplicates what's in board/nvidia/venice2/as3722_init.[ch]. It'd be good to put it all in one place. Personally I'd be OK with putting it into the existing Venice2 code, but I suppose as Simon mentioned, a "real" AS3722 driver in drivers/power/pmic would be a good idea.

Unfortunately turning this into a real driver for AS3722 makes it impossible (or at least too difficult) to unify with the code in venice2/as3722_init.ch. The issue is that the new driver relies on infrastructure (I2C, FDT) that's not available in SPL (where this code is run). I tried extending the SPL with I2C and power drivers support so that I could use the driver here as well, but that keeps failing at various points, so I preferred having a proper driver for full U-Boot and kept the low-level code for CPU power rail setup as is.

Note that I haven't turned the AS3722 support into a "PMIC" driver, because the framework for that seems to be unusable. It doesn't seem to abstract away driver-specifics at all but rather provides a way to access registers in a uniform way (sort of what regmap does in Linux). Using that framework would therefore require knowledge about the exact register accesses within drivers and therefore wouldn't be an improvement over the current situation.

Thierry
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 819 bytes
Desc: not available
URL: <http://lists.denx.de/pipermail/u-boot/attachments/20140822/bcfa57e6/attachment.pgp>

#81 lore raw

PATCH 23/23 ARM: tegra: Enable PCIe on Jetson TK1

Quoted 27 lines · Thierry Reding
Quoted 18 lines · Stephen Warren
Quoted 11 lines · Thierry Reding

From: Thierry Reding <[email protected]>

The Jetson TK1 has an ethernet NIC connected to the PCIe bus and routes the second root port to a miniPCIe slot. Enable the PCIe controller and

arch/arm/dts/tegra124-jetson-tk1.dts +3 -0
 
+	regulators {
 
+		/* Molex power connector */
+		vdd_5v0_sata: regulator at 13 {

...

arch/arm/dts/tegra124-jetson-tk1.dts line 453

Quoted 1 line
arch/arm/dts/tegra124-jetson-tk1.dts +1 -0
+		vdd_12v0_sata: regulator at 14 {

Those two aren't in the kernel DT yet. I'll assume they match what's been proposed for the SATA patches:-)

Quoted 7 lines

board/nvidia/jetson-tk1/jetson-tk1.c

Quoted 1 line
board/nvidia/jetson-tk1/jetson-tk1.c +0 -0

A lot of the AS3722 code here duplicates what's in board/nvidia/venice2/as3722_init.[ch]. It'd be good to put it all in one place. Personally I'd be OK with putting it into the existing Venice2 code, but I suppose as Simon mentioned, a "real" AS3722 driver in drivers/power/pmic would be a good idea.

Quoted 8 lines

Unfortunately turning this into a real driver for AS3722 makes it impossible (or at least too difficult) to unify with the code in venice2/as3722_init.ch. The issue is that the new driver relies on infrastructure (I2C, FDT) that's not available in SPL (where this code is run). I tried extending the SPL with I2C and power drivers support so that I could use the driver here as well, but that keeps failing at various points, so I preferred having a proper driver for full U-Boot and kept the low-level code for CPU power rail setup as is.

Ah yes. That makes sense.

Quoted 10 lines

Note that I haven't turned the AS3722 support into a "PMIC" driver, because the framework for that seems to be unusable. It doesn't seem to abstract away driver-specifics at all but rather provides a way to access registers in a uniform way (sort of what regmap does in Linux). Using that framework would therefore require knowledge about the exact register accesses within drivers and therefore wouldn't be an improvement over the current situation.

Thierry

#82 lore raw

PATCH 23/23 ARM: tegra: Enable PCIe on Jetson TK1

In reply to Thierry Reding

Hi Thierry,

Quoted 30 lines · Thierry Reding
Quoted 7 lines · Stephen Warren

Review

Quoted 6 lines · Thierry Reding

From: Thierry Reding <[email protected]>

The Jetson TK1 has an ethernet NIC connected to the PCIe bus and routes the second root port to a miniPCIe slot. Enable the PCIe controller and

(quoted diff) +0 -0

b/arch/arm/dts/tegra124-jetson-tk1.dts

Quoted 5 lines

arch/arm/dts/tegra124-jetson-tk1.dts line 442

Quoted 5 lines
arch/arm/dts/tegra124-jetson-tk1.dts +3 -0
+    regulators {
 
+            /* Molex power connector */
+            vdd_5v0_sata: regulator at 13 {
Quoted 7 lines

...

Quoted 1 line

+ vdd_12v0_sata: regulator at 14 {

Those two aren't in the kernel DT yet. I'll assume they match what's been proposed for the SATA patches:-)

Review

Quoted 1 line
(quoted diff) +0 -0

b/board/nvidia/jetson-tk1/jetson-tk1.c

Quoted 4 lines

A lot of the AS3722 code here duplicates what's in board/nvidia/venice2/as3722_init.[ch]. It'd be good to put it all in one place. Personally I'd be OK with putting it into the existing Venice2

code,

Quoted 2 lines

but I suppose as Simon mentioned, a "real" AS3722 driver in drivers/power/pmic would be a good idea.

Quoted 9 lines

Unfortunately turning this into a real driver for AS3722 makes it impossible (or at least too difficult) to unify with the code in venice2/as3722_init.ch. The issue is that the new driver relies on infrastructure (I2C, FDT) that's not available in SPL (where this code is run). I tried extending the SPL with I2C and power drivers support so that I could use the driver here as well, but that keeps failing at various points, so I preferred having a proper driver for full U-Boot and kept the low-level code for CPU power rail setup as is.

That seems OK to me. When we have driver model in there we can perhaps revisit things.

Quoted 9 lines

Note that I haven't turned the AS3722 support into a "PMIC" driver, because the framework for that seems to be unusable. It doesn't seem to abstract away driver-specifics at all but rather provides a way to access registers in a uniform way (sort of what regmap does in Linux). Using that framework would therefore require knowledge about the exact register accesses within drivers and therefore wouldn't be an improvement over the current situation.

It doesn't provide a PMIC API as such - just a way to find a PMIC and the access registers. I think it is useful for that at least.

Regards,
Simon

#83 lore raw

PATCH 23/23 ARM: tegra: Enable PCIe on Jetson TK1

Quoted 1 line · Simon Glass

On 22 August 2014 06:09, Thierry Reding <[email protected]> wrote:

[...]

Quoted 11 lines
Quoted 8 lines

Note that I haven't turned the AS3722 support into a "PMIC" driver, because the framework for that seems to be unusable. It doesn't seem to abstract away driver-specifics at all but rather provides a way to access registers in a uniform way (sort of what regmap does in Linux). Using that framework would therefore require knowledge about the exact register accesses within drivers and therefore wouldn't be an improvement over the current situation.

It doesn't provide a PMIC API as such - just a way to find a PMIC and the access registers. I think it is useful for that at least.

But that's not very useful in itself, is it? I mean, there's no abstraction whatsoever for the PMIC functionality, so all users will need to implement direct register accesses, which essentially means there's about zero code reuse. So the abstraction is at the wrong point in my opinion and the only use-case where I think it would be beneficial is if the same PMIC could be used on different interfaces (I2C vs. SPI) and therefore the register access abstraction could allow a single driver to control both types.

I've opted instead to provide an somewhat higher-level API that users can call to set voltages on the regulators and enable them.

Thierry
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 819 bytes
Desc: not available
URL: <http://lists.denx.de/pipermail/u-boot/attachments/20140822/ec0c04fe/attachment.pgp>

#84 lore raw

PATCH 23/23 ARM: tegra: Enable PCIe on Jetson TK1

Hi Thierry,

Quoted 15 lines · Thierry Reding
Quoted 1 line · Simon Glass

On 22 August 2014 06:09, Thierry Reding <[email protected]> wrote:

[...]

Quoted 11 lines
Quoted 8 lines

Note that I haven't turned the AS3722 support into a "PMIC" driver, because the framework for that seems to be unusable. It doesn't seem to abstract away driver-specifics at all but rather provides a way to access registers in a uniform way (sort of what regmap does in Linux). Using that framework would therefore require knowledge about the exact register accesses within drivers and therefore wouldn't be an improvement over the current situation.

It doesn't provide a PMIC API as such - just a way to find a PMIC and the access registers. I think it is useful for that at least.

Quoted 8 lines

But that's not very useful in itself, is it? I mean, there's no abstraction whatsoever for the PMIC functionality, so all users will need to implement direct register accesses, which essentially means there's about zero code reuse. So the abstraction is at the wrong point in my opinion and the only use-case where I think it would be beneficial is if the same PMIC could be used on different interfaces (I2C vs. SPI) and therefore the register access abstraction could allow a single driver to control both types.

Yes that's right.

Quoted 3 lines

I've opted instead to provide an somewhat higher-level API that users can call to set voltages on the regulators and enable them.

But then this should use/extend the pmic interface I think, and not create a parallel one.

Regards,
Simon

#85 lore raw

PATCH 23/23 ARM: tegra: Enable PCIe on Jetson TK1

Quoted 1 line · Simon Glass

On 22 August 2014 13:40, Thierry Reding <[email protected]> wrote:

[...]

Quoted 5 lines
Quoted 2 lines

I've opted instead to provide an somewhat higher-level API that users can call to set voltages on the regulators and enable them.

But then this should use/extend the pmic interface I think, and not create a parallel one.

It's not a parallel framework. And it's not anything out of the ordinary either. There's a whole bunch of drivers in drivers/power that do the very same thing.

And I'm not sure something like Linux' regulator framework is something that we really need in U-Boot. The code in question is usually run in some board-specific initialization file, not from some generic driver that would need to be used in conjunction with potentially very many PMICs.

Thierry
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 836 bytes
Desc: not available
URL: <http://lists.denx.de/pipermail/u-boot/attachments/20140823/8f7acf78/attachment.pgp>

#86 lore raw

PATCH 23/23 ARM: tegra: Enable PCIe on Jetson TK1

Hi Thierry,

Quoted 13 lines · Thierry Reding
Quoted 1 line · Simon Glass

On 22 August 2014 13:40, Thierry Reding <[email protected]> wrote:

[...]

Quoted 5 lines
Quoted 2 lines

I've opted instead to provide an somewhat higher-level API that users can call to set voltages on the regulators and enable them.

But then this should use/extend the pmic interface I think, and not create a parallel one.

It's not a parallel framework. And it's not anything out of the ordinary either. There's a whole bunch of drivers in drivers/power that do the very same thing.

Quoted 5 lines

And I'm not sure something like Linux' regulator framework is something that we really need in U-Boot. The code in question is usually run in some board-specific initialization file, not from some generic driver that would need to be used in conjunction with potentially very many PMICs.

OK, well I suggest first take a look at pmic_tps65090.c and convince yourself that you can't plumb your pmic in in a similar way. It's up to you.

Regards,
Simon

#87 lore raw

PATCH 23/23 ARM: tegra: Enable PCIe on Jetson TK1

Quoted 22 lines · Simon Glass

Hi Thierry,

Quoted 13 lines · Thierry Reding
Quoted 1 line · Simon Glass

On 22 August 2014 13:40, Thierry Reding <[email protected]> wrote:

[...]

Quoted 5 lines
Quoted 2 lines

I've opted instead to provide an somewhat higher-level API that users can call to set voltages on the regulators and enable them.

But then this should use/extend the pmic interface I think, and not create a parallel one.

It's not a parallel framework. And it's not anything out of the ordinary either. There's a whole bunch of drivers in drivers/power that do the very same thing.

Quoted 5 lines

And I'm not sure something like Linux' regulator framework is something that we really need in U-Boot. The code in question is usually run in some board-specific initialization file, not from some generic driver that would need to be used in conjunction with potentially very many PMICs.

Quoted 3 lines

OK, well I suggest first take a look at pmic_tps65090.c and convince yourself that you can't plumb your pmic in in a similar way. It's up to you.

It's very similar to that driver except that it doesn't go through the trouble of "registering" the PMIC. Instead it works roughly like this:

	struct as3722_pmic *pmic;

	err = as3722_init(&pmic, fdt);
	if (err < 0)
		return err;

	err = as3722_sd_set_voltage(pmic, ...);
	if (err < 0)
		return err;

	err = as3722_sd_enable(pmic, ...);
	if (err < 0)
		return err;

That saves the public API from having to repeatedly go and look up the PMIC in the registry.

Thierry
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 836 bytes
Desc: not available
URL: <http://lists.denx.de/pipermail/u-boot/attachments/20140823/b9151cf6/attachment.pgp>

#88 lore raw

PATCH 23/23 ARM: tegra: Enable PCIe on Jetson TK1

In reply to Thierry Reding
Quoted 7 lines · Thierry Reding

From: Thierry Reding <[email protected]>

The Jetson TK1 has an ethernet NIC connected to the PCIe bus and routes the second root port to a miniPCIe slot. Enable the PCIe controller and the network driver to allow the device to boot over the network.

arch/arm/dts/tegra124-jetson-tk1.dts line 140

Quoted 10 lines
arch/arm/dts/tegra124-jetson-tk1.dts +4 -0
 
  	i2c at 7000d000 {
 
+		pmic: pmic at 40 {
 
+			regulators {
 
+				sd1 {
 
+					ams,ext-control = <1>;

According to an internal bug, we need to remove that property in order to get correct sequencing of the power rails at shutdown time. We need to fix that for the kernel too. However, we need to do more than just remove that property, or suspend won't actually turn off the rails:-/ So I suppose we should wait until the kernel patches land before resolving that; your patch does match what the kernel does currently.

#89 lore raw

PATCH 23/23 ARM: tegra: Enable PCIe on Jetson TK1

In reply to Thierry Reding

On 18/08/14 10:16, Thierry Reding wrote:
[...]

Quoted 18 lines
board/nvidia/jetson-tk1/jetson-tk1.c +18 -0
+static int as3722_gpio_direction_output(u8 gpio, u8 level)
+{
+	u8 value;
+	int err;
+
+	if (gpio > 7)
+		return -EINVAL;
+
+	if (level == 0)
+		value = AS3722_GPIO_CONTROL_MODE_OUTPUT_VDDL;
+	else
+		value = AS3722_GPIO_CONTROL_MODE_OUTPUT_VDDH;
+
+	err = as3722_write(AS3722_GPIO_CONTROL(gpio), value);
+	if (err) {
+		error("as3722: failed to configure GPIO#%u as output: %d\n",
+		      gpio, err);
+		return err;

board/nvidia/jetson-tk1/jetson-tk1.c void pinmux_init(void) · line 184

Quoted 10 lines
board/nvidia/jetson-tk1/jetson-tk1.c +10 -0
+	}
+
+	err = as3722_gpio_set(gpio, level);
+	if (err < 0) {
+		error("as3722: failed to set GPIO#%u high: %d\n", gpio, err);
+		return err;
+	}
+
+	return 0;
+}

This function doesn't work correctly if the GPIO was originally configured as inverted and low, which GPIO#2 seems to be. (as3722_read(AS3722_GPIO_CONTROL(2), &value) returns value == 0x87)...

Quoted 3 lines
board/nvidia/jetson-tk1/jetson-tk1.c +3 -0
+
+int tegra_pcie_board_init(void)
+{

[...]

board/nvidia/jetson-tk1/jetson-tk1.c void pinmux_init(void) · line 236

Quoted 6 lines
board/nvidia/jetson-tk1/jetson-tk1.c +6 -0
+
+	err = as3722_gpio_direction_output(2, 1);
+	if (err < 0) {
+		error("as3722: failed to set GPIO#2 high: %d\n", err);
+		return err;
+	}

[...]

On my board, this call results in UART corruption, like this:

tegra-pcie:   non-prefetchable memory: 0x13000000-0x20000000
tegra-pcie:   prefetchable memory: 0x20000000-0x40000000

??????b????b2x1, 1x1 configuration
??5R?tegra-pcie: probing port 1, using 1 lanes

Likely because GPIO#2 controls the +3.3V_LP0 rail, which powers the UART level shifters. Commenting the function call out fixes the corruption and PCI-E still works fine.

Signature · 1 line
nvpublic
#90 lore raw

PATCH 23/23 ARM: tegra: Enable PCIe on Jetson TK1

Quoted 26 lines · Tuomas Tynkkynen

On 18/08/14 10:16, Thierry Reding wrote:
[...]

Quoted 24 lines
board/nvidia/jetson-tk1/jetson-tk1.c +24 -0
+static int as3722_gpio_direction_output(u8 gpio, u8 level)
+{
+	u8 value;
+	int err;
+
+	if (gpio > 7)
+		return -EINVAL;
+
+	if (level == 0)
+		value = AS3722_GPIO_CONTROL_MODE_OUTPUT_VDDL;
+	else
+		value = AS3722_GPIO_CONTROL_MODE_OUTPUT_VDDH;
+
+	err = as3722_write(AS3722_GPIO_CONTROL(gpio), value);
+	if (err) {
+		error("as3722: failed to configure GPIO#%u as output: %d\n",
+		      gpio, err);
+		return err;
+	}
+
+	err = as3722_gpio_set(gpio, level);
+	if (err < 0) {
+		error("as3722: failed to set GPIO#%u high: %d\n", gpio, err);
+		return err;
Quoted 8 lines

board/nvidia/jetson-tk1/jetson-tk1.c void pinmux_init(void) · line 68

Quoted 4 lines
board/nvidia/jetson-tk1/jetson-tk1.c +4 -0
+	}
+
+	return 0;
+}

This function doesn't work correctly if the GPIO was originally configured as inverted and low, which GPIO#2 seems to be. (as3722_read(AS3722_GPIO_CONTROL(2), &value) returns value == 0x87)...

That should be equivalent to what we're setting but is a somewhat weird default. I guess the fact that we're inverting it and then changing the value to high in separate transactions makes the output flip twice.

Quoted 14 lines
Quoted 3 lines
board/nvidia/jetson-tk1/jetson-tk1.c +3 -0
+
+int tegra_pcie_board_init(void)
+{

[...]

board/nvidia/jetson-tk1/jetson-tk1.c void pinmux_init(void) · line 236

Quoted 6 lines
board/nvidia/jetson-tk1/jetson-tk1.c +6 -0
+
+	err = as3722_gpio_direction_output(2, 1);
+	if (err < 0) {
+		error("as3722: failed to set GPIO#2 high: %d\n", err);
+		return err;
+	}

[...]

On my board, this call results in UART corruption, like this:

Quoted 8 lines
tegra-pcie:   non-prefetchable memory: 0x13000000-0x20000000
tegra-pcie:   prefetchable memory: 0x20000000-0x40000000

??????b????b2x1, 1x1 configuration
??5R?tegra-pcie: probing port 1, using 1 lanes

Likely because GPIO#2 controls the +3.3V_LP0 rail, which powers the UART level shifters. Commenting the function call out fixes the corruption and PCI-E still works fine.

If I add a udelay(500) after the above I'm not able to reproduce the UART breakage anymore. But I guess making the AS3722 GPIO code smarter would be helpful. In the kernel this is done by checking the invert bit and then setting the value accordingly. I suppose the same could be done for the mode bits. I'll see if I can work up a patch.

Thierry
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 819 bytes
Desc: not available
URL: <http://lists.denx.de/pipermail/u-boot/attachments/20140827/a70598fd/attachment.pgp>

#91 lore raw

PATCH 23/23 ARM: tegra: Enable PCIe on Jetson TK1

Quoted 63 lines · Thierry Reding
Quoted 26 lines · Tuomas Tynkkynen

On 18/08/14 10:16, Thierry Reding wrote:
[...]

Quoted 24 lines
(quoted diff) +24 -0
+static int as3722_gpio_direction_output(u8 gpio, u8 level)
+{
+	u8 value;
+	int err;
+
+	if (gpio > 7)
+		return -EINVAL;
+
+	if (level == 0)
+		value = AS3722_GPIO_CONTROL_MODE_OUTPUT_VDDL;
+	else
+		value = AS3722_GPIO_CONTROL_MODE_OUTPUT_VDDH;
+
+	err = as3722_write(AS3722_GPIO_CONTROL(gpio), value);
+	if (err) {
+		error("as3722: failed to configure GPIO#%u as output: %d\n",
+		      gpio, err);
+		return err;
+	}
+
+	err = as3722_gpio_set(gpio, level);
+	if (err < 0) {
+		error("as3722: failed to set GPIO#%u high: %d\n", gpio, err);
+		return err;
Quoted 8 lines

Review

Quoted 4 lines
(quoted diff) +4 -0
+	}
+
+	return 0;
+}

This function doesn't work correctly if the GPIO was originally configured as inverted and low, which GPIO#2 seems to be. (as3722_read(AS3722_GPIO_CONTROL(2), &value) returns value == 0x87)...

That should be equivalent to what we're setting but is a somewhat weird default. I guess the fact that we're inverting it and then changing the value to high in separate transactions makes the output flip twice.

Quoted 14 lines
Quoted 3 lines
(quoted diff) +3 -0
+
+int tegra_pcie_board_init(void)
+{

[...]

Review

Quoted 6 lines
(quoted diff) +6 -0
+
+	err = as3722_gpio_direction_output(2, 1);
+	if (err < 0) {
+		error("as3722: failed to set GPIO#2 high: %d\n", err);
+		return err;
+	}

[...]

On my board, this call results in UART corruption, like this:

Quoted 8 lines
tegra-pcie:   non-prefetchable memory: 0x13000000-0x20000000
tegra-pcie:   prefetchable memory: 0x20000000-0x40000000

??????b????b2x1, 1x1 configuration
??5R?tegra-pcie: probing port 1, using 1 lanes

Likely because GPIO#2 controls the +3.3V_LP0 rail, which powers the UART level shifters. Commenting the function call out fixes the corruption and PCI-E still works fine.

Quoted 5 lines

If I add a udelay(500) after the above I'm not able to reproduce the UART breakage anymore. But I guess making the AS3722 GPIO code smarter would be helpful. In the kernel this is done by checking the invert bit and then setting the value accordingly. I suppose the same could be done for the mode bits. I'll see if I can work up a patch.

How about this:
-------------- next part --------------

drivers/power/as3722.c +14 -2
index 59d1bf1b50b0..393dc8608d07 100644
@@ -17,6 +17,7 @@
 #define AS3722_GPIO_CONTROL(n) (0x08 + (n))
 #define  AS3722_GPIO_CONTROL_MODE_OUTPUT_VDDH (1 << 0)
 #define  AS3722_GPIO_CONTROL_MODE_OUTPUT_VDDL (7 << 0)
+#define  AS3722_GPIO_CONTROL_MODE_MASK (7 << 0)
 #define  AS3722_GPIO_CONTROL_INVERT (1 << 7)
 #define AS3722_LDO_VOLTAGE(n) (0x10 + (n))
 #define AS3722_GPIO_SIGNAL_OUT 0x20
@@ -220,10 +221,21 @@ int as3722_gpio_direction_output(struct as3722 *pmic, unsigned int gpio,
 	if (gpio > 7)
 		return -EINVAL;
 
+	err = as3722_read(pmic, AS3722_GPIO_CONTROL(gpio), &value);
+	if (err < 0) {
+		error("failed to read GPIO#%u control register: %d", gpio, err);
+		return err;
+	}
+
+	if (value & AS3722_GPIO_CONTROL_INVERT)
+		level = !level;
+
+	value &= ~AS3722_GPIO_CONTROL_MODE_MASK;
+
 	if (level == 0)
-		value = AS3722_GPIO_CONTROL_MODE_OUTPUT_VDDL;
+		value |= AS3722_GPIO_CONTROL_MODE_OUTPUT_VDDL;
 	else
-		value = AS3722_GPIO_CONTROL_MODE_OUTPUT_VDDH;
+		value |= AS3722_GPIO_CONTROL_MODE_OUTPUT_VDDH;
 
 	err = as3722_write(pmic, AS3722_GPIO_CONTROL(gpio), value);
 	if (err) {

-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 819 bytes
Desc: not available
URL: <http://lists.denx.de/pipermail/u-boot/attachments/20140827/e771d6cb/attachment.pgp>

#92 lore raw

PATCH 23/23 ARM: tegra: Enable PCIe on Jetson TK1

On 27/08/14 17:34, Thierry Reding wrote:
[...]

Quoted 11 lines
Quoted 11 lines
Quoted 10 lines

On my board, this call results in UART corruption, like this:

tegra-pcie:   non-prefetchable memory: 0x13000000-0x20000000
tegra-pcie:   prefetchable memory: 0x20000000-0x40000000

??????b????b2x1, 1x1 configuration
??5R?tegra-pcie: probing port 1, using 1 lanes

Likely because GPIO#2 controls the +3.3V_LP0 rail, which powers the UART level shifters. Commenting the function call out fixes the corruption and PCI-E still works fine.

Quoted 7 lines
Quoted 5 lines

If I add a udelay(500) after the above I'm not able to reproduce the UART breakage anymore. But I guess making the AS3722 GPIO code smarter would be helpful. In the kernel this is done by checking the invert bit and then setting the value accordingly. I suppose the same could be done for the mode bits. I'll see if I can work up a patch.

How about this:

[...]

Yes, that helps.

Signature · 1 line
nvpublic