All of lore.kernel.org
 help / color / mirror / Atom feed
* [U-Boot] [PATCH 00/23] ARM: tegra: Add PCIe support
@ 2014-08-18  7:16 Thierry Reding
  2014-08-18  7:16 ` [U-Boot] [PATCH 01/23] fdt: Add functions to query a node's #address- and #size-cells Thierry Reding
                   ` (22 more replies)
  0 siblings, 23 replies; 95+ messages in thread
From: Thierry Reding @ 2014-08-18  7:16 UTC (permalink / raw)
  To: u-boot

From: Thierry Reding <treding@nvidia.com>

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

-- 
2.0.4

^ permalink raw reply	[flat|nested] 95+ messages in thread

* [U-Boot] [PATCH 01/23] fdt: Add functions to query a node's #address- and #size-cells
  2014-08-18  7:16 [U-Boot] [PATCH 00/23] ARM: tegra: Add PCIe support Thierry Reding
@ 2014-08-18  7:16 ` Thierry Reding
  2014-08-18 17:52   ` Simon Glass
  2014-08-18  7:16 ` [U-Boot] [PATCH 02/23] fdt: Add a function to get the index of a string Thierry Reding
                   ` (21 subsequent siblings)
  22 siblings, 1 reply; 95+ messages in thread
From: Thierry Reding @ 2014-08-18  7:16 UTC (permalink / raw)
  To: u-boot

From: Thierry Reding <treding@nvidia.com>

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.

Signed-off-by: Thierry Reding <treding@nvidia.com>
---
 include/libfdt.h    | 28 ++++++++++++++++++++++++++++
 lib/libfdt/fdt_ro.c | 36 ++++++++++++++++++++++++++++++++++++
 2 files changed, 64 insertions(+)

diff --git a/include/libfdt.h b/include/libfdt.h
index a1ef1e15df3d..e7f991b388cf 100644
--- a/include/libfdt.h
+++ b/include/libfdt.h
@@ -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 */
diff --git a/lib/libfdt/fdt_ro.c b/lib/libfdt/fdt_ro.c
index 36af0435254b..17cd11333c1e 100644
--- a/lib/libfdt/fdt_ro.c
+++ b/lib/libfdt/fdt_ro.c
@@ -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;
+}
-- 
2.0.4

^ permalink raw reply related	[flat|nested] 95+ messages in thread

* [U-Boot] [PATCH 02/23] fdt: Add a function to get the index of a string
  2014-08-18  7:16 [U-Boot] [PATCH 00/23] ARM: tegra: Add PCIe support Thierry Reding
  2014-08-18  7:16 ` [U-Boot] [PATCH 01/23] fdt: Add functions to query a node's #address- and #size-cells Thierry Reding
@ 2014-08-18  7:16 ` Thierry Reding
  2014-08-18 17:58   ` Simon Glass
  2014-08-18  7:16 ` [U-Boot] [PATCH 03/23] fdt: Add resource parsing functions Thierry Reding
                   ` (20 subsequent siblings)
  22 siblings, 1 reply; 95+ messages in thread
From: Thierry Reding @ 2014-08-18  7:16 UTC (permalink / raw)
  To: u-boot

From: Thierry Reding <treding@nvidia.com>

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.

Signed-off-by: Thierry Reding <treding@nvidia.com>
---
 include/libfdt.h    | 11 +++++++++++
 lib/libfdt/fdt_ro.c | 28 ++++++++++++++++++++++++++++
 2 files changed, 39 insertions(+)

diff --git a/include/libfdt.h b/include/libfdt.h
index e7f991b388cf..4d7fb2681669 100644
--- a/include/libfdt.h
+++ b/include/libfdt.h
@@ -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)                           */
 /**********************************************************************/
diff --git a/lib/libfdt/fdt_ro.c b/lib/libfdt/fdt_ro.c
index 17cd11333c1e..f211c64ca7ca 100644
--- a/lib/libfdt/fdt_ro.c
+++ b/lib/libfdt/fdt_ro.c
@@ -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)
 {
-- 
2.0.4

^ permalink raw reply related	[flat|nested] 95+ messages in thread

* [U-Boot] [PATCH 03/23] fdt: Add resource parsing functions
  2014-08-18  7:16 [U-Boot] [PATCH 00/23] ARM: tegra: Add PCIe support Thierry Reding
  2014-08-18  7:16 ` [U-Boot] [PATCH 01/23] fdt: Add functions to query a node's #address- and #size-cells Thierry Reding
  2014-08-18  7:16 ` [U-Boot] [PATCH 02/23] fdt: Add a function to get the index of a string Thierry Reding
@ 2014-08-18  7:16 ` Thierry Reding
  2014-08-18 18:06   ` Simon Glass
  2014-08-18  7:16 ` [U-Boot] [PATCH 04/23] fdt: Add a function to return PCI BDF triplet Thierry Reding
                   ` (19 subsequent siblings)
  22 siblings, 1 reply; 95+ messages in thread
From: Thierry Reding @ 2014-08-18  7:16 UTC (permalink / raw)
  To: u-boot

From: Thierry Reding <treding@nvidia.com>

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.

Signed-off-by: Thierry Reding <treding@nvidia.com>
---
 include/fdtdec.h | 48 ++++++++++++++++++++++++++++++++++++++++++++++++
 lib/fdtdec.c     | 43 +++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 91 insertions(+)

diff --git a/include/fdtdec.h b/include/fdtdec.h
index 856e6cf766de..e9091eee6bae 100644
--- a/include/fdtdec.h
+++ b/include/fdtdec.h
@@ -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
diff --git a/lib/fdtdec.c b/lib/fdtdec.c
index eb5aa20526fd..fbfae4a7cbaf 100644
--- a/lib/fdtdec.c
+++ b/lib/fdtdec.c
@@ -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)
+{
+	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;
+
+	while (ptr + na + ns <= end) {
+		if (i == index) {
+			res->start = fdt_addr_to_cpu(*ptr);
+			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
-- 
2.0.4

^ permalink raw reply related	[flat|nested] 95+ messages in thread

* [U-Boot] [PATCH 04/23] fdt: Add a function to return PCI BDF triplet
  2014-08-18  7:16 [U-Boot] [PATCH 00/23] ARM: tegra: Add PCIe support Thierry Reding
                   ` (2 preceding siblings ...)
  2014-08-18  7:16 ` [U-Boot] [PATCH 03/23] fdt: Add resource parsing functions Thierry Reding
@ 2014-08-18  7:16 ` Thierry Reding
  2014-08-18 18:20   ` Simon Glass
  2014-08-18  7:16 ` [U-Boot] [PATCH 05/23] fdt: Add a subnodes iterator macro Thierry Reding
                   ` (18 subsequent siblings)
  22 siblings, 1 reply; 95+ messages in thread
From: Thierry Reding @ 2014-08-18  7:16 UTC (permalink / raw)
  To: u-boot

From: Thierry Reding <treding@nvidia.com>

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.

Signed-off-by: Thierry Reding <treding@nvidia.com>
---
 include/fdtdec.h | 11 +++++++++++
 lib/fdtdec.c     | 14 ++++++++++++++
 2 files changed, 25 insertions(+)

diff --git a/include/fdtdec.h b/include/fdtdec.h
index e9091eee6bae..56bc29375128 100644
--- a/include/fdtdec.h
+++ b/include/fdtdec.h
@@ -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
diff --git a/lib/fdtdec.c b/lib/fdtdec.c
index fbfae4a7cbaf..d2f2c9164b37 100644
--- a/lib/fdtdec.c
+++ b/lib/fdtdec.c
@@ -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
-- 
2.0.4

^ permalink raw reply related	[flat|nested] 95+ messages in thread

* [U-Boot] [PATCH 05/23] fdt: Add a subnodes iterator macro
  2014-08-18  7:16 [U-Boot] [PATCH 00/23] ARM: tegra: Add PCIe support Thierry Reding
                   ` (3 preceding siblings ...)
  2014-08-18  7:16 ` [U-Boot] [PATCH 04/23] fdt: Add a function to return PCI BDF triplet Thierry Reding
@ 2014-08-18  7:16 ` Thierry Reding
  2014-08-18 18:11   ` Simon Glass
  2014-08-18  7:16 ` [U-Boot] [PATCH 06/23] pci: Abort early if bus does not exist Thierry Reding
                   ` (17 subsequent siblings)
  22 siblings, 1 reply; 95+ messages in thread
From: Thierry Reding @ 2014-08-18  7:16 UTC (permalink / raw)
  To: u-boot

From: Thierry Reding <treding@nvidia.com>

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.

Signed-off-by: Thierry Reding <treding@nvidia.com>
---
 include/libfdt.h | 20 ++++++++++++++++++++
 1 file changed, 20 insertions(+)

diff --git a/include/libfdt.h b/include/libfdt.h
index 4d7fb2681669..0330d7a29a58 100644
--- a/include/libfdt.h
+++ b/include/libfdt.h
@@ -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                                                  */
 /**********************************************************************/
-- 
2.0.4

^ permalink raw reply related	[flat|nested] 95+ messages in thread

* [U-Boot] [PATCH 06/23] pci: Abort early if bus does not exist
  2014-08-18  7:16 [U-Boot] [PATCH 00/23] ARM: tegra: Add PCIe support Thierry Reding
                   ` (4 preceding siblings ...)
  2014-08-18  7:16 ` [U-Boot] [PATCH 05/23] fdt: Add a subnodes iterator macro Thierry Reding
@ 2014-08-18  7:16 ` Thierry Reding
  2014-08-18  7:16 ` [U-Boot] [PATCH 07/23] pci: Honour pci_skip_dev() Thierry Reding
                   ` (16 subsequent siblings)
  22 siblings, 0 replies; 95+ messages in thread
From: Thierry Reding @ 2014-08-18  7:16 UTC (permalink / raw)
  To: u-boot

From: Thierry Reding <treding@nvidia.com>

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.

Signed-off-by: Thierry Reding <treding@nvidia.com>
---
 common/cmd_pci.c | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/common/cmd_pci.c b/common/cmd_pci.c
index a1ba42e2f3a2..5a6048c92604 100644
--- a/common/cmd_pci.c
+++ b/common/cmd_pci.c
@@ -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) {
-- 
2.0.4

^ permalink raw reply related	[flat|nested] 95+ messages in thread

* [U-Boot] [PATCH 07/23] pci: Honour pci_skip_dev()
  2014-08-18  7:16 [U-Boot] [PATCH 00/23] ARM: tegra: Add PCIe support Thierry Reding
                   ` (5 preceding siblings ...)
  2014-08-18  7:16 ` [U-Boot] [PATCH 06/23] pci: Abort early if bus does not exist Thierry Reding
@ 2014-08-18  7:16 ` Thierry Reding
  2014-08-18  7:16 ` [U-Boot] [PATCH 08/23] Add pr_fmt() macro Thierry Reding
                   ` (15 subsequent siblings)
  22 siblings, 0 replies; 95+ messages in thread
From: Thierry Reding @ 2014-08-18  7:16 UTC (permalink / raw)
  To: u-boot

From: Thierry Reding <treding@nvidia.com>

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.

Signed-off-by: Thierry Reding <treding@nvidia.com>
---
 common/cmd_pci.c  | 3 +++
 drivers/pci/pci.c | 3 +++
 include/pci.h     | 1 +
 3 files changed, 7 insertions(+)

diff --git a/common/cmd_pci.c b/common/cmd_pci.c
index 5a6048c92604..e3a77e35820c 100644
--- a/common/cmd_pci.c
+++ b/common/cmd_pci.c
@@ -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;
diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c
index ed113bf4022f..61882ba1462f 100644
--- a/drivers/pci/pci.c
+++ b/drivers/pci/pci.c
@@ -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,
diff --git a/include/pci.h b/include/pci.h
index 461f17c05895..133fff4957b1 100644
--- a/include/pci.h
+++ b/include/pci.h
@@ -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);
 
-- 
2.0.4

^ permalink raw reply related	[flat|nested] 95+ messages in thread

* [U-Boot] [PATCH 08/23] Add pr_fmt() macro
  2014-08-18  7:16 [U-Boot] [PATCH 00/23] ARM: tegra: Add PCIe support Thierry Reding
                   ` (6 preceding siblings ...)
  2014-08-18  7:16 ` [U-Boot] [PATCH 07/23] pci: Honour pci_skip_dev() Thierry Reding
@ 2014-08-18  7:16 ` Thierry Reding
  2014-08-18 18:24   ` Simon Glass
  2014-08-18  7:16 ` [U-Boot] [PATCH 09/23] ARM: tegra: Implement tegra_plle_enable() Thierry Reding
                   ` (14 subsequent siblings)
  22 siblings, 1 reply; 95+ messages in thread
From: Thierry Reding @ 2014-08-18  7:16 UTC (permalink / raw)
  To: u-boot

From: Thierry Reding <treding@nvidia.com>

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

Signed-off-by: Thierry Reding <treding@nvidia.com>
---
 include/common.h | 14 +++++++++-----
 1 file changed, 9 insertions(+), 5 deletions(-)

diff --git a/include/common.h b/include/common.h
index 1d6cb48ff078..65db04b452d7 100644
--- a/include/common.h
+++ b/include/common.h
@@ -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)
 
-- 
2.0.4

^ permalink raw reply related	[flat|nested] 95+ messages in thread

* [U-Boot] [PATCH 09/23] ARM: tegra: Implement tegra_plle_enable()
  2014-08-18  7:16 [U-Boot] [PATCH 00/23] ARM: tegra: Add PCIe support Thierry Reding
                   ` (7 preceding siblings ...)
  2014-08-18  7:16 ` [U-Boot] [PATCH 08/23] Add pr_fmt() macro Thierry Reding
@ 2014-08-18  7:16 ` Thierry Reding
  2014-08-20 18:12   ` Stephen Warren
  2014-08-18  7:16 ` [U-Boot] [PATCH 10/23] ARM: tegra: Provide PCIEXCLK reset ID Thierry Reding
                   ` (13 subsequent siblings)
  22 siblings, 1 reply; 95+ messages in thread
From: Thierry Reding @ 2014-08-18  7:16 UTC (permalink / raw)
  To: u-boot

From: Thierry Reding <treding@nvidia.com>

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.

Signed-off-by: Thierry Reding <treding@nvidia.com>
---
 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(+)

diff --git a/arch/arm/cpu/tegra124-common/clock.c b/arch/arm/cpu/tegra124-common/clock.c
index 739436326eca..fc8bd194ddc9 100644
--- a/arch/arm/cpu/tegra124-common/clock.c
+++ b/arch/arm/cpu/tegra124-common/clock.c
@@ -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;
+}
diff --git a/arch/arm/cpu/tegra20-common/clock.c b/arch/arm/cpu/tegra20-common/clock.c
index 0c4f5fb288a0..d55fbc87c340 100644
--- a/arch/arm/cpu/tegra20-common/clock.c
+++ b/arch/arm/cpu/tegra20-common/clock.c
@@ -7,6 +7,7 @@
 /* Tegra20 Clock control functions */
 
 #include <common.h>
+#include <errno.h>
 #include <asm/io.h>
 #include <asm/arch/clock.h>
 #include <asm/arch/tegra.h>
@@ -548,3 +549,139 @@ void clock_early_init(void)
 void arch_timer_init(void)
 {
 }
+
+#define PMC_SATA_PWRGT 0x1ac
+#define  PMC_SATA_PWRGT_PLLE_IDDQ_OVERRIDE (1 << 5)
+#define  PMC_SATA_PWRGT_PLLE_IDDQ_SWCTL (1 << 4)
+
+#define PLLE_SS_CNTL 0x68
+#define  PLLE_SS_CNTL_SSCINCINTRV(x) (((x) & 0x3f) << 24)
+#define  PLLE_SS_CNTL_SSCINC(x) (((x) & 0xff) << 16)
+#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_CML (1 << 31)
+#define  PLLE_BASE_ENABLE (1 << 30)
+#define  PLLE_BASE_PLDIV_CML(x) (((x) & 0xf) << 24)
+#define  PLLE_BASE_PLDIV(x) (((x) & 0x3f) << 16)
+#define  PLLE_BASE_NDIV(x) (((x) & 0xff) << 8)
+#define  PLLE_BASE_MDIV(x) (((x) & 0xff) << 0)
+
+#define PLLE_MISC 0x0ec
+#define  PLLE_MISC_SETUP_BASE(x) (((x) & 0xffff) << 16)
+#define  PLLE_MISC_PLL_READY (1 << 15)
+#define  PLLE_MISC_LOCK (1 << 11)
+#define  PLLE_MISC_LOCK_ENABLE (1 << 9)
+#define  PLLE_MISC_SETUP_EXT(x) (((x) & 0x3) << 2)
+
+static int tegra_plle_train(void)
+{
+	unsigned int timeout = 2000;
+	unsigned long value;
+
+	value = readl(NV_PA_PMC_BASE + PMC_SATA_PWRGT);
+	value |= PMC_SATA_PWRGT_PLLE_IDDQ_OVERRIDE;
+	writel(value, NV_PA_PMC_BASE + PMC_SATA_PWRGT);
+
+	value = readl(NV_PA_PMC_BASE + PMC_SATA_PWRGT);
+	value |= PMC_SATA_PWRGT_PLLE_IDDQ_SWCTL;
+	writel(value, NV_PA_PMC_BASE + PMC_SATA_PWRGT);
+
+	value = readl(NV_PA_PMC_BASE + PMC_SATA_PWRGT);
+	value &= ~PMC_SATA_PWRGT_PLLE_IDDQ_OVERRIDE;
+	writel(value, NV_PA_PMC_BASE + PMC_SATA_PWRGT);
+
+	do {
+		value = readl(NV_PA_CLK_RST_BASE + PLLE_MISC);
+		if (value & PLLE_MISC_PLL_READY)
+			break;
+
+		udelay(100);
+	} while (--timeout);
+
+	if (timeout == 0) {
+		error("timeout waiting for PLLE to become ready");
+		return -ETIMEDOUT;
+	}
+
+	return 0;
+}
+
+int tegra_plle_enable(void)
+{
+	unsigned int timeout = 1000;
+	u32 value;
+	int err;
+
+	/* disable PLLE clock */
+	value = readl(NV_PA_CLK_RST_BASE + PLLE_BASE);
+	value &= ~PLLE_BASE_ENABLE_CML;
+	value &= ~PLLE_BASE_ENABLE;
+	writel(value, NV_PA_CLK_RST_BASE + PLLE_BASE);
+
+	/* clear lock enable and setup field */
+	value = readl(NV_PA_CLK_RST_BASE + PLLE_MISC);
+	value &= ~PLLE_MISC_LOCK_ENABLE;
+	value &= ~PLLE_MISC_SETUP_BASE(0xffff);
+	value &= ~PLLE_MISC_SETUP_EXT(0x3);
+	writel(value, NV_PA_CLK_RST_BASE + PLLE_MISC);
+
+	value = readl(NV_PA_CLK_RST_BASE + PLLE_MISC);
+	if ((value & PLLE_MISC_PLL_READY) == 0) {
+		err = tegra_plle_train();
+		if (err < 0) {
+			error("failed to train PLLE: %d", err);
+			return err;
+		}
+	}
+
+	value = readl(NV_PA_CLK_RST_BASE + PLLE_MISC);
+	value |= PLLE_MISC_SETUP_BASE(0x7);
+	value |= PLLE_MISC_LOCK_ENABLE;
+	value |= PLLE_MISC_SETUP_EXT(0);
+	writel(value, NV_PA_CLK_RST_BASE + PLLE_MISC);
+
+	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_ENABLE_CML | PLLE_BASE_ENABLE;
+	writel(value, NV_PA_CLK_RST_BASE + PLLE_BASE);
+
+	do {
+		value = readl(NV_PA_CLK_RST_BASE + PLLE_MISC);
+		if (value & PLLE_MISC_LOCK)
+			break;
+
+		udelay(2);
+	} while (--timeout);
+
+	if (timeout == 0) {
+		error("timeout waiting for PLLE to lock");
+		return -ETIMEDOUT;
+	}
+
+	udelay(50);
+
+	value = readl(NV_PA_CLK_RST_BASE + PLLE_SS_CNTL);
+	value &= ~PLLE_SS_CNTL_SSCINCINTRV(0x3f);
+	value |= PLLE_SS_CNTL_SSCINCINTRV(0x18);
+
+	value &= ~PLLE_SS_CNTL_SSCINC(0xff);
+	value |= PLLE_SS_CNTL_SSCINC(0x01);
+
+	value &= ~PLLE_SS_CNTL_SSCBYP;
+	value &= ~PLLE_SS_CNTL_INTERP_RESET;
+	value &= ~PLLE_SS_CNTL_BYPASS_SS;
+
+	value &= ~PLLE_SS_CNTL_SSCMAX(0x1ff);
+	value |= PLLE_SS_CNTL_SSCMAX(0x24);
+	writel(value, NV_PA_CLK_RST_BASE + PLLE_SS_CNTL);
+
+	return 0;
+}
diff --git a/arch/arm/cpu/tegra30-common/clock.c b/arch/arm/cpu/tegra30-common/clock.c
index 80ba2d8c1ca5..8e5c49888219 100644
--- a/arch/arm/cpu/tegra30-common/clock.c
+++ b/arch/arm/cpu/tegra30-common/clock.c
@@ -17,6 +17,7 @@
 /* Tegra30 Clock control functions */
 
 #include <common.h>
+#include <errno.h>
 #include <asm/io.h>
 #include <asm/arch/clock.h>
 #include <asm/arch/tegra.h>
@@ -587,3 +588,156 @@ void clock_early_init(void)
 void arch_timer_init(void)
 {
 }
+
+#define PMC_SATA_PWRGT 0x1ac
+#define  PMC_SATA_PWRGT_PLLE_IDDQ_OVERRIDE (1 << 5)
+#define  PMC_SATA_PWRGT_PLLE_IDDQ_SWCTL (1 << 4)
+
+#define PLLE_SS_CNTL 0x68
+#define  PLLE_SS_CNTL_SSCINCINTRV(x) (((x) & 0x3f) << 24)
+#define  PLLE_SS_CNTL_SSCINC(x) (((x) & 0xff) << 16)
+#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_CML (1 << 31)
+#define  PLLE_BASE_ENABLE (1 << 30)
+#define  PLLE_BASE_PLDIV_CML(x) (((x) & 0xf) << 24)
+#define  PLLE_BASE_PLDIV(x) (((x) & 0x3f) << 16)
+#define  PLLE_BASE_NDIV(x) (((x) & 0xff) << 8)
+#define  PLLE_BASE_MDIV(x) (((x) & 0xff) << 0)
+
+#define PLLE_MISC 0x0ec
+#define  PLLE_MISC_SETUP_BASE(x) (((x) & 0xffff) << 16)
+#define  PLLE_MISC_PLL_READY (1 << 15)
+#define  PLLE_MISC_LOCK (1 << 11)
+#define  PLLE_MISC_LOCK_ENABLE (1 << 9)
+#define  PLLE_MISC_SETUP_EXT(x) (((x) & 0x3) << 2)
+
+static int tegra_plle_train(void)
+{
+	unsigned int timeout = 2000;
+	unsigned long value;
+
+	value = readl(NV_PA_PMC_BASE + PMC_SATA_PWRGT);
+	value |= PMC_SATA_PWRGT_PLLE_IDDQ_OVERRIDE;
+	writel(value, NV_PA_PMC_BASE + PMC_SATA_PWRGT);
+
+	value = readl(NV_PA_PMC_BASE + PMC_SATA_PWRGT);
+	value |= PMC_SATA_PWRGT_PLLE_IDDQ_SWCTL;
+	writel(value, NV_PA_PMC_BASE + PMC_SATA_PWRGT);
+
+	value = readl(NV_PA_PMC_BASE + PMC_SATA_PWRGT);
+	value &= ~PMC_SATA_PWRGT_PLLE_IDDQ_OVERRIDE;
+	writel(value, NV_PA_PMC_BASE + PMC_SATA_PWRGT);
+
+	do {
+		value = readl(NV_PA_CLK_RST_BASE + PLLE_MISC);
+		if (value & PLLE_MISC_PLL_READY)
+			break;
+
+		udelay(100);
+	} while (--timeout);
+
+	if (timeout == 0) {
+		error("timeout waiting for PLLE to become ready");
+		return -ETIMEDOUT;
+	}
+
+	return 0;
+}
+
+int tegra_plle_enable(void)
+{
+	unsigned int cpcon = 11, p = 18, n = 150, m = 1, timeout = 1000;
+	u32 value;
+	int err;
+
+	/* disable PLLE clock */
+	value = readl(NV_PA_CLK_RST_BASE + PLLE_BASE);
+	value &= ~PLLE_BASE_ENABLE_CML;
+	value &= ~PLLE_BASE_ENABLE;
+	writel(value, NV_PA_CLK_RST_BASE + PLLE_BASE);
+
+	/* clear lock enable and setup field */
+	value = readl(NV_PA_CLK_RST_BASE + PLLE_MISC);
+	value &= ~PLLE_MISC_LOCK_ENABLE;
+	value &= ~PLLE_MISC_SETUP_BASE(0xffff);
+	value &= ~PLLE_MISC_SETUP_EXT(0x3);
+	writel(value, NV_PA_CLK_RST_BASE + PLLE_MISC);
+
+	value = readl(NV_PA_CLK_RST_BASE + PLLE_MISC);
+	if ((value & PLLE_MISC_PLL_READY) == 0) {
+		err = tegra_plle_train();
+		if (err < 0) {
+			error("failed to train PLLE: %d", err);
+			return err;
+		}
+	}
+
+	/* configure PLLE */
+	value = readl(NV_PA_CLK_RST_BASE + PLLE_BASE);
+
+	value &= ~PLLE_BASE_PLDIV_CML(0x0f);
+	value |= PLLE_BASE_PLDIV_CML(cpcon);
+
+	value &= ~PLLE_BASE_PLDIV(0x3f);
+	value |= PLLE_BASE_PLDIV(p);
+
+	value &= ~PLLE_BASE_NDIV(0xff);
+	value |= PLLE_BASE_NDIV(n);
+
+	value &= ~PLLE_BASE_MDIV(0xff);
+	value |= PLLE_BASE_MDIV(m);
+
+	writel(value, NV_PA_CLK_RST_BASE + PLLE_BASE);
+
+	value = readl(NV_PA_CLK_RST_BASE + PLLE_MISC);
+	value |= PLLE_MISC_SETUP_BASE(0x7);
+	value |= PLLE_MISC_LOCK_ENABLE;
+	value |= PLLE_MISC_SETUP_EXT(0);
+	writel(value, NV_PA_CLK_RST_BASE + PLLE_MISC);
+
+	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_ENABLE_CML | PLLE_BASE_ENABLE;
+	writel(value, NV_PA_CLK_RST_BASE + PLLE_BASE);
+
+	do {
+		value = readl(NV_PA_CLK_RST_BASE + PLLE_MISC);
+		if (value & PLLE_MISC_LOCK)
+			break;
+
+		udelay(2);
+	} while (--timeout);
+
+	if (timeout == 0) {
+		error("timeout waiting for PLLE to lock");
+		return -ETIMEDOUT;
+	}
+
+	udelay(50);
+
+	value = readl(NV_PA_CLK_RST_BASE + PLLE_SS_CNTL);
+	value &= ~PLLE_SS_CNTL_SSCINCINTRV(0x3f);
+	value |= PLLE_SS_CNTL_SSCINCINTRV(0x18);
+
+	value &= ~PLLE_SS_CNTL_SSCINC(0xff);
+	value |= PLLE_SS_CNTL_SSCINC(0x01);
+
+	value &= ~PLLE_SS_CNTL_SSCBYP;
+	value &= ~PLLE_SS_CNTL_INTERP_RESET;
+	value &= ~PLLE_SS_CNTL_BYPASS_SS;
+
+	value &= ~PLLE_SS_CNTL_SSCMAX(0x1ff);
+	value |= PLLE_SS_CNTL_SSCMAX(0x24);
+	writel(value, NV_PA_CLK_RST_BASE + PLLE_SS_CNTL);
+
+	return 0;
+}
diff --git a/arch/arm/include/asm/arch-tegra124/clock.h b/arch/arm/include/asm/arch-tegra124/clock.h
index 8e39d21a7b5e..8e650862529e 100644
--- a/arch/arm/include/asm/arch-tegra124/clock.h
+++ b/arch/arm/include/asm/arch-tegra124/clock.h
@@ -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_ */
diff --git a/arch/arm/include/asm/arch-tegra20/clock.h b/arch/arm/include/asm/arch-tegra20/clock.h
index 889c65a16f1f..4df8da96e2a3 100644
--- a/arch/arm/include/asm/arch-tegra20/clock.h
+++ b/arch/arm/include/asm/arch-tegra20/clock.h
@@ -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 */
diff --git a/arch/arm/include/asm/arch-tegra30/clock.h b/arch/arm/include/asm/arch-tegra30/clock.h
index 2f24a75cc4c3..410c35289978 100644
--- a/arch/arm/include/asm/arch-tegra30/clock.h
+++ b/arch/arm/include/asm/arch-tegra30/clock.h
@@ -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_ */
-- 
2.0.4

^ permalink raw reply related	[flat|nested] 95+ messages in thread

* [U-Boot] [PATCH 10/23] ARM: tegra: Provide PCIEXCLK reset ID
  2014-08-18  7:16 [U-Boot] [PATCH 00/23] ARM: tegra: Add PCIe support Thierry Reding
                   ` (8 preceding siblings ...)
  2014-08-18  7:16 ` [U-Boot] [PATCH 09/23] ARM: tegra: Implement tegra_plle_enable() Thierry Reding
@ 2014-08-18  7:16 ` Thierry Reding
  2014-08-20 18:20   ` Stephen Warren
  2014-08-18  7:16 ` [U-Boot] [PATCH 11/23] ARM: tegra: Implement powergate support Thierry Reding
                   ` (12 subsequent siblings)
  22 siblings, 1 reply; 95+ messages in thread
From: Thierry Reding @ 2014-08-18  7:16 UTC (permalink / raw)
  To: u-boot

From: Thierry Reding <treding@nvidia.com>

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

Signed-off-by: Thierry Reding <treding@nvidia.com>
---
 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(-)

diff --git a/arch/arm/cpu/tegra20-common/clock.c b/arch/arm/cpu/tegra20-common/clock.c
index d55fbc87c340..7b9e10cd93ae 100644
--- a/arch/arm/cpu/tegra20-common/clock.c
+++ b/arch/arm/cpu/tegra20-common/clock.c
@@ -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:
diff --git a/arch/arm/cpu/tegra30-common/clock.c b/arch/arm/cpu/tegra30-common/clock.c
index 8e5c49888219..0eb0f0ade37c 100644
--- a/arch/arm/cpu/tegra30-common/clock.c
+++ b/arch/arm/cpu/tegra30-common/clock.c
@@ -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:
diff --git a/arch/arm/include/asm/arch-tegra20/clock-tables.h b/arch/arm/include/asm/arch-tegra20/clock-tables.h
index a09cb0197863..894be088cde2 100644
--- a/arch/arm/include/asm/arch-tegra20/clock-tables.h
+++ b/arch/arm/include/asm/arch-tegra20/clock-tables.h
@@ -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,
-- 
2.0.4

^ permalink raw reply related	[flat|nested] 95+ messages in thread

* [U-Boot] [PATCH 11/23] ARM: tegra: Implement powergate support
  2014-08-18  7:16 [U-Boot] [PATCH 00/23] ARM: tegra: Add PCIe support Thierry Reding
                   ` (9 preceding siblings ...)
  2014-08-18  7:16 ` [U-Boot] [PATCH 10/23] ARM: tegra: Provide PCIEXCLK reset ID Thierry Reding
@ 2014-08-18  7:16 ` Thierry Reding
  2014-08-20 18:24   ` Stephen Warren
  2014-08-18  7:16 ` [U-Boot] [PATCH 12/23] ARM: tegra: Implement XUSB pad controller Thierry Reding
                   ` (11 subsequent siblings)
  22 siblings, 1 reply; 95+ messages in thread
From: Thierry Reding @ 2014-08-18  7:16 UTC (permalink / raw)
  To: u-boot

From: Thierry Reding <treding@nvidia.com>

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

Signed-off-by: Thierry Reding <treding@nvidia.com>
---
 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

diff --git a/arch/arm/cpu/tegra-common/Makefile b/arch/arm/cpu/tegra-common/Makefile
index 892556e64451..fed618ba8fc9 100644
--- a/arch/arm/cpu/tegra-common/Makefile
+++ b/arch/arm/cpu/tegra-common/Makefile
@@ -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
diff --git a/arch/arm/cpu/tegra-common/powergate.c b/arch/arm/cpu/tegra-common/powergate.c
new file mode 100644
index 000000000000..2097bbcde365
--- /dev/null
+++ b/arch/arm/cpu/tegra-common/powergate.c
@@ -0,0 +1,80 @@
+#include <common.h>
+
+#include <asm/io.h>
+#include <asm/types.h>
+
+#include <asm/arch/powergate.h>
+#include <asm/arch/tegra.h>
+
+#define PWRGATE_TOGGLE 0x30
+#define  PWRGATE_TOGGLE_START (1 << 8)
+
+#define PWRGATE_STATUS 0x38
+
+static int tegra_powergate_set(enum tegra_powergate id, bool state)
+{
+	unsigned long value;
+	bool old_state;
+
+	value = readl(NV_PA_PMC_BASE + PWRGATE_STATUS);
+	old_state = value & (1 << id);
+
+	if (state == old_state)
+		return 0;
+
+	writel(PWRGATE_TOGGLE_START | id, NV_PA_PMC_BASE + PWRGATE_TOGGLE);
+
+	return 0;
+}
+
+static int tegra_powergate_power_on(enum tegra_powergate id)
+{
+	return tegra_powergate_set(id, true);
+}
+
+int tegra_powergate_power_off(enum tegra_powergate id)
+{
+	return tegra_powergate_set(id, false);
+}
+
+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;
+
+	writel(value, NV_PA_PMC_BASE + 0x34);
+
+	return 0;
+}
+
+int tegra_powergate_sequence_power_up(enum tegra_powergate id,
+				      enum periph_id periph)
+{
+	int err;
+
+	reset_set_enable(periph, 1);
+
+	err = tegra_powergate_power_on(id);
+	if (err < 0)
+		return err;
+
+	clock_enable(periph);
+
+	udelay(10);
+
+	err = tegra_powergate_remove_clamping(id);
+	if (err < 0)
+		return err;
+
+	udelay(10);
+
+	reset_set_enable(periph, 0);
+
+	return 0;
+}
diff --git a/arch/arm/include/asm/arch-tegra/powergate.h b/arch/arm/include/asm/arch-tegra/powergate.h
new file mode 100644
index 000000000000..53bed37d42c1
--- /dev/null
+++ b/arch/arm/include/asm/arch-tegra/powergate.h
@@ -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
diff --git a/arch/arm/include/asm/arch-tegra114/powergate.h b/arch/arm/include/asm/arch-tegra114/powergate.h
new file mode 100644
index 000000000000..260ea801b81b
--- /dev/null
+++ b/arch/arm/include/asm/arch-tegra114/powergate.h
@@ -0,0 +1,6 @@
+#ifndef _TEGRA114_POWERGATE_H_
+#define _TEGRA114_POWERGATE_H_
+
+#include <asm/arch-tegra/powergate.h>
+
+#endif /* _TEGRA114_POWERGATE_H_ */
diff --git a/arch/arm/include/asm/arch-tegra124/powergate.h b/arch/arm/include/asm/arch-tegra124/powergate.h
new file mode 100644
index 000000000000..8a0cfbaf9665
--- /dev/null
+++ b/arch/arm/include/asm/arch-tegra124/powergate.h
@@ -0,0 +1,6 @@
+#ifndef _TEGRA124_POWERGATE_H_
+#define _TEGRA124_POWERGATE_H_
+
+#include <asm/arch-tegra/powergate.h>
+
+#endif /* _TEGRA124_POWERGATE_H_ */
diff --git a/arch/arm/include/asm/arch-tegra20/powergate.h b/arch/arm/include/asm/arch-tegra20/powergate.h
new file mode 100644
index 000000000000..439d88b7022a
--- /dev/null
+++ b/arch/arm/include/asm/arch-tegra20/powergate.h
@@ -0,0 +1,6 @@
+#ifndef _TEGRA20_POWERGATE_H_
+#define _TEGRA20_POWERGATE_H_
+
+#include <asm/arch-tegra/powergate.h>
+
+#endif /* _TEGRA20_POWERGATE_H_ */
diff --git a/arch/arm/include/asm/arch-tegra30/powergate.h b/arch/arm/include/asm/arch-tegra30/powergate.h
new file mode 100644
index 000000000000..c70e44b6216d
--- /dev/null
+++ b/arch/arm/include/asm/arch-tegra30/powergate.h
@@ -0,0 +1,6 @@
+#ifndef _TEGRA30_POWERGATE_H_
+#define _TEGRA30_POWERGATE_H_
+
+#include <asm/arch-tegra/powergate.h>
+
+#endif /* _TEGRA30_POWERGATE_H_ */
-- 
2.0.4

^ permalink raw reply related	[flat|nested] 95+ messages in thread

* [U-Boot] [PATCH 12/23] ARM: tegra: Implement XUSB pad controller
  2014-08-18  7:16 [U-Boot] [PATCH 00/23] ARM: tegra: Add PCIe support Thierry Reding
                   ` (10 preceding siblings ...)
  2014-08-18  7:16 ` [U-Boot] [PATCH 11/23] ARM: tegra: Implement powergate support Thierry Reding
@ 2014-08-18  7:16 ` Thierry Reding
  2014-08-20 18:32   ` Stephen Warren
  2014-08-18  7:16 ` [U-Boot] [PATCH 13/23] ARM: tegra: Add XUSB pad controller on Tegra124 Thierry Reding
                   ` (10 subsequent siblings)
  22 siblings, 1 reply; 95+ messages in thread
From: Thierry Reding @ 2014-08-18  7:16 UTC (permalink / raw)
  To: u-boot

From: Thierry Reding <treding@nvidia.com>

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.

Signed-off-by: Thierry Reding <treding@nvidia.com>
---
 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

diff --git a/arch/arm/cpu/tegra-common/Makefile b/arch/arm/cpu/tegra-common/Makefile
index fed618ba8fc9..528ffe0a2fcc 100644
--- a/arch/arm/cpu/tegra-common/Makefile
+++ b/arch/arm/cpu/tegra-common/Makefile
@@ -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
diff --git a/arch/arm/cpu/tegra-common/xusb-padctl.c b/arch/arm/cpu/tegra-common/xusb-padctl.c
new file mode 100644
index 000000000000..2a1d860844c7
--- /dev/null
+++ b/arch/arm/cpu/tegra-common/xusb-padctl.c
@@ -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)
+{
+}
diff --git a/arch/arm/cpu/tegra124-common/Makefile b/arch/arm/cpu/tegra124-common/Makefile
index ff77992b330c..7b59fb121614 100644
--- a/arch/arm/cpu/tegra124-common/Makefile
+++ b/arch/arm/cpu/tegra124-common/Makefile
@@ -8,3 +8,4 @@
 obj-y	+= clock.o
 obj-y	+= funcmux.o
 obj-y	+= pinmux.o
+obj-y	+= xusb-padctl.o
diff --git a/arch/arm/cpu/tegra124-common/xusb-padctl.c b/arch/arm/cpu/tegra124-common/xusb-padctl.c
new file mode 100644
index 000000000000..bceacff59fb7
--- /dev/null
+++ b/arch/arm/cpu/tegra124-common/xusb-padctl.c
@@ -0,0 +1,766 @@
+/*
+ * Copyright (c) 2014, NVIDIA CORPORATION.  All rights reserved.
+ *
+ * SPDX-License-Identifier: GPL-2.0
+ */
+
+#define pr_fmt(fmt) "tegra-xusb-padctl: " fmt
+
+#include <common.h>
+#include <errno.h>
+#include <fdtdec.h>
+#include <malloc.h>
+
+#include <asm/io.h>
+
+#include <asm/arch/clock.h>
+#include <asm/arch/xusb-padctl.h>
+
+#include <dt-bindings/pinctrl/pinctrl-tegra-xusb.h>
+
+#define XUSB_PADCTL_ELPG_PROGRAM 0x01c
+#define XUSB_PADCTL_ELPG_PROGRAM_AUX_MUX_LP0_VCORE_DOWN (1 << 26)
+#define XUSB_PADCTL_ELPG_PROGRAM_AUX_MUX_LP0_CLAMP_EN_EARLY (1 << 25)
+#define XUSB_PADCTL_ELPG_PROGRAM_AUX_MUX_LP0_CLAMP_EN (1 << 24)
+
+#define XUSB_PADCTL_IOPHY_PLL_P0_CTL1 0x040
+#define XUSB_PADCTL_IOPHY_PLL_P0_CTL1_PLL0_LOCKDET (1 << 19)
+#define XUSB_PADCTL_IOPHY_PLL_P0_CTL1_REFCLK_SEL_MASK (0xf << 12)
+#define XUSB_PADCTL_IOPHY_PLL_P0_CTL1_PLL_RST (1 << 1)
+
+#define XUSB_PADCTL_IOPHY_PLL_P0_CTL2 0x044
+#define XUSB_PADCTL_IOPHY_PLL_P0_CTL2_REFCLKBUF_EN (1 << 6)
+#define XUSB_PADCTL_IOPHY_PLL_P0_CTL2_TXCLKREF_EN (1 << 5)
+#define XUSB_PADCTL_IOPHY_PLL_P0_CTL2_TXCLKREF_SEL (1 << 4)
+
+#define XUSB_PADCTL_IOPHY_PLL_S0_CTL1 0x138
+#define XUSB_PADCTL_IOPHY_PLL_S0_CTL1_PLL1_LOCKDET (1 << 27)
+#define XUSB_PADCTL_IOPHY_PLL_S0_CTL1_PLL1_MODE (1 << 24)
+#define XUSB_PADCTL_IOPHY_PLL_S0_CTL1_PLL_PWR_OVRD (1 << 3)
+#define XUSB_PADCTL_IOPHY_PLL_S0_CTL1_PLL_RST (1 << 1)
+#define XUSB_PADCTL_IOPHY_PLL_S0_CTL1_PLL_IDDQ (1 << 0)
+
+#define XUSB_PADCTL_IOPHY_MISC_PAD_S0_CTL1 0x148
+#define XUSB_PADCTL_IOPHY_MISC_PAD_S0_CTL1_IDDQ_OVRD (1 << 1)
+#define XUSB_PADCTL_IOPHY_MISC_PAD_S0_CTL1_IDDQ (1 << 0)
+
+enum tegra124_function {
+	TEGRA124_FUNC_SNPS,
+	TEGRA124_FUNC_XUSB,
+	TEGRA124_FUNC_UART,
+	TEGRA124_FUNC_PCIE,
+	TEGRA124_FUNC_USB3,
+	TEGRA124_FUNC_SATA,
+	TEGRA124_FUNC_RSVD,
+};
+
+static const char *const tegra124_functions[] = {
+	"snps",
+	"xusb",
+	"uart",
+	"pcie",
+	"usb3",
+	"sata",
+	"rsvd",
+};
+
+static const unsigned int tegra124_otg_functions[] = {
+	TEGRA124_FUNC_SNPS,
+	TEGRA124_FUNC_XUSB,
+	TEGRA124_FUNC_UART,
+	TEGRA124_FUNC_RSVD,
+};
+
+static const unsigned int tegra124_usb_functions[] = {
+	TEGRA124_FUNC_SNPS,
+	TEGRA124_FUNC_XUSB,
+};
+
+static const unsigned int tegra124_pci_functions[] = {
+	TEGRA124_FUNC_PCIE,
+	TEGRA124_FUNC_USB3,
+	TEGRA124_FUNC_SATA,
+	TEGRA124_FUNC_RSVD,
+};
+
+struct tegra_xusb_padctl_lane {
+	const char *name;
+
+	unsigned int offset;
+	unsigned int shift;
+	unsigned int mask;
+	unsigned int iddq;
+
+	const unsigned int *funcs;
+	unsigned int num_funcs;
+};
+
+#define TEGRA124_LANE(_name, _offset, _shift, _mask, _iddq, _funcs)	\
+	{								\
+		.name = _name,						\
+		.offset = _offset,					\
+		.shift = _shift,					\
+		.mask = _mask,						\
+		.iddq = _iddq,						\
+		.num_funcs = ARRAY_SIZE(tegra124_##_funcs##_functions),	\
+		.funcs = tegra124_##_funcs##_functions,			\
+	}
+
+static const struct tegra_xusb_padctl_lane tegra124_lanes[] = {
+	TEGRA124_LANE("otg-0",  0x004,  0, 0x3, 0, otg),
+	TEGRA124_LANE("otg-1",  0x004,  2, 0x3, 0, otg),
+	TEGRA124_LANE("otg-2",  0x004,  4, 0x3, 0, otg),
+	TEGRA124_LANE("ulpi-0", 0x004, 12, 0x1, 0, usb),
+	TEGRA124_LANE("hsic-0", 0x004, 14, 0x1, 0, usb),
+	TEGRA124_LANE("hsic-1", 0x004, 15, 0x1, 0, usb),
+	TEGRA124_LANE("pcie-0", 0x134, 16, 0x3, 1, pci),
+	TEGRA124_LANE("pcie-1", 0x134, 18, 0x3, 2, pci),
+	TEGRA124_LANE("pcie-2", 0x134, 20, 0x3, 3, pci),
+	TEGRA124_LANE("pcie-3", 0x134, 22, 0x3, 4, pci),
+	TEGRA124_LANE("pcie-4", 0x134, 24, 0x3, 5, pci),
+	TEGRA124_LANE("sata-0", 0x134, 26, 0x3, 6, pci),
+};
+
+struct tegra_xusb_phy_ops {
+	int (*prepare)(struct tegra_xusb_phy *phy);
+	int (*enable)(struct tegra_xusb_phy *phy);
+	int (*disable)(struct tegra_xusb_phy *phy);
+	int (*unprepare)(struct tegra_xusb_phy *phy);
+};
+
+struct tegra_xusb_phy {
+	const struct tegra_xusb_phy_ops *ops;
+
+	struct tegra_xusb_padctl *padctl;
+};
+
+struct tegra_xusb_padctl_pin {
+	const struct tegra_xusb_padctl_lane *lane;
+
+	unsigned int func;
+	int iddq;
+};
+
+#define MAX_GROUPS 3
+#define MAX_PINS 6
+
+struct tegra_xusb_padctl_group {
+	const char *name;
+
+	const char *pins[MAX_PINS];
+	unsigned int num_pins;
+
+	const char *func;
+	int iddq;
+};
+
+struct tegra_xusb_padctl_config {
+	const char *name;
+
+	struct tegra_xusb_padctl_group groups[MAX_GROUPS];
+	unsigned int num_groups;
+};
+
+struct tegra_xusb_padctl {
+	struct fdt_resource regs;
+
+	unsigned int enable;
+
+	struct tegra_xusb_phy phys[2];
+
+	const struct tegra_xusb_padctl_lane *lanes;
+	unsigned int num_lanes;
+
+	const char *const *functions;
+	unsigned int num_functions;
+
+	struct tegra_xusb_padctl_config config;
+};
+
+static inline u32 padctl_readl(struct tegra_xusb_padctl *padctl,
+			       unsigned long offset)
+{
+	return readl(padctl->regs.start + offset);
+}
+
+static inline void padctl_writel(struct tegra_xusb_padctl *padctl,
+				 u32 value, unsigned long offset)
+{
+	writel(value, padctl->regs.start + offset);
+}
+
+static int tegra_xusb_padctl_enable(struct tegra_xusb_padctl *padctl)
+{
+	u32 value;
+
+	if (padctl->enable++ > 0)
+		return 0;
+
+	value = padctl_readl(padctl, XUSB_PADCTL_ELPG_PROGRAM);
+	value &= ~XUSB_PADCTL_ELPG_PROGRAM_AUX_MUX_LP0_CLAMP_EN;
+	padctl_writel(padctl, value, XUSB_PADCTL_ELPG_PROGRAM);
+
+	udelay(100);
+
+	value = padctl_readl(padctl, XUSB_PADCTL_ELPG_PROGRAM);
+	value &= ~XUSB_PADCTL_ELPG_PROGRAM_AUX_MUX_LP0_CLAMP_EN_EARLY;
+	padctl_writel(padctl, value, XUSB_PADCTL_ELPG_PROGRAM);
+
+	udelay(100);
+
+	value = padctl_readl(padctl, XUSB_PADCTL_ELPG_PROGRAM);
+	value &= ~XUSB_PADCTL_ELPG_PROGRAM_AUX_MUX_LP0_VCORE_DOWN;
+	padctl_writel(padctl, value, XUSB_PADCTL_ELPG_PROGRAM);
+
+	return 0;
+}
+
+static int tegra_xusb_padctl_disable(struct tegra_xusb_padctl *padctl)
+{
+	u32 value;
+
+	if (padctl->enable == 0) {
+		error("tegra-xusb-padctl: unbalanced enable/disable");
+		return 0;
+	}
+
+	if (--padctl->enable > 0)
+		return 0;
+
+	value = padctl_readl(padctl, XUSB_PADCTL_ELPG_PROGRAM);
+	value |= XUSB_PADCTL_ELPG_PROGRAM_AUX_MUX_LP0_VCORE_DOWN;
+	padctl_writel(padctl, value, XUSB_PADCTL_ELPG_PROGRAM);
+
+	udelay(100);
+
+	value = padctl_readl(padctl, XUSB_PADCTL_ELPG_PROGRAM);
+	value |= XUSB_PADCTL_ELPG_PROGRAM_AUX_MUX_LP0_CLAMP_EN_EARLY;
+	padctl_writel(padctl, value, XUSB_PADCTL_ELPG_PROGRAM);
+
+	udelay(100);
+
+	value = padctl_readl(padctl, XUSB_PADCTL_ELPG_PROGRAM);
+	value |= XUSB_PADCTL_ELPG_PROGRAM_AUX_MUX_LP0_CLAMP_EN;
+	padctl_writel(padctl, value, XUSB_PADCTL_ELPG_PROGRAM);
+
+	return 0;
+}
+
+static int phy_prepare(struct tegra_xusb_phy *phy)
+{
+	return tegra_xusb_padctl_enable(phy->padctl);
+}
+
+static int phy_unprepare(struct tegra_xusb_phy *phy)
+{
+	return tegra_xusb_padctl_disable(phy->padctl);
+}
+
+static int pcie_phy_enable(struct tegra_xusb_phy *phy)
+{
+	struct tegra_xusb_padctl *padctl = phy->padctl;
+	int err = -ETIMEDOUT;
+	unsigned long start;
+	u32 value;
+
+	value = padctl_readl(padctl, XUSB_PADCTL_IOPHY_PLL_P0_CTL1);
+	value &= ~XUSB_PADCTL_IOPHY_PLL_P0_CTL1_REFCLK_SEL_MASK;
+	padctl_writel(padctl, value, XUSB_PADCTL_IOPHY_PLL_P0_CTL1);
+
+	value = padctl_readl(padctl, XUSB_PADCTL_IOPHY_PLL_P0_CTL2);
+	value |= XUSB_PADCTL_IOPHY_PLL_P0_CTL2_REFCLKBUF_EN |
+		 XUSB_PADCTL_IOPHY_PLL_P0_CTL2_TXCLKREF_EN |
+		 XUSB_PADCTL_IOPHY_PLL_P0_CTL2_TXCLKREF_SEL;
+	padctl_writel(padctl, value, XUSB_PADCTL_IOPHY_PLL_P0_CTL2);
+
+	value = padctl_readl(padctl, XUSB_PADCTL_IOPHY_PLL_P0_CTL1);
+	value |= XUSB_PADCTL_IOPHY_PLL_P0_CTL1_PLL_RST;
+	padctl_writel(padctl, value, XUSB_PADCTL_IOPHY_PLL_P0_CTL1);
+
+	start = get_timer(0);
+
+	while (get_timer(start) < 50) {
+		value = padctl_readl(padctl, XUSB_PADCTL_IOPHY_PLL_P0_CTL1);
+		if (value & XUSB_PADCTL_IOPHY_PLL_P0_CTL1_PLL0_LOCKDET) {
+			err = 0;
+			break;
+		}
+	}
+
+	return err;
+}
+
+static int pcie_phy_disable(struct tegra_xusb_phy *phy)
+{
+	struct tegra_xusb_padctl *padctl = phy->padctl;
+	u32 value;
+
+	value = padctl_readl(padctl, XUSB_PADCTL_IOPHY_PLL_P0_CTL1);
+	value &= ~XUSB_PADCTL_IOPHY_PLL_P0_CTL1_PLL_RST;
+	padctl_writel(padctl, value, XUSB_PADCTL_IOPHY_PLL_P0_CTL1);
+
+	return 0;
+}
+
+static int sata_phy_enable(struct tegra_xusb_phy *phy)
+{
+	struct tegra_xusb_padctl *padctl = phy->padctl;
+	int err = -ETIMEDOUT;
+	unsigned long start;
+	u32 value;
+
+	value = padctl_readl(padctl, XUSB_PADCTL_IOPHY_MISC_PAD_S0_CTL1);
+	value &= ~XUSB_PADCTL_IOPHY_MISC_PAD_S0_CTL1_IDDQ_OVRD;
+	value &= ~XUSB_PADCTL_IOPHY_MISC_PAD_S0_CTL1_IDDQ;
+	padctl_writel(padctl, value, XUSB_PADCTL_IOPHY_MISC_PAD_S0_CTL1);
+
+	value = padctl_readl(padctl, XUSB_PADCTL_IOPHY_PLL_S0_CTL1);
+	value &= ~XUSB_PADCTL_IOPHY_PLL_S0_CTL1_PLL_PWR_OVRD;
+	value &= ~XUSB_PADCTL_IOPHY_PLL_S0_CTL1_PLL_IDDQ;
+	padctl_writel(padctl, value, XUSB_PADCTL_IOPHY_PLL_S0_CTL1);
+
+	value = padctl_readl(padctl, XUSB_PADCTL_IOPHY_PLL_S0_CTL1);
+	value |= XUSB_PADCTL_IOPHY_PLL_S0_CTL1_PLL1_MODE;
+	padctl_writel(padctl, value, XUSB_PADCTL_IOPHY_PLL_S0_CTL1);
+
+	value = padctl_readl(padctl, XUSB_PADCTL_IOPHY_PLL_S0_CTL1);
+	value |= XUSB_PADCTL_IOPHY_PLL_S0_CTL1_PLL_RST;
+	padctl_writel(padctl, value, XUSB_PADCTL_IOPHY_PLL_S0_CTL1);
+
+	start = get_timer(0);
+
+	while (get_timer(start) < 50) {
+		value = padctl_readl(padctl, XUSB_PADCTL_IOPHY_PLL_S0_CTL1);
+		if (value & XUSB_PADCTL_IOPHY_PLL_S0_CTL1_PLL1_LOCKDET) {
+			err = 0;
+			break;
+		}
+	}
+
+	return err;
+}
+
+static int sata_phy_disable(struct tegra_xusb_phy *phy)
+{
+	struct tegra_xusb_padctl *padctl = phy->padctl;
+	u32 value;
+
+	value = padctl_readl(padctl, XUSB_PADCTL_IOPHY_PLL_S0_CTL1);
+	value &= ~XUSB_PADCTL_IOPHY_PLL_S0_CTL1_PLL_RST;
+	padctl_writel(padctl, value, XUSB_PADCTL_IOPHY_PLL_S0_CTL1);
+
+	value = padctl_readl(padctl, XUSB_PADCTL_IOPHY_PLL_S0_CTL1);
+	value &= ~XUSB_PADCTL_IOPHY_PLL_S0_CTL1_PLL1_MODE;
+	padctl_writel(padctl, value, XUSB_PADCTL_IOPHY_PLL_S0_CTL1);
+
+	value = padctl_readl(padctl, XUSB_PADCTL_IOPHY_PLL_S0_CTL1);
+	value |= XUSB_PADCTL_IOPHY_PLL_S0_CTL1_PLL_PWR_OVRD;
+	value |= XUSB_PADCTL_IOPHY_PLL_S0_CTL1_PLL_IDDQ;
+	padctl_writel(padctl, value, XUSB_PADCTL_IOPHY_PLL_S0_CTL1);
+
+	value = padctl_readl(padctl, XUSB_PADCTL_IOPHY_MISC_PAD_S0_CTL1);
+	value |= ~XUSB_PADCTL_IOPHY_MISC_PAD_S0_CTL1_IDDQ_OVRD;
+	value |= ~XUSB_PADCTL_IOPHY_MISC_PAD_S0_CTL1_IDDQ;
+	padctl_writel(padctl, value, XUSB_PADCTL_IOPHY_MISC_PAD_S0_CTL1);
+
+	return 0;
+}
+
+static const struct tegra_xusb_phy_ops pcie_phy_ops = {
+	.prepare = phy_prepare,
+	.enable = pcie_phy_enable,
+	.disable = pcie_phy_disable,
+	.unprepare = phy_unprepare,
+};
+
+static const struct tegra_xusb_phy_ops sata_phy_ops = {
+	.prepare = phy_prepare,
+	.enable = sata_phy_enable,
+	.disable = sata_phy_disable,
+	.unprepare = phy_unprepare,
+};
+
+static struct tegra_xusb_padctl *padctl = &(struct tegra_xusb_padctl) {
+	.phys = {
+		[0] = {
+			.ops = &pcie_phy_ops,
+		},
+		[1] = {
+			.ops = &sata_phy_ops,
+		},
+	},
+};
+
+int fdtdec_count_strings(const void *fdt, int node, const char *prop_name)
+{
+	int length, i, count = 0;
+	const char *list;
+
+	list = fdt_getprop(fdt, node, prop_name, &length);
+	if (!list)
+		return -length;
+
+	for (i = 0; i < length; i++) {
+		int len = strlen(list);
+
+		list += len + 1;
+		i += len;
+		count++;
+	}
+
+	return count;
+}
+
+int fdtdec_get_string_index(const void *fdt, int node, const char *prop_name,
+			    int index, const char **output)
+{
+	const char *list;
+	int length, i;
+
+	list = fdt_getprop(fdt, node, prop_name, &length);
+
+	for (i = 0; i < length; i++) {
+		int len = strlen(list);
+
+		if (index == 0) {
+			*output = list;
+			return 0;
+		}
+
+		list += len + 1;
+		i += len;
+		index--;
+	}
+
+	return FDT_ERR_NOTFOUND;
+}
+
+int fdtdec_get_string(const void *fdt, int node, const char *prop_name,
+		      const char **output)
+{
+	return fdtdec_get_string_index(fdt, node, prop_name, 0, output);
+}
+
+static const struct tegra_xusb_padctl_lane *
+tegra_xusb_padctl_find_lane(struct tegra_xusb_padctl *padctl, const char *name)
+{
+	unsigned int i;
+
+	for (i = 0; i < padctl->num_lanes; i++)
+		if (strcmp(name, padctl->lanes[i].name) == 0)
+			return &padctl->lanes[i];
+
+	return NULL;
+}
+
+static int
+tegra_xusb_padctl_group_parse_dt(struct tegra_xusb_padctl *padctl,
+				 struct tegra_xusb_padctl_group *group,
+				 const void *fdt, int node)
+{
+	unsigned int i;
+	int len, err;
+
+	group->name = fdt_get_name(fdt, node, &len);
+
+	len = fdtdec_count_strings(fdt, node, "nvidia,lanes");
+	if (len < 0) {
+		error("tegra-xusb-padctl: failed to parse \"nvidia,lanes\" property");
+		return -EINVAL;
+	}
+
+	group->num_pins = len;
+
+	for (i = 0; i < group->num_pins; i++) {
+		err = fdtdec_get_string_index(fdt, node, "nvidia,lanes", i,
+					      &group->pins[i]);
+		if (err < 0) {
+			error("tegra-xusb-padctl: failed to read string from \"nvidia,lanes\" property");
+			return -EINVAL;
+		}
+	}
+
+	group->num_pins = len;
+
+	err = fdtdec_get_string(fdt, node, "nvidia,function", &group->func);
+	if (err < 0) {
+		error("tegra-xusb-padctl: failed to parse \"nvidia,func\" property");
+		return -EINVAL;
+	}
+
+	group->iddq = fdtdec_get_int(fdt, node, "nvidia,iddq", -1);
+
+	return 0;
+}
+
+static int tegra_xusb_padctl_find_function(struct tegra_xusb_padctl *padctl,
+					   const char *name)
+{
+	unsigned int i;
+
+	for (i = 0; i < padctl->num_functions; i++)
+		if (strcmp(name, padctl->functions[i]) == 0)
+			return i;
+
+	return -ENOENT;
+}
+
+static int
+tegra_xusb_padctl_lane_find_function(struct tegra_xusb_padctl *padctl,
+				     const struct tegra_xusb_padctl_lane *lane,
+				     const char *name)
+{
+	unsigned int i;
+	int func;
+
+	func = tegra_xusb_padctl_find_function(padctl, name);
+	if (func < 0)
+		return func;
+
+	for (i = 0; i < lane->num_funcs; i++)
+		if (lane->funcs[i] == func)
+			return i;
+
+	return -ENOENT;
+}
+
+static int
+tegra_xusb_padctl_group_apply(struct tegra_xusb_padctl *padctl,
+			      const struct tegra_xusb_padctl_group *group)
+{
+	unsigned int i;
+
+	for (i = 0; i < group->num_pins; i++) {
+		const struct tegra_xusb_padctl_lane *lane;
+		unsigned int func;
+		u32 value;
+
+		lane = tegra_xusb_padctl_find_lane(padctl, group->pins[i]);
+		if (!lane) {
+			error("tegra-xusb-padctl: no lane for pin %s",
+			      group->pins[i]);
+			continue;
+		}
+
+		func = tegra_xusb_padctl_lane_find_function(padctl, lane,
+							    group->func);
+		if (func < 0) {
+			error("tegra-xusb-padctl: function %s invalid for lane %s: %d",
+			      group->func, lane->name, func);
+			continue;
+		}
+
+		value = padctl_readl(padctl, lane->offset);
+
+		/* set pin function */
+		value &= ~(lane->mask << lane->shift);
+		value |= func << lane->shift;
+
+		/*
+		 * Set IDDQ if supported on the lane and specified in the
+		 * configuration.
+		 */
+		if (lane->iddq > 0 && group->iddq >= 0) {
+			if (group->iddq != 0)
+				value &= ~(1 << lane->iddq);
+			else
+				value |= 1 << lane->iddq;
+		}
+
+		padctl_writel(padctl, value, lane->offset);
+	}
+
+	return 0;
+}
+
+static int
+tegra_xusb_padctl_config_apply(struct tegra_xusb_padctl *padctl,
+			       struct tegra_xusb_padctl_config *config)
+{
+	unsigned int i;
+
+	for (i = 0; i < config->num_groups; i++) {
+		const struct tegra_xusb_padctl_group *group;
+		int err;
+
+		group = &config->groups[i];
+
+		err = tegra_xusb_padctl_group_apply(padctl, group);
+		if (err < 0) {
+			error("tegra-xusb-padctl: failed to apply group %s: %d",
+			      group->name, err);
+			continue;
+		}
+	}
+
+	return 0;
+}
+
+static int
+tegra_xusb_padctl_config_parse_dt(struct tegra_xusb_padctl *padctl,
+				  struct tegra_xusb_padctl_config *config,
+				  const void *fdt, int node)
+{
+	int subnode;
+
+	config->name = fdt_get_name(fdt, node, NULL);
+
+	fdt_for_each_subnode(fdt, subnode, node) {
+		struct tegra_xusb_padctl_group *group;
+		int err;
+
+		group = &config->groups[config->num_groups];
+
+		err = tegra_xusb_padctl_group_parse_dt(padctl, group, fdt,
+						       subnode);
+		if (err < 0) {
+			error("tegra-xusb-padctl: failed to parse group %s",
+			      group->name);
+			return err;
+		}
+
+		config->num_groups++;
+	}
+
+	return 0;
+}
+
+static int tegra_xusb_padctl_parse_dt(struct tegra_xusb_padctl *padctl,
+				      const void *fdt, int node)
+{
+	int subnode, err;
+
+	err = fdt_get_resource(fdt, node, "reg", 0, &padctl->regs);
+	if (err < 0) {
+		error("tegra-xusb-padctl: registers not found");
+		return err;
+	}
+
+	fdt_for_each_subnode(fdt, subnode, node) {
+		struct tegra_xusb_padctl_config *config = &padctl->config;
+
+		err = tegra_xusb_padctl_config_parse_dt(padctl, config, fdt,
+							subnode);
+		if (err < 0) {
+			error("tegra-xusb-padctl: failed to parse entry %s: %d",
+			      config->name, err);
+			continue;
+		}
+	}
+
+	return 0;
+}
+
+static int process_nodes(const void *fdt, int nodes[], unsigned int count)
+{
+	unsigned int i;
+
+	for (i = 0; i < count; i++) {
+		enum fdt_compat_id id;
+		int err;
+
+		if (!fdtdec_get_is_enabled(fdt, nodes[i]))
+			continue;
+
+		id = fdtdec_lookup(fdt, nodes[i]);
+		switch (id) {
+		case COMPAT_NVIDIA_TEGRA124_XUSB_PADCTL:
+			break;
+
+		default:
+			error("tegra-xusb-padctl: unsupported compatible: %s",
+			      fdtdec_get_compatible(id));
+			continue;
+		}
+
+		padctl->num_lanes = ARRAY_SIZE(tegra124_lanes);
+		padctl->lanes = tegra124_lanes;
+
+		padctl->num_functions = ARRAY_SIZE(tegra124_functions);
+		padctl->functions = tegra124_functions;
+
+		err = tegra_xusb_padctl_parse_dt(padctl, fdt, nodes[i]);
+		if (err < 0) {
+			error("tegra-xusb-padctl: failed to parse DT: %d",
+			      err);
+			continue;
+		}
+
+		/* deassert XUSB padctl reset */
+		reset_set_enable(PERIPH_ID_XUSB_PADCTL, 0);
+
+		err = tegra_xusb_padctl_config_apply(padctl, &padctl->config);
+		if (err < 0) {
+			error("tegra-xusb-padctl: failed to apply pinmux: %d",
+			      err);
+			continue;
+		}
+
+		/* only a single instance is supported */
+		break;
+	}
+
+	return 0;
+}
+
+struct tegra_xusb_phy *tegra_xusb_phy_get(unsigned int type)
+{
+	struct tegra_xusb_phy *phy = NULL;
+
+	switch (type) {
+	case TEGRA_XUSB_PADCTL_PCIE:
+		phy = &padctl->phys[0];
+		phy->padctl = padctl;
+		break;
+
+	case TEGRA_XUSB_PADCTL_SATA:
+		phy = &padctl->phys[1];
+		phy->padctl = padctl;
+		break;
+	}
+
+	return phy;
+}
+
+int tegra_xusb_phy_prepare(struct tegra_xusb_phy *phy)
+{
+	if (phy && phy->ops && phy->ops->prepare)
+		return phy->ops->prepare(phy);
+
+	return phy ? -ENOSYS : -EINVAL;
+}
+
+int tegra_xusb_phy_enable(struct tegra_xusb_phy *phy)
+{
+	if (phy && phy->ops && phy->ops->enable)
+		return phy->ops->enable(phy);
+
+	return phy ? -ENOSYS : -EINVAL;
+}
+
+int tegra_xusb_phy_disable(struct tegra_xusb_phy *phy)
+{
+	if (phy && phy->ops && phy->ops->disable)
+		return phy->ops->disable(phy);
+
+	return phy ? -ENOSYS : -EINVAL;
+}
+
+int tegra_xusb_phy_unprepare(struct tegra_xusb_phy *phy)
+{
+	if (phy && phy->ops && phy->ops->unprepare)
+		return phy->ops->unprepare(phy);
+
+	return phy ? -ENOSYS : -EINVAL;
+}
+
+void tegra_xusb_padctl_init(const void *fdt)
+{
+	int count, nodes[1];
+
+	count = fdtdec_find_aliases_for_id(fdt, "padctl",
+					   COMPAT_NVIDIA_TEGRA124_XUSB_PADCTL,
+					   nodes, ARRAY_SIZE(nodes));
+	if (process_nodes(fdt, nodes, count))
+		return;
+}
diff --git a/arch/arm/include/asm/arch-tegra/xusb-padctl.h b/arch/arm/include/asm/arch-tegra/xusb-padctl.h
new file mode 100644
index 000000000000..39d01ae0132e
--- /dev/null
+++ b/arch/arm/include/asm/arch-tegra/xusb-padctl.h
@@ -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
diff --git a/arch/arm/include/asm/arch-tegra114/xusb-padctl.h b/arch/arm/include/asm/arch-tegra114/xusb-padctl.h
new file mode 100644
index 000000000000..2b5c5ff4c912
--- /dev/null
+++ b/arch/arm/include/asm/arch-tegra114/xusb-padctl.h
@@ -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_ */
diff --git a/arch/arm/include/asm/arch-tegra124/xusb-padctl.h b/arch/arm/include/asm/arch-tegra124/xusb-padctl.h
new file mode 100644
index 000000000000..90a9d8042391
--- /dev/null
+++ b/arch/arm/include/asm/arch-tegra124/xusb-padctl.h
@@ -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_ */
diff --git a/arch/arm/include/asm/arch-tegra20/xusb-padctl.h b/arch/arm/include/asm/arch-tegra20/xusb-padctl.h
new file mode 100644
index 000000000000..8204dcdc696b
--- /dev/null
+++ b/arch/arm/include/asm/arch-tegra20/xusb-padctl.h
@@ -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_ */
diff --git a/arch/arm/include/asm/arch-tegra30/xusb-padctl.h b/arch/arm/include/asm/arch-tegra30/xusb-padctl.h
new file mode 100644
index 000000000000..ed429963a3a5
--- /dev/null
+++ b/arch/arm/include/asm/arch-tegra30/xusb-padctl.h
@@ -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_ */
diff --git a/board/nvidia/common/board.c b/board/nvidia/common/board.c
index d01abcee13c1..ba6417c5f535 100644
--- a/board/nvidia/common/board.c
+++ b/board/nvidia/common/board.c
@@ -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();
diff --git a/include/dt-bindings/pinctrl/pinctrl-tegra-xusb.h b/include/dt-bindings/pinctrl/pinctrl-tegra-xusb.h
new file mode 100644
index 000000000000..914d56da9324
--- /dev/null
+++ b/include/dt-bindings/pinctrl/pinctrl-tegra-xusb.h
@@ -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 */
diff --git a/include/fdtdec.h b/include/fdtdec.h
index 56bc29375128..c0464f07961d 100644
--- a/include/fdtdec.h
+++ b/include/fdtdec.h
@@ -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 */
diff --git a/lib/fdtdec.c b/lib/fdtdec.c
index d2f2c9164b37..16e0714b0fed 100644
--- a/lib/fdtdec.c
+++ b/lib/fdtdec.c
@@ -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"),
-- 
2.0.4

^ permalink raw reply related	[flat|nested] 95+ messages in thread

* [U-Boot] [PATCH 13/23] ARM: tegra: Add XUSB pad controller on Tegra124
  2014-08-18  7:16 [U-Boot] [PATCH 00/23] ARM: tegra: Add PCIe support Thierry Reding
                   ` (11 preceding siblings ...)
  2014-08-18  7:16 ` [U-Boot] [PATCH 12/23] ARM: tegra: Implement XUSB pad controller Thierry Reding
@ 2014-08-18  7:16 ` Thierry Reding
  2014-08-20 18:33   ` Stephen Warren
  2014-08-18  7:16 ` [U-Boot] [PATCH 14/23] ARM: tegra: Enable XUSB pad controller on Jetson TK1 Thierry Reding
                   ` (9 subsequent siblings)
  22 siblings, 1 reply; 95+ messages in thread
From: Thierry Reding @ 2014-08-18  7:16 UTC (permalink / raw)
  To: u-boot

From: Thierry Reding <treding@nvidia.com>

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

Signed-off-by: Thierry Reding <treding@nvidia.com>
---
 arch/arm/dts/tegra124.dtsi | 10 ++++++++++
 1 file changed, 10 insertions(+)

diff --git a/arch/arm/dts/tegra124.dtsi b/arch/arm/dts/tegra124.dtsi
index 4561c5f83943..d48f1a34ec3c 100644
--- a/arch/arm/dts/tegra124.dtsi
+++ b/arch/arm/dts/tegra124.dtsi
@@ -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>;
-- 
2.0.4

^ permalink raw reply related	[flat|nested] 95+ messages in thread

* [U-Boot] [PATCH 14/23] ARM: tegra: Enable XUSB pad controller on Jetson TK1
  2014-08-18  7:16 [U-Boot] [PATCH 00/23] ARM: tegra: Add PCIe support Thierry Reding
                   ` (12 preceding siblings ...)
  2014-08-18  7:16 ` [U-Boot] [PATCH 13/23] ARM: tegra: Add XUSB pad controller on Tegra124 Thierry Reding
@ 2014-08-18  7:16 ` Thierry Reding
  2014-08-20 18:34   ` Stephen Warren
  2014-08-18  7:16 ` [U-Boot] [PATCH 15/23] pci: tegra: Add Tegra PCIe driver Thierry Reding
                   ` (8 subsequent siblings)
  22 siblings, 1 reply; 95+ messages in thread
From: Thierry Reding @ 2014-08-18  7:16 UTC (permalink / raw)
  To: u-boot

From: Thierry Reding <treding@nvidia.com>

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

Signed-off-by: Thierry Reding <treding@nvidia.com>
---
 arch/arm/dts/tegra124-jetson-tk1.dts | 26 ++++++++++++++++++++++++++
 1 file changed, 26 insertions(+)

diff --git a/arch/arm/dts/tegra124-jetson-tk1.dts b/arch/arm/dts/tegra124-jetson-tk1.dts
index 464287e03ecf..f61736f0ef0f 100644
--- a/arch/arm/dts/tegra124-jetson-tk1.dts
+++ b/arch/arm/dts/tegra124-jetson-tk1.dts
@@ -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 */
-- 
2.0.4

^ permalink raw reply related	[flat|nested] 95+ messages in thread

* [U-Boot] [PATCH 15/23] pci: tegra: Add Tegra PCIe driver
  2014-08-18  7:16 [U-Boot] [PATCH 00/23] ARM: tegra: Add PCIe support Thierry Reding
                   ` (13 preceding siblings ...)
  2014-08-18  7:16 ` [U-Boot] [PATCH 14/23] ARM: tegra: Enable XUSB pad controller on Jetson TK1 Thierry Reding
@ 2014-08-18  7:16 ` Thierry Reding
  2014-08-20 19:04   ` Stephen Warren
  2014-08-18  7:16 ` [U-Boot] [PATCH 16/23] ARM: tegra: Add Tegra20 PCIe device tree node Thierry Reding
                   ` (7 subsequent siblings)
  22 siblings, 1 reply; 95+ messages in thread
From: Thierry Reding @ 2014-08-18  7:16 UTC (permalink / raw)
  To: u-boot

From: Thierry Reding <treding@nvidia.com>

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.

Signed-off-by: Thierry Reding <treding@nvidia.com>
---
 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

diff --git a/drivers/pci/Makefile b/drivers/pci/Makefile
index e73a49861983..8eb2320539f9 100644
--- a/drivers/pci/Makefile
+++ b/drivers/pci/Makefile
@@ -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
diff --git a/drivers/pci/pci_tegra.c b/drivers/pci/pci_tegra.c
new file mode 100644
index 000000000000..3316ef34e092
--- /dev/null
+++ b/drivers/pci/pci_tegra.c
@@ -0,0 +1,1133 @@
+/*
+ * Copyright (c) 2010, CompuLab, Ltd.
+ * Author: Mike Rapoport <mike@compulab.co.il>
+ *
+ * Based on NVIDIA PCIe driver
+ * Copyright (c) 2008-2009, NVIDIA Corporation.
+ *
+ * SPDX-License-Identifier:	GPL-2.0
+ */
+
+#define DEBUG
+#define pr_fmt(fmt) "tegra-pcie: " fmt
+
+#include <common.h>
+#include <errno.h>
+#include <fdtdec.h>
+#include <malloc.h>
+#include <pci.h>
+
+#include <asm/io.h>
+#include <asm/gpio.h>
+
+#include <asm/arch/clock.h>
+#include <asm/arch/powergate.h>
+#include <asm/arch/xusb-padctl.h>
+
+#include <linux/list.h>
+
+#include <dt-bindings/pinctrl/pinctrl-tegra-xusb.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+#define AFI_AXI_BAR0_SZ	0x00
+#define AFI_AXI_BAR1_SZ	0x04
+#define AFI_AXI_BAR2_SZ	0x08
+#define AFI_AXI_BAR3_SZ	0x0c
+#define AFI_AXI_BAR4_SZ	0x10
+#define AFI_AXI_BAR5_SZ	0x14
+
+#define AFI_AXI_BAR0_START	0x18
+#define AFI_AXI_BAR1_START	0x1c
+#define AFI_AXI_BAR2_START	0x20
+#define AFI_AXI_BAR3_START	0x24
+#define AFI_AXI_BAR4_START	0x28
+#define AFI_AXI_BAR5_START	0x2c
+
+#define AFI_FPCI_BAR0	0x30
+#define AFI_FPCI_BAR1	0x34
+#define AFI_FPCI_BAR2	0x38
+#define AFI_FPCI_BAR3	0x3c
+#define AFI_FPCI_BAR4	0x40
+#define AFI_FPCI_BAR5	0x44
+
+#define AFI_CACHE_BAR0_SZ	0x48
+#define AFI_CACHE_BAR0_ST	0x4c
+#define AFI_CACHE_BAR1_SZ	0x50
+#define AFI_CACHE_BAR1_ST	0x54
+
+#define AFI_MSI_BAR_SZ		0x60
+#define AFI_MSI_FPCI_BAR_ST	0x64
+#define AFI_MSI_AXI_BAR_ST	0x68
+
+#define AFI_CONFIGURATION		0xac
+#define  AFI_CONFIGURATION_EN_FPCI	(1 << 0)
+
+#define AFI_FPCI_ERROR_MASKS	0xb0
+
+#define AFI_INTR_MASK		0xb4
+#define  AFI_INTR_MASK_INT_MASK	(1 << 0)
+#define  AFI_INTR_MASK_MSI_MASK	(1 << 8)
+
+#define AFI_SM_INTR_ENABLE	0xc4
+#define  AFI_SM_INTR_INTA_ASSERT	(1 << 0)
+#define  AFI_SM_INTR_INTB_ASSERT	(1 << 1)
+#define  AFI_SM_INTR_INTC_ASSERT	(1 << 2)
+#define  AFI_SM_INTR_INTD_ASSERT	(1 << 3)
+#define  AFI_SM_INTR_INTA_DEASSERT	(1 << 4)
+#define  AFI_SM_INTR_INTB_DEASSERT	(1 << 5)
+#define  AFI_SM_INTR_INTC_DEASSERT	(1 << 6)
+#define  AFI_SM_INTR_INTD_DEASSERT	(1 << 7)
+
+#define AFI_AFI_INTR_ENABLE		0xc8
+#define  AFI_INTR_EN_INI_SLVERR		(1 << 0)
+#define  AFI_INTR_EN_INI_DECERR		(1 << 1)
+#define  AFI_INTR_EN_TGT_SLVERR		(1 << 2)
+#define  AFI_INTR_EN_TGT_DECERR		(1 << 3)
+#define  AFI_INTR_EN_TGT_WRERR		(1 << 4)
+#define  AFI_INTR_EN_DFPCI_DECERR	(1 << 5)
+#define  AFI_INTR_EN_AXI_DECERR		(1 << 6)
+#define  AFI_INTR_EN_FPCI_TIMEOUT	(1 << 7)
+#define  AFI_INTR_EN_PRSNT_SENSE	(1 << 8)
+
+#define AFI_PCIE_CONFIG					0x0f8
+#define  AFI_PCIE_CONFIG_PCIE_DISABLE(x)		(1 << ((x) + 1))
+#define  AFI_PCIE_CONFIG_PCIE_DISABLE_ALL		0xe
+#define  AFI_PCIE_CONFIG_SM2TMS0_XBAR_CONFIG_MASK	(0xf << 20)
+#define  AFI_PCIE_CONFIG_SM2TMS0_XBAR_CONFIG_SINGLE	(0x0 << 20)
+#define  AFI_PCIE_CONFIG_SM2TMS0_XBAR_CONFIG_420	(0x0 << 20)
+#define  AFI_PCIE_CONFIG_SM2TMS0_XBAR_CONFIG_X2_X1	(0x0 << 20)
+#define  AFI_PCIE_CONFIG_SM2TMS0_XBAR_CONFIG_DUAL	(0x1 << 20)
+#define  AFI_PCIE_CONFIG_SM2TMS0_XBAR_CONFIG_222	(0x1 << 20)
+#define  AFI_PCIE_CONFIG_SM2TMS0_XBAR_CONFIG_X4_X1	(0x1 << 20)
+#define  AFI_PCIE_CONFIG_SM2TMS0_XBAR_CONFIG_411	(0x2 << 20)
+
+#define AFI_FUSE			0x104
+#define  AFI_FUSE_PCIE_T0_GEN2_DIS	(1 << 2)
+
+#define AFI_PEX0_CTRL			0x110
+#define AFI_PEX1_CTRL			0x118
+#define AFI_PEX2_CTRL			0x128
+#define  AFI_PEX_CTRL_RST		(1 << 0)
+#define  AFI_PEX_CTRL_CLKREQ_EN		(1 << 1)
+#define  AFI_PEX_CTRL_REFCLK_EN		(1 << 3)
+#define  AFI_PEX_CTRL_OVERRIDE_EN	(1 << 4)
+
+#define AFI_PLLE_CONTROL		0x160
+#define  AFI_PLLE_CONTROL_BYPASS_PADS2PLLE_CONTROL (1 << 9)
+#define  AFI_PLLE_CONTROL_PADS2PLLE_CONTROL_EN (1 << 1)
+
+#define AFI_PEXBIAS_CTRL_0		0x168
+
+#define PADS_CTL_SEL		0x0000009C
+
+#define PADS_CTL		0x000000A0
+#define  PADS_CTL_IDDQ_1L	(1 <<  0)
+#define  PADS_CTL_TX_DATA_EN_1L	(1 <<  6)
+#define  PADS_CTL_RX_DATA_EN_1L	(1 << 10)
+
+#define PADS_PLL_CTL_TEGRA20			0x000000B8
+#define PADS_PLL_CTL_TEGRA30			0x000000B4
+#define  PADS_PLL_CTL_RST_B4SM			(0x1 <<  1)
+#define  PADS_PLL_CTL_LOCKDET			(0x1 <<  8)
+#define  PADS_PLL_CTL_REFCLK_MASK		(0x3 << 16)
+#define  PADS_PLL_CTL_REFCLK_INTERNAL_CML	(0x0 << 16)
+#define  PADS_PLL_CTL_REFCLK_INTERNAL_CMOS	(0x1 << 16)
+#define  PADS_PLL_CTL_REFCLK_EXTERNAL		(0x2 << 16)
+#define  PADS_PLL_CTL_TXCLKREF_MASK		(0x1 << 20)
+#define  PADS_PLL_CTL_TXCLKREF_DIV10		(0x0 << 20)
+#define  PADS_PLL_CTL_TXCLKREF_DIV5		(0x1 << 20)
+#define  PADS_PLL_CTL_TXCLKREF_BUF_EN		(0x1 << 22)
+
+#define PADS_REFCLK_CFG0			0x000000C8
+#define PADS_REFCLK_CFG1			0x000000CC
+
+/*
+ * Fields in PADS_REFCLK_CFG*. Those registers form an array of 16-bit
+ * entries, one entry per PCIe port. These field definitions and desired
+ * values aren't in the TRM, but do come from NVIDIA.
+ */
+#define PADS_REFCLK_CFG_TERM_SHIFT		2  /* 6:2 */
+#define PADS_REFCLK_CFG_E_TERM_SHIFT		7
+#define PADS_REFCLK_CFG_PREDI_SHIFT		8  /* 11:8 */
+#define PADS_REFCLK_CFG_DRVI_SHIFT		12 /* 15:12 */
+
+/* Default value provided by HW engineering is 0xfa5c */
+#define PADS_REFCLK_CFG_VALUE \
+	( \
+		(0x17 << PADS_REFCLK_CFG_TERM_SHIFT)   | \
+		(0    << PADS_REFCLK_CFG_E_TERM_SHIFT) | \
+		(0xa  << PADS_REFCLK_CFG_PREDI_SHIFT)  | \
+		(0xf  << PADS_REFCLK_CFG_DRVI_SHIFT)     \
+	)
+
+#define RP_VEND_XP	0x00000F00
+#define  RP_VEND_XP_DL_UP	(1 << 30)
+
+#define RP_PRIV_MISC	0x00000FE0
+#define  RP_PRIV_MISC_PRSNT_MAP_EP_PRSNT (0xE << 0)
+#define  RP_PRIV_MISC_PRSNT_MAP_EP_ABSNT (0xF << 0)
+
+#define RP_LINK_CONTROL_STATUS			0x00000090
+#define  RP_LINK_CONTROL_STATUS_DL_LINK_ACTIVE	0x20000000
+#define  RP_LINK_CONTROL_STATUS_LINKSTAT_MASK	0x3fff0000
+
+struct tegra_pcie;
+
+struct tegra_pcie_port {
+	struct tegra_pcie *pcie;
+
+	struct fdt_resource regs;
+	unsigned int num_lanes;
+	unsigned int index;
+
+	struct list_head list;
+};
+
+struct tegra_pcie_soc {
+	unsigned int num_ports;
+	unsigned long pads_pll_ctl;
+	unsigned long tx_ref_sel;
+	bool has_pex_clkreq_en;
+	bool has_pex_bias_ctrl;
+	bool has_cml_clk;
+	bool has_gen2;
+};
+
+struct tegra_pcie {
+	struct pci_controller hose;
+
+	struct fdt_resource pads;
+	struct fdt_resource afi;
+	struct fdt_resource cs;
+
+	struct fdt_resource prefetch;
+	struct fdt_resource mem;
+	struct fdt_resource io;
+
+	struct list_head ports;
+	unsigned long xbar;
+
+	const struct tegra_pcie_soc *soc;
+	struct tegra_xusb_phy *phy;
+};
+
+static inline struct tegra_pcie *to_tegra_pcie(struct pci_controller *hose)
+{
+	return container_of(hose, struct tegra_pcie, hose);
+}
+
+static void afi_writel(struct tegra_pcie *pcie, unsigned long value,
+		       unsigned long offset)
+{
+	writel(value, pcie->afi.start + offset);
+}
+
+static unsigned long afi_readl(struct tegra_pcie *pcie, unsigned long offset)
+{
+	return readl(pcie->afi.start + offset);
+}
+
+static void pads_writel(struct tegra_pcie *pcie, unsigned long value,
+			unsigned long offset)
+{
+	writel(value, pcie->pads.start + offset);
+}
+
+static unsigned long pads_readl(struct tegra_pcie *pcie, unsigned long offset)
+{
+	return readl(pcie->pads.start + offset);
+}
+
+static unsigned long rp_readl(struct tegra_pcie_port *port,
+			      unsigned long offset)
+{
+	return readl(port->regs.start + offset);
+}
+
+static void rp_writel(struct tegra_pcie_port *port, unsigned long value,
+		      unsigned long offset)
+{
+	writel(value, port->regs.start + 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);
+}
+
+static int tegra_pcie_conf_address(struct tegra_pcie *pcie, pci_dev_t bdf,
+				   int where, unsigned long *address)
+{
+	unsigned int bus = PCI_BUS(bdf);
+
+	if (bus == 0) {
+		unsigned int dev = PCI_DEV(bdf);
+		struct tegra_pcie_port *port;
+
+		list_for_each_entry(port, &pcie->ports, list) {
+			if (port->index + 1 == dev) {
+				*address = port->regs.start + (where & ~3);
+				return 0;
+			}
+		}
+	} else {
+		*address = pcie->cs.start + tegra_pcie_conf_offset(bdf, where);
+		return 0;
+	}
+
+	return -1;
+}
+
+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;
+	}
+
+	*value = readl(address);
+
+	/* fixup root port class */
+	if (PCI_BUS(bdf) == 0) {
+		if (where == PCI_CLASS_REVISION) {
+			*value &= ~0x00ff0000;
+			*value |= PCI_CLASS_BRIDGE_PCI << 16;
+		}
+	}
+
+	return 0;
+}
+
+static int tegra_pcie_write_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)
+		return 1;
+
+	writel(value, address);
+
+	return 0;
+}
+
+static int tegra_pcie_port_parse_dt(const void *fdt, int node,
+				    struct tegra_pcie_port *port)
+{
+	const u32 *addr;
+	int len;
+
+	addr = fdt_getprop(fdt, node, "assigned-addresses", &len);
+	if (!addr) {
+		error("property \"assigned-addresses\" not found");
+		return -FDT_ERR_NOTFOUND;
+	}
+
+	port->regs.start = fdt32_to_cpu(addr[2]);
+	port->regs.end = port->regs.start + fdt32_to_cpu(addr[4]);
+
+	return 0;
+}
+
+static int tegra_pcie_get_xbar_config(const void *fdt, int node, u32 lanes,
+				      unsigned long *xbar)
+{
+	enum fdt_compat_id id = fdtdec_lookup(fdt, node);
+
+	switch (id) {
+	case COMPAT_NVIDIA_TEGRA20_PCIE:
+		switch (lanes) {
+		case 0x00000004:
+			debug("single-mode configuration\n");
+			*xbar = AFI_PCIE_CONFIG_SM2TMS0_XBAR_CONFIG_SINGLE;
+			return 0;
+
+		case 0x00000202:
+			debug("dual-mode configuration\n");
+			*xbar = AFI_PCIE_CONFIG_SM2TMS0_XBAR_CONFIG_DUAL;
+			return 0;
+		}
+		break;
+
+	case COMPAT_NVIDIA_TEGRA30_PCIE:
+		switch (lanes) {
+		case 0x00000204:
+			debug("4x1, 2x1 configuration\n");
+			*xbar = AFI_PCIE_CONFIG_SM2TMS0_XBAR_CONFIG_420;
+			return 0;
+
+		case 0x00020202:
+			debug("2x3 configuration\n");
+			*xbar = AFI_PCIE_CONFIG_SM2TMS0_XBAR_CONFIG_222;
+			return 0;
+
+		case 0x00010104:
+			debug("4x1, 1x2 configuration\n");
+			*xbar = AFI_PCIE_CONFIG_SM2TMS0_XBAR_CONFIG_411;
+			return 0;
+		}
+		break;
+
+	case COMPAT_NVIDIA_TEGRA124_PCIE:
+		switch (lanes) {
+		case 0x0000104:
+			debug("4x1, 1x1 configuration\n");
+			*xbar = AFI_PCIE_CONFIG_SM2TMS0_XBAR_CONFIG_X4_X1;
+			return 0;
+
+		case 0x0000102:
+			debug("2x1, 1x1 configuration\n");
+			*xbar = AFI_PCIE_CONFIG_SM2TMS0_XBAR_CONFIG_X2_X1;
+			return 0;
+		}
+		break;
+
+	default:
+		break;
+	}
+
+	return -FDT_ERR_NOTFOUND;
+}
+
+static int tegra_pcie_parse_dt_ranges(const void *fdt, int node,
+				      struct tegra_pcie *pcie)
+{
+	const u32 *ptr, *end;
+	int len;
+
+	ptr = fdt_getprop(fdt, node, "ranges", &len);
+	if (!ptr) {
+		error("missing \"ranges\" property");
+		return -FDT_ERR_NOTFOUND;
+	}
+
+	end = ptr + len / 4;
+
+	while (ptr < end) {
+		struct fdt_resource *res = NULL;
+		u32 space = fdt32_to_cpu(*ptr);
+
+		switch ((space >> 24) & 0x3) {
+		case 0x01:
+			res = &pcie->io;
+			break;
+
+		case 0x02: /* 32 bit */
+		case 0x03: /* 64 bit */
+			if (space & (1 << 30))
+				res = &pcie->prefetch;
+			else
+				res = &pcie->mem;
+
+			break;
+		}
+
+		if (res) {
+			res->start = fdt32_to_cpu(ptr[3]);
+			res->end = res->start + fdt32_to_cpu(ptr[5]);
+		}
+
+		ptr += 3 + 1 + 2;
+	}
+
+	debug("PCI regions:\n");
+	debug("  I/O: %#x-%#x\n", pcie->io.start, pcie->io.end);
+	debug("  non-prefetchable memory: %#x-%#x\n", pcie->mem.start,
+	      pcie->mem.end);
+	debug("  prefetchable memory: %#x-%#x\n", pcie->prefetch.start,
+	      pcie->prefetch.end);
+
+	return 0;
+}
+
+static int tegra_pcie_parse_port_info(const void *fdt, int node,
+				      unsigned int *index,
+				      unsigned int *lanes)
+{
+	pci_dev_t bdf;
+	int err;
+
+	err = fdtdec_get_int(fdt, node, "nvidia,num-lanes", 0);
+	if (err < 0) {
+		error("failed to parse \"nvidia,num-lanes\" property");
+		return err;
+	}
+
+	*lanes = err;
+
+	err = fdtdec_pci_get_bdf(fdt, node, &bdf);
+	if (err < 0) {
+		error("failed to parse \"reg\" property");
+		return err;
+	}
+
+	*index = PCI_DEV(bdf) - 1;
+
+	return 0;
+}
+
+static int tegra_pcie_parse_dt(const void *fdt, int node,
+			       struct tegra_pcie *pcie)
+{
+	int err, subnode;
+	u32 lanes = 0;
+
+	err = fdt_get_named_resource(fdt, node, "reg", "reg-names", "pads",
+				     &pcie->pads);
+	if (err < 0) {
+		error("resource \"pads\" not found");
+		return err;
+	}
+
+	err = fdt_get_named_resource(fdt, node, "reg", "reg-names", "afi",
+				     &pcie->afi);
+	if (err < 0) {
+		error("resource \"afi\" not found");
+		return err;
+	}
+
+	err = fdt_get_named_resource(fdt, node, "reg", "reg-names", "cs",
+				     &pcie->cs);
+	if (err < 0) {
+		error("resource \"cs\" not found");
+		return err;
+	}
+
+	pcie->phy = tegra_xusb_phy_get(TEGRA_XUSB_PADCTL_PCIE);
+	if (pcie->phy) {
+		err = tegra_xusb_phy_prepare(pcie->phy);
+		if (err < 0) {
+			error("failed to prepare PHY: %d", err);
+			return err;
+		}
+	}
+
+	err = tegra_pcie_parse_dt_ranges(fdt, node, pcie);
+	if (err < 0) {
+		error("failed to parse \"ranges\" property");
+		return err;
+	}
+
+	fdt_for_each_subnode(fdt, subnode, node) {
+		unsigned int index = 0, num_lanes = 0;
+		struct tegra_pcie_port *port;
+
+		err = tegra_pcie_parse_port_info(fdt, subnode, &index,
+						 &num_lanes);
+		if (err < 0) {
+			error("failed to obtain root port info");
+			continue;
+		}
+
+		lanes |= num_lanes << (index << 3);
+
+		if (!fdtdec_get_is_enabled(fdt, subnode))
+			continue;
+
+		port = malloc(sizeof(*port));
+		if (!port)
+			continue;
+
+		memset(port, 0, sizeof(*port));
+		port->num_lanes = num_lanes;
+		port->index = index;
+
+		err = tegra_pcie_port_parse_dt(fdt, subnode, port);
+		if (err < 0) {
+			free(port);
+			continue;
+		}
+
+		list_add_tail(&port->list, &pcie->ports);
+		port->pcie = pcie;
+	}
+
+	err = tegra_pcie_get_xbar_config(fdt, node, lanes, &pcie->xbar);
+	if (err < 0) {
+		error("invalid lane configuration");
+		return err;
+	}
+
+	return 0;
+}
+
+int __weak tegra_pcie_board_init(void)
+{
+	return 0;
+}
+
+static int tegra_pcie_power_on(struct tegra_pcie *pcie)
+{
+	const struct tegra_pcie_soc *soc = pcie->soc;
+	unsigned long value;
+	int err;
+
+	/* reset PCIEXCLK logic, AFI controller and PCIe controller */
+	reset_set_enable(PERIPH_ID_PCIEXCLK, 1);
+	reset_set_enable(PERIPH_ID_AFI, 1);
+	reset_set_enable(PERIPH_ID_PCIE, 1);
+
+	tegra_powergate_power_off(TEGRA_POWERGATE_PCIE);
+
+	tegra_pcie_board_init();
+
+	tegra_powergate_sequence_power_up(TEGRA_POWERGATE_PCIE,
+					  PERIPH_ID_PCIE);
+
+	/* take AFI controller out of reset */
+	reset_set_enable(PERIPH_ID_AFI, 0);
+
+	/* enable AFI clock */
+	clock_enable(PERIPH_ID_AFI);
+
+	if (soc->has_cml_clk) {
+		/* enable CML clock */
+		value = readl(NV_PA_CLK_RST_BASE + 0x48c);
+		value |= (1 << 0);
+		value &= ~(1 << 1);
+		writel(value, NV_PA_CLK_RST_BASE + 0x48c);
+	}
+
+	err = tegra_plle_enable();
+	if (err < 0) {
+		error("failed to enable PLLE: %d\n", err);
+		return err;
+	}
+
+	return 0;
+}
+
+static int tegra_pcie_pll_wait(struct tegra_pcie *pcie, unsigned long timeout)
+{
+	const struct tegra_pcie_soc *soc = pcie->soc;
+	unsigned long start = get_timer(0);
+	u32 value;
+
+	while (get_timer(start) < timeout) {
+		value = pads_readl(pcie, soc->pads_pll_ctl);
+		if (value & PADS_PLL_CTL_LOCKDET)
+			return 0;
+	}
+
+	return -ETIMEDOUT;
+}
+
+static int tegra_pcie_phy_enable(struct tegra_pcie *pcie)
+{
+	const struct tegra_pcie_soc *soc = pcie->soc;
+	u32 value;
+	int err;
+
+	/* initialize internal PHY, enable up to 16 PCIe lanes */
+	pads_writel(pcie, 0, PADS_CTL_SEL);
+
+	/* override IDDQ to 1 on all 4 lanes */
+	value = pads_readl(pcie, PADS_CTL);
+	value |= PADS_CTL_IDDQ_1L;
+	pads_writel(pcie, value, PADS_CTL);
+
+	/*
+	 * Set up PHY PLL inputs select PLLE output as refclock, set TX
+	 * ref sel to div10 (not div5).
+	 */
+	value = pads_readl(pcie, soc->pads_pll_ctl);
+	value &= ~(PADS_PLL_CTL_REFCLK_MASK | PADS_PLL_CTL_TXCLKREF_MASK);
+	value |= PADS_PLL_CTL_REFCLK_INTERNAL_CML | soc->tx_ref_sel;
+	pads_writel(pcie, value, soc->pads_pll_ctl);
+
+	/* reset PLL */
+	value = pads_readl(pcie, soc->pads_pll_ctl);
+	value &= ~PADS_PLL_CTL_RST_B4SM;
+	pads_writel(pcie, value, soc->pads_pll_ctl);
+
+	udelay(20);
+
+	/* take PLL out of reset */
+	value = pads_readl(pcie, soc->pads_pll_ctl);
+	value |= PADS_PLL_CTL_RST_B4SM;
+	pads_writel(pcie, value, soc->pads_pll_ctl);
+
+	/* configure the reference clock driver */
+	value = PADS_REFCLK_CFG_VALUE | (PADS_REFCLK_CFG_VALUE << 16);
+	pads_writel(pcie, value, PADS_REFCLK_CFG0);
+
+	if (soc->num_ports > 2)
+		pads_writel(pcie, PADS_REFCLK_CFG_VALUE, PADS_REFCLK_CFG1);
+
+	/* wait for the PLL to lock */
+	err = tegra_pcie_pll_wait(pcie, 500);
+	if (err < 0) {
+		error("PLL failed to lock: %d", err);
+		return err;
+	}
+
+	/* turn off IDDQ override */
+	value = pads_readl(pcie, PADS_CTL);
+	value &= ~PADS_CTL_IDDQ_1L;
+	pads_writel(pcie, value, PADS_CTL);
+
+	/* enable TX/RX data */
+	value = pads_readl(pcie, PADS_CTL);
+	value |= PADS_CTL_TX_DATA_EN_1L | PADS_CTL_RX_DATA_EN_1L;
+	pads_writel(pcie, value, PADS_CTL);
+
+	return 0;
+}
+
+static int tegra_pcie_enable_controller(struct tegra_pcie *pcie)
+{
+	const struct tegra_pcie_soc *soc = pcie->soc;
+	struct tegra_pcie_port *port;
+	u32 value;
+	int err;
+
+	if (pcie->phy) {
+		value = afi_readl(pcie, AFI_PLLE_CONTROL);
+		value &= ~AFI_PLLE_CONTROL_BYPASS_PADS2PLLE_CONTROL;
+		value |= AFI_PLLE_CONTROL_PADS2PLLE_CONTROL_EN;
+		afi_writel(pcie, value, AFI_PLLE_CONTROL);
+	}
+
+	if (soc->has_pex_bias_ctrl)
+		afi_writel(pcie, 0, AFI_PEXBIAS_CTRL_0);
+
+	value = afi_readl(pcie, AFI_PCIE_CONFIG);
+	value &= ~AFI_PCIE_CONFIG_SM2TMS0_XBAR_CONFIG_MASK;
+	value |= AFI_PCIE_CONFIG_PCIE_DISABLE_ALL | pcie->xbar;
+
+	list_for_each_entry(port, &pcie->ports, list)
+		value &= ~AFI_PCIE_CONFIG_PCIE_DISABLE(port->index);
+
+	afi_writel(pcie, value, AFI_PCIE_CONFIG);
+
+	value = afi_readl(pcie, AFI_FUSE);
+
+	if (soc->has_gen2)
+		value &= ~AFI_FUSE_PCIE_T0_GEN2_DIS;
+	else
+		value |= AFI_FUSE_PCIE_T0_GEN2_DIS;
+
+	afi_writel(pcie, value, AFI_FUSE);
+
+	if (pcie->phy)
+		err = tegra_xusb_phy_enable(pcie->phy);
+	else
+		err = tegra_pcie_phy_enable(pcie);
+
+	if (err < 0) {
+		error("failed to power on PHY: %d\n", err);
+		return err;
+	}
+
+	/* take the PCIEXCLK logic out of reset */
+	reset_set_enable(PERIPH_ID_PCIEXCLK, 0);
+
+	/* finally enable PCIe */
+	value = afi_readl(pcie, AFI_CONFIGURATION);
+	value |= AFI_CONFIGURATION_EN_FPCI;
+	afi_writel(pcie, value, AFI_CONFIGURATION);
+
+	/* disable all interrupts */
+	afi_writel(pcie, 0, AFI_AFI_INTR_ENABLE);
+	afi_writel(pcie, 0, AFI_SM_INTR_ENABLE);
+	afi_writel(pcie, 0, AFI_INTR_MASK);
+	afi_writel(pcie, 0, AFI_FPCI_ERROR_MASKS);
+
+	return 0;
+}
+
+static void tegra_pcie_setup_translations(struct tegra_pcie *pcie)
+{
+	unsigned long fpci, axi, size;
+
+	/* BAR 0: type 1 extended configuration space */
+	fpci = 0xfe100000;
+	size = fdt_resource_size(&pcie->cs);
+	axi = pcie->cs.start;
+
+	afi_writel(pcie, axi, AFI_AXI_BAR0_START);
+	afi_writel(pcie, size >> 12, AFI_AXI_BAR0_SZ);
+	afi_writel(pcie, fpci, AFI_FPCI_BAR0);
+
+	/* BAR 1: downstream I/O */
+	fpci = 0xfdfc0000;
+	size = fdt_resource_size(&pcie->io);
+	axi = pcie->io.start;
+
+	afi_writel(pcie, axi, AFI_AXI_BAR1_START);
+	afi_writel(pcie, size >> 12, AFI_AXI_BAR1_SZ);
+	afi_writel(pcie, fpci, AFI_FPCI_BAR1);
+
+	/* BAR 2: prefetchable memory */
+	fpci = (((pcie->prefetch.start >> 12) & 0x0fffffff) << 4) | 0x1;
+	size = fdt_resource_size(&pcie->prefetch);
+	axi = pcie->prefetch.start;
+
+	afi_writel(pcie, axi, AFI_AXI_BAR2_START);
+	afi_writel(pcie, size >> 12, AFI_AXI_BAR2_SZ);
+	afi_writel(pcie, fpci, AFI_FPCI_BAR2);
+
+	/* BAR 3: non-prefetchable memory */
+	fpci = (((pcie->mem.start >> 12) & 0x0fffffff) << 4) | 0x1;
+	size = fdt_resource_size(&pcie->mem);
+	axi = pcie->mem.start;
+
+	afi_writel(pcie, axi, AFI_AXI_BAR3_START);
+	afi_writel(pcie, size >> 12, AFI_AXI_BAR3_SZ);
+	afi_writel(pcie, fpci, AFI_FPCI_BAR3);
+
+	/* NULL out the remaining BARs as they are not used */
+	afi_writel(pcie, 0, AFI_AXI_BAR4_START);
+	afi_writel(pcie, 0, AFI_AXI_BAR4_SZ);
+	afi_writel(pcie, 0, AFI_FPCI_BAR4);
+
+	afi_writel(pcie, 0, AFI_AXI_BAR5_START);
+	afi_writel(pcie, 0, AFI_AXI_BAR5_SZ);
+	afi_writel(pcie, 0, AFI_FPCI_BAR5);
+
+	/* map all upstream transactions as uncached */
+	afi_writel(pcie, NV_PA_SDRAM_BASE, AFI_CACHE_BAR0_ST);
+	afi_writel(pcie, 0, AFI_CACHE_BAR0_SZ);
+	afi_writel(pcie, 0, AFI_CACHE_BAR1_ST);
+	afi_writel(pcie, 0, AFI_CACHE_BAR1_SZ);
+
+	/* MSI translations are setup only when needed */
+	afi_writel(pcie, 0, AFI_MSI_FPCI_BAR_ST);
+	afi_writel(pcie, 0, AFI_MSI_BAR_SZ);
+	afi_writel(pcie, 0, AFI_MSI_AXI_BAR_ST);
+	afi_writel(pcie, 0, AFI_MSI_BAR_SZ);
+}
+
+static unsigned long tegra_pcie_port_get_pex_ctrl(struct tegra_pcie_port *port)
+{
+	unsigned long ret = 0;
+
+	switch (port->index) {
+	case 0:
+		ret = AFI_PEX0_CTRL;
+		break;
+
+	case 1:
+		ret = AFI_PEX1_CTRL;
+		break;
+
+	case 2:
+		ret = AFI_PEX2_CTRL;
+		break;
+	}
+
+	return ret;
+}
+
+static void tegra_pcie_port_reset(struct tegra_pcie_port *port)
+{
+	unsigned long ctrl = tegra_pcie_port_get_pex_ctrl(port);
+	unsigned long value;
+
+	/* pulse reset signel */
+	value = afi_readl(port->pcie, ctrl);
+	value &= ~AFI_PEX_CTRL_RST;
+	afi_writel(port->pcie, value, ctrl);
+
+	udelay(2000);
+
+	value = afi_readl(port->pcie, ctrl);
+	value |= AFI_PEX_CTRL_RST;
+	afi_writel(port->pcie, value, ctrl);
+}
+
+static void tegra_pcie_port_enable(struct tegra_pcie_port *port)
+{
+	unsigned long ctrl = tegra_pcie_port_get_pex_ctrl(port);
+	unsigned long value;
+
+	/* enable reference clock */
+	value = afi_readl(port->pcie, ctrl);
+	value |= AFI_PEX_CTRL_REFCLK_EN;
+
+	if (port->pcie->soc->has_pex_clkreq_en)
+		value |= AFI_PEX_CTRL_CLKREQ_EN;
+
+	value |= AFI_PEX_CTRL_OVERRIDE_EN;
+
+	afi_writel(port->pcie, value, ctrl);
+
+	tegra_pcie_port_reset(port);
+}
+
+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)
+				break;
+
+			udelay(2000);
+		} while (--timeout);
+
+		if (!timeout) {
+			debug("link %u down, retrying\n", port->index);
+			goto retry;
+		}
+
+		timeout = 200;
+
+		do {
+			value = rp_readl(port, RP_LINK_CONTROL_STATUS);
+			if (value & RP_LINK_CONTROL_STATUS_DL_LINK_ACTIVE)
+				return true;
+
+			udelay(2000);
+		} while (--timeout);
+
+retry:
+		tegra_pcie_port_reset(port);
+	} while (--retries);
+
+	return false;
+}
+
+static void tegra_pcie_port_disable(struct tegra_pcie_port *port)
+{
+	unsigned long ctrl = tegra_pcie_port_get_pex_ctrl(port);
+	unsigned long value;
+
+	/* assert port reset */
+	value = afi_readl(port->pcie, ctrl);
+	value &= ~AFI_PEX_CTRL_RST;
+	afi_writel(port->pcie, value, ctrl);
+
+	/* disable reference clock */
+	value = afi_readl(port->pcie, ctrl);
+	value &= ~AFI_PEX_CTRL_REFCLK_EN;
+	afi_writel(port->pcie, value, ctrl);
+}
+
+static void tegra_pcie_port_free(struct tegra_pcie_port *port)
+{
+	list_del(&port->list);
+	free(port);
+}
+
+static int tegra_pcie_enable(struct tegra_pcie *pcie)
+{
+	struct tegra_pcie_port *port, *tmp;
+
+	list_for_each_entry_safe(port, tmp, &pcie->ports, list) {
+		debug("probing port %u, using %u lanes\n", port->index,
+		      port->num_lanes);
+
+		tegra_pcie_port_enable(port);
+
+		if (tegra_pcie_port_check_link(port))
+			continue;
+
+		debug("link %u down, ignoring\n", port->index);
+
+		tegra_pcie_port_disable(port);
+		tegra_pcie_port_free(port);
+	}
+
+	return 0;
+}
+
+static const struct tegra_pcie_soc tegra20_pcie_soc = {
+	.num_ports = 2,
+	.pads_pll_ctl = PADS_PLL_CTL_TEGRA20,
+	.tx_ref_sel = PADS_PLL_CTL_TXCLKREF_DIV10,
+	.has_pex_clkreq_en = false,
+	.has_pex_bias_ctrl = false,
+	.has_cml_clk = false,
+	.has_gen2 = false,
+};
+
+static const struct tegra_pcie_soc tegra30_pcie_soc = {
+	.num_ports = 3,
+	.pads_pll_ctl = PADS_PLL_CTL_TEGRA30,
+	.tx_ref_sel = PADS_PLL_CTL_TXCLKREF_BUF_EN,
+	.has_pex_clkreq_en = true,
+	.has_pex_bias_ctrl = true,
+	.has_cml_clk = true,
+	.has_gen2 = false,
+};
+
+static const struct tegra_pcie_soc tegra124_pcie_soc = {
+	.num_ports = 2,
+	.pads_pll_ctl = PADS_PLL_CTL_TEGRA30,
+	.tx_ref_sel = PADS_PLL_CTL_TXCLKREF_BUF_EN,
+	.has_pex_clkreq_en = true,
+	.has_pex_bias_ctrl = true,
+	.has_cml_clk = true,
+	.has_gen2 = true,
+};
+
+static int process_nodes(const void *fdt, int nodes[], unsigned int count)
+{
+	unsigned int i;
+
+	for (i = 0; i < count; i++) {
+		const struct tegra_pcie_soc *soc;
+		struct tegra_pcie *pcie;
+		enum fdt_compat_id id;
+		int err;
+
+		if (!fdtdec_get_is_enabled(fdt, nodes[i]))
+			continue;
+
+		id = fdtdec_lookup(fdt, nodes[i]);
+		switch (id) {
+		case COMPAT_NVIDIA_TEGRA20_PCIE:
+			soc = &tegra20_pcie_soc;
+			break;
+
+		case COMPAT_NVIDIA_TEGRA30_PCIE:
+			soc = &tegra30_pcie_soc;
+			break;
+
+		case COMPAT_NVIDIA_TEGRA124_PCIE:
+			soc = &tegra124_pcie_soc;
+			break;
+
+		default:
+			error("unsupported compatible: %s",
+			      fdtdec_get_compatible(id));
+			continue;
+		}
+
+		pcie = malloc(sizeof(*pcie));
+		if (!pcie) {
+			error("failed to allocate controller");
+			continue;
+		}
+
+		memset(pcie, 0, sizeof(*pcie));
+		pcie->soc = soc;
+
+		INIT_LIST_HEAD(&pcie->ports);
+
+		err = tegra_pcie_parse_dt(fdt, nodes[i], pcie);
+		if (err < 0) {
+			free(pcie);
+			continue;
+		}
+
+		err = tegra_pcie_power_on(pcie);
+		if (err < 0) {
+			error("failed to power on");
+			continue;
+		}
+
+		err = tegra_pcie_enable_controller(pcie);
+		if (err < 0) {
+			error("failed to enable controller");
+			continue;
+		}
+
+		tegra_pcie_setup_translations(pcie);
+
+		err = tegra_pcie_enable(pcie);
+		if (err < 0) {
+			error("failed to enable PCIe");
+			continue;
+		}
+
+		pcie->hose.first_busno = 0;
+		pcie->hose.current_busno = 0;
+		pcie->hose.last_busno = 0;
+
+		pci_set_region(&pcie->hose.regions[0], NV_PA_SDRAM_BASE,
+			       NV_PA_SDRAM_BASE, gd->ram_size,
+			       PCI_REGION_MEM | PCI_REGION_SYS_MEMORY);
+
+		pci_set_region(&pcie->hose.regions[1], pcie->io.start,
+			       pcie->io.start, fdt_resource_size(&pcie->io),
+			       PCI_REGION_IO);
+
+		pci_set_region(&pcie->hose.regions[2], pcie->mem.start,
+			       pcie->mem.start, fdt_resource_size(&pcie->mem),
+			       PCI_REGION_MEM);
+
+		pci_set_region(&pcie->hose.regions[3], pcie->prefetch.start,
+			       pcie->prefetch.start,
+			       fdt_resource_size(&pcie->prefetch),
+			       PCI_REGION_MEM | PCI_REGION_PREFETCH);
+
+		pcie->hose.region_count = 4;
+
+		pci_set_ops(&pcie->hose,
+			    pci_hose_read_config_byte_via_dword,
+			    pci_hose_read_config_word_via_dword,
+			    tegra_pcie_read_conf,
+			    pci_hose_write_config_byte_via_dword,
+			    pci_hose_write_config_word_via_dword,
+			    tegra_pcie_write_conf);
+
+		pci_register_hose(&pcie->hose);
+
+#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);
+	}
+
+	return 0;
+}
+
+void pci_init_board(void)
+{
+	const void *fdt = gd->fdt_blob;
+	int count, nodes[1];
+
+	count = fdtdec_find_aliases_for_id(fdt, "pcie-controller",
+					   COMPAT_NVIDIA_TEGRA124_PCIE,
+					   nodes, ARRAY_SIZE(nodes));
+	if (process_nodes(fdt, nodes, count))
+		return;
+
+	count = fdtdec_find_aliases_for_id(fdt, "pcie-controller",
+					   COMPAT_NVIDIA_TEGRA30_PCIE,
+					   nodes, ARRAY_SIZE(nodes));
+	if (process_nodes(fdt, nodes, count))
+		return;
+
+	count = fdtdec_find_aliases_for_id(fdt, "pcie-controller",
+					   COMPAT_NVIDIA_TEGRA20_PCIE,
+					   nodes, ARRAY_SIZE(nodes));
+	if (process_nodes(fdt, nodes, count))
+		return;
+}
+
+int pci_skip_dev(struct pci_controller *hose, pci_dev_t dev)
+{
+	if (PCI_BUS(dev) != 0 && PCI_DEV(dev) > 0)
+		return 1;
+
+	return 0;
+}
diff --git a/include/fdtdec.h b/include/fdtdec.h
index c0464f07961d..2869cd0ae206 100644
--- a/include/fdtdec.h
+++ b/include/fdtdec.h
@@ -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 */
diff --git a/lib/fdtdec.c b/lib/fdtdec.c
index 16e0714b0fed..3e41b0c99683 100644
--- a/lib/fdtdec.c
+++ b/lib/fdtdec.c
@@ -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"),
-- 
2.0.4

^ permalink raw reply related	[flat|nested] 95+ messages in thread

* [U-Boot] [PATCH 16/23] ARM: tegra: Add Tegra20 PCIe device tree node
  2014-08-18  7:16 [U-Boot] [PATCH 00/23] ARM: tegra: Add PCIe support Thierry Reding
                   ` (14 preceding siblings ...)
  2014-08-18  7:16 ` [U-Boot] [PATCH 15/23] pci: tegra: Add Tegra PCIe driver Thierry Reding
@ 2014-08-18  7:16 ` Thierry Reding
  2014-08-20 18:37   ` Stephen Warren
  2014-08-18  7:16 ` [U-Boot] [PATCH 17/23] ARM: tegra: Enable PCIe on TrimSlice Thierry Reding
                   ` (6 subsequent siblings)
  22 siblings, 1 reply; 95+ messages in thread
From: Thierry Reding @ 2014-08-18  7:16 UTC (permalink / raw)
  To: u-boot

From: Thierry Reding <treding@nvidia.com>

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

Signed-off-by: Thierry Reding <treding@nvidia.com>
---
 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

diff --git a/arch/arm/dts/tegra20.dtsi b/arch/arm/dts/tegra20.dtsi
index a524f6eed410..ac9aeeb76582 100644
--- a/arch/arm/dts/tegra20.dtsi
+++ b/arch/arm/dts/tegra20.dtsi
@@ -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>;
diff --git a/include/dt-bindings/clock/tegra20-car.h b/include/dt-bindings/clock/tegra20-car.h
new file mode 100644
index 000000000000..a1ae9a8fdd6c
--- /dev/null
+++ b/include/dt-bindings/clock/tegra20-car.h
@@ -0,0 +1,158 @@
+/*
+ * This header provides constants for binding nvidia,tegra20-car.
+ *
+ * The first 96 clocks are numbered to match the bits in the CAR's CLK_OUT_ENB
+ * registers. These IDs often match those in the CAR's RST_DEVICES registers,
+ * but not in all cases. Some bits in CLK_OUT_ENB affect multiple clocks. In
+ * this case, those clocks are assigned IDs above 95 in order to highlight
+ * this issue. Implementations that interpret these clock IDs as bit values
+ * within the CLK_OUT_ENB or RST_DEVICES registers should be careful to
+ * explicitly handle these special cases.
+ *
+ * The balance of the clocks controlled by the CAR are assigned IDs of 96 and
+ * above.
+ */
+
+#ifndef _DT_BINDINGS_CLOCK_TEGRA20_CAR_H
+#define _DT_BINDINGS_CLOCK_TEGRA20_CAR_H
+
+#define TEGRA20_CLK_CPU 0
+/* 1 */
+/* 2 */
+#define TEGRA20_CLK_AC97 3
+#define TEGRA20_CLK_RTC 4
+#define TEGRA20_CLK_TIMER 5
+#define TEGRA20_CLK_UARTA 6
+/* 7 (register bit affects uart2 and vfir) */
+#define TEGRA20_CLK_GPIO 8
+#define TEGRA20_CLK_SDMMC2 9
+/* 10 (register bit affects spdif_in and spdif_out) */
+#define TEGRA20_CLK_I2S1 11
+#define TEGRA20_CLK_I2C1 12
+#define TEGRA20_CLK_NDFLASH 13
+#define TEGRA20_CLK_SDMMC1 14
+#define TEGRA20_CLK_SDMMC4 15
+#define TEGRA20_CLK_TWC 16
+#define TEGRA20_CLK_PWM 17
+#define TEGRA20_CLK_I2S2 18
+#define TEGRA20_CLK_EPP 19
+/* 20 (register bit affects vi and vi_sensor) */
+#define TEGRA20_CLK_GR2D 21
+#define TEGRA20_CLK_USBD 22
+#define TEGRA20_CLK_ISP 23
+#define TEGRA20_CLK_GR3D 24
+#define TEGRA20_CLK_IDE 25
+#define TEGRA20_CLK_DISP2 26
+#define TEGRA20_CLK_DISP1 27
+#define TEGRA20_CLK_HOST1X 28
+#define TEGRA20_CLK_VCP 29
+/* 30 */
+#define TEGRA20_CLK_CACHE2 31
+
+#define TEGRA20_CLK_MEM 32
+#define TEGRA20_CLK_AHBDMA 33
+#define TEGRA20_CLK_APBDMA 34
+/* 35 */
+#define TEGRA20_CLK_KBC 36
+#define TEGRA20_CLK_STAT_MON 37
+#define TEGRA20_CLK_PMC 38
+#define TEGRA20_CLK_FUSE 39
+#define TEGRA20_CLK_KFUSE 40
+#define TEGRA20_CLK_SBC1 41
+#define TEGRA20_CLK_NOR 42
+#define TEGRA20_CLK_SPI 43
+#define TEGRA20_CLK_SBC2 44
+#define TEGRA20_CLK_XIO 45
+#define TEGRA20_CLK_SBC3 46
+#define TEGRA20_CLK_DVC 47
+#define TEGRA20_CLK_DSI 48
+/* 49 (register bit affects tvo and cve) */
+#define TEGRA20_CLK_MIPI 50
+#define TEGRA20_CLK_HDMI 51
+#define TEGRA20_CLK_CSI 52
+#define TEGRA20_CLK_TVDAC 53
+#define TEGRA20_CLK_I2C2 54
+#define TEGRA20_CLK_UARTC 55
+/* 56 */
+#define TEGRA20_CLK_EMC 57
+#define TEGRA20_CLK_USB2 58
+#define TEGRA20_CLK_USB3 59
+#define TEGRA20_CLK_MPE 60
+#define TEGRA20_CLK_VDE 61
+#define TEGRA20_CLK_BSEA 62
+#define TEGRA20_CLK_BSEV 63
+
+#define TEGRA20_CLK_SPEEDO 64
+#define TEGRA20_CLK_UARTD 65
+#define TEGRA20_CLK_UARTE 66
+#define TEGRA20_CLK_I2C3 67
+#define TEGRA20_CLK_SBC4 68
+#define TEGRA20_CLK_SDMMC3 69
+#define TEGRA20_CLK_PEX 70
+#define TEGRA20_CLK_OWR 71
+#define TEGRA20_CLK_AFI 72
+#define TEGRA20_CLK_CSITE 73
+#define TEGRA20_CLK_PCIE_XCLK 74
+#define TEGRA20_CLK_AVPUCQ 75
+#define TEGRA20_CLK_LA 76
+/* 77 */
+/* 78 */
+/* 79 */
+/* 80 */
+/* 81 */
+/* 82 */
+/* 83 */
+#define TEGRA20_CLK_IRAMA 84
+#define TEGRA20_CLK_IRAMB 85
+#define TEGRA20_CLK_IRAMC 86
+#define TEGRA20_CLK_IRAMD 87
+#define TEGRA20_CLK_CRAM2 88
+#define TEGRA20_CLK_AUDIO_2X 89 /* a/k/a audio_2x_sync_clk */
+#define TEGRA20_CLK_CLK_D 90
+/* 91 */
+#define TEGRA20_CLK_CSUS 92
+#define TEGRA20_CLK_CDEV2 93
+#define TEGRA20_CLK_CDEV1 94
+/* 95 */
+
+#define TEGRA20_CLK_UARTB 96
+#define TEGRA20_CLK_VFIR 97
+#define TEGRA20_CLK_SPDIF_IN 98
+#define TEGRA20_CLK_SPDIF_OUT 99
+#define TEGRA20_CLK_VI 100
+#define TEGRA20_CLK_VI_SENSOR 101
+#define TEGRA20_CLK_TVO 102
+#define TEGRA20_CLK_CVE 103
+#define TEGRA20_CLK_OSC 104
+#define TEGRA20_CLK_CLK_32K 105 /* a/k/a clk_s */
+#define TEGRA20_CLK_CLK_M 106
+#define TEGRA20_CLK_SCLK 107
+#define TEGRA20_CLK_CCLK 108
+#define TEGRA20_CLK_HCLK 109
+#define TEGRA20_CLK_PCLK 110
+#define TEGRA20_CLK_BLINK 111
+#define TEGRA20_CLK_PLL_A 112
+#define TEGRA20_CLK_PLL_A_OUT0 113
+#define TEGRA20_CLK_PLL_C 114
+#define TEGRA20_CLK_PLL_C_OUT1 115
+#define TEGRA20_CLK_PLL_D 116
+#define TEGRA20_CLK_PLL_D_OUT0 117
+#define TEGRA20_CLK_PLL_E 118
+#define TEGRA20_CLK_PLL_M 119
+#define TEGRA20_CLK_PLL_M_OUT1 120
+#define TEGRA20_CLK_PLL_P 121
+#define TEGRA20_CLK_PLL_P_OUT1 122
+#define TEGRA20_CLK_PLL_P_OUT2 123
+#define TEGRA20_CLK_PLL_P_OUT3 124
+#define TEGRA20_CLK_PLL_P_OUT4 125
+#define TEGRA20_CLK_PLL_S 126
+#define TEGRA20_CLK_PLL_U 127
+
+#define TEGRA20_CLK_PLL_X 128
+#define TEGRA20_CLK_COP 129 /* a/k/a avp */
+#define TEGRA20_CLK_AUDIO 130 /* a/k/a audio_sync_clk */
+#define TEGRA20_CLK_PLL_REF 131
+#define TEGRA20_CLK_TWD 132
+#define TEGRA20_CLK_CLK_MAX 133
+
+#endif	/* _DT_BINDINGS_CLOCK_TEGRA20_CAR_H */
-- 
2.0.4

^ permalink raw reply related	[flat|nested] 95+ messages in thread

* [U-Boot] [PATCH 17/23] ARM: tegra: Enable PCIe on TrimSlice
  2014-08-18  7:16 [U-Boot] [PATCH 00/23] ARM: tegra: Add PCIe support Thierry Reding
                   ` (15 preceding siblings ...)
  2014-08-18  7:16 ` [U-Boot] [PATCH 16/23] ARM: tegra: Add Tegra20 PCIe device tree node Thierry Reding
@ 2014-08-18  7:16 ` Thierry Reding
  2014-08-20 18:38   ` Stephen Warren
  2014-08-18  7:16 ` [U-Boot] [PATCH 18/23] ARM: tegra: Add Tegra30 PCIe device tree node Thierry Reding
                   ` (5 subsequent siblings)
  22 siblings, 1 reply; 95+ messages in thread
From: Thierry Reding @ 2014-08-18  7:16 UTC (permalink / raw)
  To: u-boot

From: Thierry Reding <treding@nvidia.com>

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.

Signed-off-by: Thierry Reding <treding@nvidia.com>
---
 arch/arm/dts/tegra20-trimslice.dts   | 35 +++++++++++++++++++++++++++++++++++
 board/compulab/trimslice/trimslice.c |  8 ++++++++
 include/configs/trimslice.h          | 10 ++++++++++
 3 files changed, 53 insertions(+)

diff --git a/arch/arm/dts/tegra20-trimslice.dts b/arch/arm/dts/tegra20-trimslice.dts
index ee31476c1eb8..298a0379c591 100644
--- a/arch/arm/dts/tegra20-trimslice.dts
+++ b/arch/arm/dts/tegra20-trimslice.dts
@@ -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;
+		};
+	};
+
 };
diff --git a/board/compulab/trimslice/trimslice.c b/board/compulab/trimslice/trimslice.c
index 723293fef35a..c9da80d5eb1c 100644
--- a/board/compulab/trimslice/trimslice.c
+++ b/board/compulab/trimslice/trimslice.c
@@ -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
diff --git a/include/configs/trimslice.h b/include/configs/trimslice.h
index f81cfa2e354d..285dc7a9e660 100644
--- a/include/configs/trimslice.h
+++ b/include/configs/trimslice.h
@@ -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
-- 
2.0.4

^ permalink raw reply related	[flat|nested] 95+ messages in thread

* [U-Boot] [PATCH 18/23] ARM: tegra: Add Tegra30 PCIe device tree node
  2014-08-18  7:16 [U-Boot] [PATCH 00/23] ARM: tegra: Add PCIe support Thierry Reding
                   ` (16 preceding siblings ...)
  2014-08-18  7:16 ` [U-Boot] [PATCH 17/23] ARM: tegra: Enable PCIe on TrimSlice Thierry Reding
@ 2014-08-18  7:16 ` Thierry Reding
  2014-08-20 18:39   ` Stephen Warren
  2014-08-18  7:16 ` [U-Boot] [PATCH 19/23] ARM: tegra: Enable PCIe on Beaver Thierry Reding
                   ` (4 subsequent siblings)
  22 siblings, 1 reply; 95+ messages in thread
From: Thierry Reding @ 2014-08-18  7:16 UTC (permalink / raw)
  To: u-boot

From: Thierry Reding <treding@nvidia.com>

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

Signed-off-by: Thierry Reding <treding@nvidia.com>
---
 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

diff --git a/arch/arm/dts/tegra30.dtsi b/arch/arm/dts/tegra30.dtsi
index 7be3791fc9a6..ae0abf055a78 100644
--- a/arch/arm/dts/tegra30.dtsi
+++ b/arch/arm/dts/tegra30.dtsi
@@ -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>;
diff --git a/include/dt-bindings/clock/tegra30-car.h b/include/dt-bindings/clock/tegra30-car.h
new file mode 100644
index 000000000000..e40fae8f9a8d
--- /dev/null
+++ b/include/dt-bindings/clock/tegra30-car.h
@@ -0,0 +1,265 @@
+/*
+ * This header provides constants for binding nvidia,tegra30-car.
+ *
+ * The first 130 clocks are numbered to match the bits in the CAR's CLK_OUT_ENB
+ * registers. These IDs often match those in the CAR's RST_DEVICES registers,
+ * but not in all cases. Some bits in CLK_OUT_ENB affect multiple clocks. In
+ * this case, those clocks are assigned IDs above 160 in order to highlight
+ * this issue. Implementations that interpret these clock IDs as bit values
+ * within the CLK_OUT_ENB or RST_DEVICES registers should be careful to
+ * explicitly handle these special cases.
+ *
+ * The balance of the clocks controlled by the CAR are assigned IDs of 160 and
+ * above.
+ */
+
+#ifndef _DT_BINDINGS_CLOCK_TEGRA30_CAR_H
+#define _DT_BINDINGS_CLOCK_TEGRA30_CAR_H
+
+#define TEGRA30_CLK_CPU 0
+/* 1 */
+/* 2 */
+/* 3 */
+#define TEGRA30_CLK_RTC 4
+#define TEGRA30_CLK_TIMER 5
+#define TEGRA30_CLK_UARTA 6
+/* 7 (register bit affects uartb and vfir) */
+#define TEGRA30_CLK_GPIO 8
+#define TEGRA30_CLK_SDMMC2 9
+/* 10 (register bit affects spdif_in and spdif_out) */
+#define TEGRA30_CLK_I2S1 11
+#define TEGRA30_CLK_I2C1 12
+#define TEGRA30_CLK_NDFLASH 13
+#define TEGRA30_CLK_SDMMC1 14
+#define TEGRA30_CLK_SDMMC4 15
+/* 16 */
+#define TEGRA30_CLK_PWM 17
+#define TEGRA30_CLK_I2S2 18
+#define TEGRA30_CLK_EPP 19
+/* 20 (register bit affects vi and vi_sensor) */
+#define TEGRA30_CLK_GR2D 21
+#define TEGRA30_CLK_USBD 22
+#define TEGRA30_CLK_ISP 23
+#define TEGRA30_CLK_GR3D 24
+/* 25 */
+#define TEGRA30_CLK_DISP2 26
+#define TEGRA30_CLK_DISP1 27
+#define TEGRA30_CLK_HOST1X 28
+#define TEGRA30_CLK_VCP 29
+#define TEGRA30_CLK_I2S0 30
+#define TEGRA30_CLK_COP_CACHE 31
+
+#define TEGRA30_CLK_MC 32
+#define TEGRA30_CLK_AHBDMA 33
+#define TEGRA30_CLK_APBDMA 34
+/* 35 */
+#define TEGRA30_CLK_KBC 36
+#define TEGRA30_CLK_STATMON 37
+#define TEGRA30_CLK_PMC 38
+/* 39 (register bit affects fuse and fuse_burn) */
+#define TEGRA30_CLK_KFUSE 40
+#define TEGRA30_CLK_SBC1 41
+#define TEGRA30_CLK_NOR 42
+/* 43 */
+#define TEGRA30_CLK_SBC2 44
+/* 45 */
+#define TEGRA30_CLK_SBC3 46
+#define TEGRA30_CLK_I2C5 47
+#define TEGRA30_CLK_DSIA 48
+/* 49 (register bit affects cve and tvo) */
+#define TEGRA30_CLK_MIPI 50
+#define TEGRA30_CLK_HDMI 51
+#define TEGRA30_CLK_CSI 52
+#define TEGRA30_CLK_TVDAC 53
+#define TEGRA30_CLK_I2C2 54
+#define TEGRA30_CLK_UARTC 55
+/* 56 */
+#define TEGRA30_CLK_EMC 57
+#define TEGRA30_CLK_USB2 58
+#define TEGRA30_CLK_USB3 59
+#define TEGRA30_CLK_MPE 60
+#define TEGRA30_CLK_VDE 61
+#define TEGRA30_CLK_BSEA 62
+#define TEGRA30_CLK_BSEV 63
+
+#define TEGRA30_CLK_SPEEDO 64
+#define TEGRA30_CLK_UARTD 65
+#define TEGRA30_CLK_UARTE 66
+#define TEGRA30_CLK_I2C3 67
+#define TEGRA30_CLK_SBC4 68
+#define TEGRA30_CLK_SDMMC3 69
+#define TEGRA30_CLK_PCIE 70
+#define TEGRA30_CLK_OWR 71
+#define TEGRA30_CLK_AFI 72
+#define TEGRA30_CLK_CSITE 73
+#define TEGRA30_CLK_PCIEX 74
+#define TEGRA30_CLK_AVPUCQ 75
+#define TEGRA30_CLK_LA 76
+/* 77 */
+/* 78 */
+#define TEGRA30_CLK_DTV 79
+#define TEGRA30_CLK_NDSPEED 80
+#define TEGRA30_CLK_I2CSLOW 81
+#define TEGRA30_CLK_DSIB 82
+/* 83 */
+#define TEGRA30_CLK_IRAMA 84
+#define TEGRA30_CLK_IRAMB 85
+#define TEGRA30_CLK_IRAMC 86
+#define TEGRA30_CLK_IRAMD 87
+#define TEGRA30_CLK_CRAM2 88
+/* 89 */
+#define TEGRA30_CLK_AUDIO_2X 90 /* a/k/a audio_2x_sync_clk */
+/* 91 */
+#define TEGRA30_CLK_CSUS 92
+#define TEGRA30_CLK_CDEV2 93
+#define TEGRA30_CLK_CDEV1 94
+/* 95 */
+
+#define TEGRA30_CLK_CPU_G 96
+#define TEGRA30_CLK_CPU_LP 97
+#define TEGRA30_CLK_GR3D2 98
+#define TEGRA30_CLK_MSELECT 99
+#define TEGRA30_CLK_TSENSOR 100
+#define TEGRA30_CLK_I2S3 101
+#define TEGRA30_CLK_I2S4 102
+#define TEGRA30_CLK_I2C4 103
+#define TEGRA30_CLK_SBC5 104
+#define TEGRA30_CLK_SBC6 105
+#define TEGRA30_CLK_D_AUDIO 106
+#define TEGRA30_CLK_APBIF 107
+#define TEGRA30_CLK_DAM0 108
+#define TEGRA30_CLK_DAM1 109
+#define TEGRA30_CLK_DAM2 110
+#define TEGRA30_CLK_HDA2CODEC_2X 111
+#define TEGRA30_CLK_ATOMICS 112
+#define TEGRA30_CLK_AUDIO0_2X 113
+#define TEGRA30_CLK_AUDIO1_2X 114
+#define TEGRA30_CLK_AUDIO2_2X 115
+#define TEGRA30_CLK_AUDIO3_2X 116
+#define TEGRA30_CLK_AUDIO4_2X 117
+#define TEGRA30_CLK_SPDIF_2X 118
+#define TEGRA30_CLK_ACTMON 119
+#define TEGRA30_CLK_EXTERN1 120
+#define TEGRA30_CLK_EXTERN2 121
+#define TEGRA30_CLK_EXTERN3 122
+#define TEGRA30_CLK_SATA_OOB 123
+#define TEGRA30_CLK_SATA 124
+#define TEGRA30_CLK_HDA 125
+/* 126 */
+#define TEGRA30_CLK_SE 127
+
+#define TEGRA30_CLK_HDA2HDMI 128
+#define TEGRA30_CLK_SATA_COLD 129
+/* 130 */
+/* 131 */
+/* 132 */
+/* 133 */
+/* 134 */
+/* 135 */
+/* 136 */
+/* 137 */
+/* 138 */
+/* 139 */
+/* 140 */
+/* 141 */
+/* 142 */
+/* 143 */
+/* 144 */
+/* 145 */
+/* 146 */
+/* 147 */
+/* 148 */
+/* 149 */
+/* 150 */
+/* 151 */
+/* 152 */
+/* 153 */
+/* 154 */
+/* 155 */
+/* 156 */
+/* 157 */
+/* 158 */
+/* 159 */
+
+#define TEGRA30_CLK_UARTB 160
+#define TEGRA30_CLK_VFIR 161
+#define TEGRA30_CLK_SPDIF_IN 162
+#define TEGRA30_CLK_SPDIF_OUT 163
+#define TEGRA30_CLK_VI 164
+#define TEGRA30_CLK_VI_SENSOR 165
+#define TEGRA30_CLK_FUSE 166
+#define TEGRA30_CLK_FUSE_BURN 167
+#define TEGRA30_CLK_CVE 168
+#define TEGRA30_CLK_TVO 169
+#define TEGRA30_CLK_CLK_32K 170
+#define TEGRA30_CLK_CLK_M 171
+#define TEGRA30_CLK_CLK_M_DIV2 172
+#define TEGRA30_CLK_CLK_M_DIV4 173
+#define TEGRA30_CLK_PLL_REF 174
+#define TEGRA30_CLK_PLL_C 175
+#define TEGRA30_CLK_PLL_C_OUT1 176
+#define TEGRA30_CLK_PLL_M 177
+#define TEGRA30_CLK_PLL_M_OUT1 178
+#define TEGRA30_CLK_PLL_P 179
+#define TEGRA30_CLK_PLL_P_OUT1 180
+#define TEGRA30_CLK_PLL_P_OUT2 181
+#define TEGRA30_CLK_PLL_P_OUT3 182
+#define TEGRA30_CLK_PLL_P_OUT4 183
+#define TEGRA30_CLK_PLL_A 184
+#define TEGRA30_CLK_PLL_A_OUT0 185
+#define TEGRA30_CLK_PLL_D 186
+#define TEGRA30_CLK_PLL_D_OUT0 187
+#define TEGRA30_CLK_PLL_D2 188
+#define TEGRA30_CLK_PLL_D2_OUT0 189
+#define TEGRA30_CLK_PLL_U 190
+#define TEGRA30_CLK_PLL_X 191
+
+#define TEGRA30_CLK_PLL_X_OUT0 192
+#define TEGRA30_CLK_PLL_E 193
+#define TEGRA30_CLK_SPDIF_IN_SYNC 194
+#define TEGRA30_CLK_I2S0_SYNC 195
+#define TEGRA30_CLK_I2S1_SYNC 196
+#define TEGRA30_CLK_I2S2_SYNC 197
+#define TEGRA30_CLK_I2S3_SYNC 198
+#define TEGRA30_CLK_I2S4_SYNC 199
+#define TEGRA30_CLK_VIMCLK_SYNC 200
+#define TEGRA30_CLK_AUDIO0 201
+#define TEGRA30_CLK_AUDIO1 202
+#define TEGRA30_CLK_AUDIO2 203
+#define TEGRA30_CLK_AUDIO3 204
+#define TEGRA30_CLK_AUDIO4 205
+#define TEGRA30_CLK_SPDIF 206
+#define TEGRA30_CLK_CLK_OUT_1 207 /* (extern1) */
+#define TEGRA30_CLK_CLK_OUT_2 208 /* (extern2) */
+#define TEGRA30_CLK_CLK_OUT_3 209 /* (extern3) */
+#define TEGRA30_CLK_SCLK 210
+#define TEGRA30_CLK_BLINK 211
+#define TEGRA30_CLK_CCLK_G 212
+#define TEGRA30_CLK_CCLK_LP 213
+#define TEGRA30_CLK_TWD 214
+#define TEGRA30_CLK_CML0 215
+#define TEGRA30_CLK_CML1 216
+#define TEGRA30_CLK_HCLK 217
+#define TEGRA30_CLK_PCLK 218
+/* 219 */
+/* 220 */
+/* 221 */
+/* 222 */
+/* 223 */
+
+/* 288 */
+/* 289 */
+/* 290 */
+/* 291 */
+/* 292 */
+/* 293 */
+/* 294 */
+/* 295 */
+/* 296 */
+/* 297 */
+/* 298 */
+/* 299 */
+#define TEGRA30_CLK_CLK_OUT_1_MUX 300
+#define TEGRA30_CLK_CLK_MAX 301
+
+#endif	/* _DT_BINDINGS_CLOCK_TEGRA30_CAR_H */
-- 
2.0.4

^ permalink raw reply related	[flat|nested] 95+ messages in thread

* [U-Boot] [PATCH 19/23] ARM: tegra: Enable PCIe on Beaver
  2014-08-18  7:16 [U-Boot] [PATCH 00/23] ARM: tegra: Add PCIe support Thierry Reding
                   ` (17 preceding siblings ...)
  2014-08-18  7:16 ` [U-Boot] [PATCH 18/23] ARM: tegra: Add Tegra30 PCIe device tree node Thierry Reding
@ 2014-08-18  7:16 ` Thierry Reding
  2014-08-19 13:48   ` Marcel Ziswiler
  2014-08-20 18:43   ` Stephen Warren
  2014-08-18  7:16 ` [U-Boot] [PATCH 20/23] ARM: tegra: Enable PCIe on Cardhu Thierry Reding
                   ` (3 subsequent siblings)
  22 siblings, 2 replies; 95+ messages in thread
From: Thierry Reding @ 2014-08-18  7:16 UTC (permalink / raw)
  To: u-boot

From: Thierry Reding <treding@nvidia.com>

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.

Signed-off-by: Thierry Reding <treding@nvidia.com>
---
 arch/arm/dts/tegra30-beaver.dts | 166 ++++++++++++++++++++++++++++++++++++++++
 board/nvidia/cardhu/cardhu.c    |  56 ++++++++++++++
 include/configs/beaver.h        |  10 +++
 3 files changed, 232 insertions(+)

diff --git a/arch/arm/dts/tegra30-beaver.dts b/arch/arm/dts/tegra30-beaver.dts
index 85e62e9db32e..e113801fdfb4 100644
--- a/arch/arm/dts/tegra30-beaver.dts
+++ b/arch/arm/dts/tegra30-beaver.dts
@@ -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>;
+		};
+	};
 };
diff --git a/board/nvidia/cardhu/cardhu.c b/board/nvidia/cardhu/cardhu.c
index cc0e5e130fda..5738dd1f5195 100644
--- a/board/nvidia/cardhu/cardhu.c
+++ b/board/nvidia/cardhu/cardhu.c
@@ -8,8 +8,11 @@
 #include <common.h>
 #include <asm/arch/pinmux.h>
 #include <asm/arch/gp_padctrl.h>
+#include <asm/arch/gpio.h>
+#include <asm/gpio.h>
 #include "pinmux-config-cardhu.h"
 #include <i2c.h>
+#include <netdev.h>
 
 #define PMU_I2C_ADDRESS		0x2D
 #define MAX_I2C_RETRY		3
@@ -76,3 +79,56 @@ void pin_mux_mmc(void)
 	board_sdmmc_voltage_init();
 }
 #endif	/* MMC */
+
+#ifdef CONFIG_PCI_TEGRA
+int tegra_pcie_board_init(void)
+{
+	unsigned int old_bus;
+	u8 addr, data[1];
+	int err;
+
+	old_bus = i2c_get_bus_num();
+
+	err = i2c_set_bus_num(0);
+	if (err) {
+		debug("failed to set I2C bus\n");
+		return err;
+	}
+
+	/* TPS659110: LDO1_REG = 1.05V, ACTIVE */
+	data[0] = 0x15;
+	addr = 0x30;
+
+	err = i2c_write(PMU_I2C_ADDRESS, addr, 1, data, 1);
+	if (err) {
+		debug("failed to set VDD supply\n");
+		return err;
+	}
+
+	/* GPIO: PEX = 3.3V */
+	err = gpio_request(GPIO_PL7, "PEX");
+	if (err < 0)
+		return err;
+
+	gpio_direction_output(GPIO_PL7, 1);
+
+	/* TPS659110: LDO2_REG = 1.05V, ACTIVE */
+	data[0] = 0x15;
+	addr = 0x31;
+
+	err = i2c_read(PMU_I2C_ADDRESS, addr, 1, data, 1);
+	if (err) {
+		debug("failed to set AVDD supply\n");
+		return err;
+	}
+
+	i2c_set_bus_num(old_bus);
+
+	return 0;
+}
+
+int board_eth_init(bd_t *bis)
+{
+	return pci_eth_init(bis);
+}
+#endif /* PCI */
diff --git a/include/configs/beaver.h b/include/configs/beaver.h
index ae831127985f..bc96f6438d3c 100644
--- a/include/configs/beaver.h
+++ b/include/configs/beaver.h
@@ -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
-- 
2.0.4

^ permalink raw reply related	[flat|nested] 95+ messages in thread

* [U-Boot] [PATCH 20/23] ARM: tegra: Enable PCIe on Cardhu
  2014-08-18  7:16 [U-Boot] [PATCH 00/23] ARM: tegra: Add PCIe support Thierry Reding
                   ` (18 preceding siblings ...)
  2014-08-18  7:16 ` [U-Boot] [PATCH 19/23] ARM: tegra: Enable PCIe on Beaver Thierry Reding
@ 2014-08-18  7:16 ` Thierry Reding
  2014-08-18  7:16 ` [U-Boot] [PATCH 21/23] ARM: tegra: Add GIC for Tegra124 Thierry Reding
                   ` (2 subsequent siblings)
  22 siblings, 0 replies; 95+ messages in thread
From: Thierry Reding @ 2014-08-18  7:16 UTC (permalink / raw)
  To: u-boot

From: Thierry Reding <treding@nvidia.com>

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.

Signed-off-by: Thierry Reding <treding@nvidia.com>
---
 arch/arm/dts/tegra30-cardhu.dts | 357 ++++++++++++++++++++++++++++++++++++++++
 include/configs/cardhu.h        |  10 ++
 2 files changed, 367 insertions(+)

diff --git a/arch/arm/dts/tegra30-cardhu.dts b/arch/arm/dts/tegra30-cardhu.dts
index ea2cf76ff3a8..8d3e85ab263b 100644
--- a/arch/arm/dts/tegra30-cardhu.dts
+++ b/arch/arm/dts/tegra30-cardhu.dts
@@ -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>;
+		};
+	};
 };
diff --git a/include/configs/cardhu.h b/include/configs/cardhu.h
index 59f429cf5784..f5f4a860f6a9 100644
--- a/include/configs/cardhu.h
+++ b/include/configs/cardhu.h
@@ -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
-- 
2.0.4

^ permalink raw reply related	[flat|nested] 95+ messages in thread

* [U-Boot] [PATCH 21/23] ARM: tegra: Add GIC for Tegra124
  2014-08-18  7:16 [U-Boot] [PATCH 00/23] ARM: tegra: Add PCIe support Thierry Reding
                   ` (19 preceding siblings ...)
  2014-08-18  7:16 ` [U-Boot] [PATCH 20/23] ARM: tegra: Enable PCIe on Cardhu Thierry Reding
@ 2014-08-18  7:16 ` Thierry Reding
  2014-08-20 18:45   ` Stephen Warren
  2014-08-18  7:16 ` [U-Boot] [PATCH 22/23] ARM: tegra: Add Tegra124 PCIe device tree node Thierry Reding
  2014-08-18  7:16 ` [U-Boot] [PATCH 23/23] ARM: tegra: Enable PCIe on Jetson TK1 Thierry Reding
  22 siblings, 1 reply; 95+ messages in thread
From: Thierry Reding @ 2014-08-18  7:16 UTC (permalink / raw)
  To: u-boot

From: Thierry Reding <treding@nvidia.com>

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.

Signed-off-by: Thierry Reding <treding@nvidia.com>
---
 arch/arm/dts/tegra124.dtsi | 13 +++++++++++++
 1 file changed, 13 insertions(+)

diff --git a/arch/arm/dts/tegra124.dtsi b/arch/arm/dts/tegra124.dtsi
index d48f1a34ec3c..510fa332ef98 100644
--- a/arch/arm/dts/tegra124.dtsi
+++ b/arch/arm/dts/tegra124.dtsi
@@ -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";
-- 
2.0.4

^ permalink raw reply related	[flat|nested] 95+ messages in thread

* [U-Boot] [PATCH 22/23] ARM: tegra: Add Tegra124 PCIe device tree node
  2014-08-18  7:16 [U-Boot] [PATCH 00/23] ARM: tegra: Add PCIe support Thierry Reding
                   ` (20 preceding siblings ...)
  2014-08-18  7:16 ` [U-Boot] [PATCH 21/23] ARM: tegra: Add GIC for Tegra124 Thierry Reding
@ 2014-08-18  7:16 ` Thierry Reding
  2014-08-20 18:46   ` Stephen Warren
  2014-08-18  7:16 ` [U-Boot] [PATCH 23/23] ARM: tegra: Enable PCIe on Jetson TK1 Thierry Reding
  22 siblings, 1 reply; 95+ messages in thread
From: Thierry Reding @ 2014-08-18  7:16 UTC (permalink / raw)
  To: u-boot

From: Thierry Reding <treding@nvidia.com>

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

Signed-off-by: Thierry Reding <treding@nvidia.com>
---
 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

diff --git a/arch/arm/dts/tegra124.dtsi b/arch/arm/dts/tegra124.dtsi
index 510fa332ef98..d6dee96b12d6 100644
--- a/arch/arm/dts/tegra124.dtsi
+++ b/arch/arm/dts/tegra124.dtsi
@@ -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>;
diff --git a/include/dt-bindings/clock/tegra124-car.h b/include/dt-bindings/clock/tegra124-car.h
new file mode 100644
index 000000000000..433528ab5161
--- /dev/null
+++ b/include/dt-bindings/clock/tegra124-car.h
@@ -0,0 +1,341 @@
+/*
+ * This header provides constants for binding nvidia,tegra124-car.
+ *
+ * The first 192 clocks are numbered to match the bits in the CAR's CLK_OUT_ENB
+ * registers. These IDs often match those in the CAR's RST_DEVICES registers,
+ * but not in all cases. Some bits in CLK_OUT_ENB affect multiple clocks. In
+ * this case, those clocks are assigned IDs above 185 in order to highlight
+ * this issue. Implementations that interpret these clock IDs as bit values
+ * within the CLK_OUT_ENB or RST_DEVICES registers should be careful to
+ * explicitly handle these special cases.
+ *
+ * The balance of the clocks controlled by the CAR are assigned IDs of 185 and
+ * above.
+ */
+
+#ifndef _DT_BINDINGS_CLOCK_TEGRA124_CAR_H
+#define _DT_BINDINGS_CLOCK_TEGRA124_CAR_H
+
+/* 0 */
+/* 1 */
+/* 2 */
+#define TEGRA124_CLK_ISPB 3
+#define TEGRA124_CLK_RTC 4
+#define TEGRA124_CLK_TIMER 5
+#define TEGRA124_CLK_UARTA 6
+/* 7 (register bit affects uartb and vfir) */
+/* 8 */
+#define TEGRA124_CLK_SDMMC2 9
+/* 10 (register bit affects spdif_in and spdif_out) */
+#define TEGRA124_CLK_I2S1 11
+#define TEGRA124_CLK_I2C1 12
+/* 13 */
+#define TEGRA124_CLK_SDMMC1 14
+#define TEGRA124_CLK_SDMMC4 15
+/* 16 */
+#define TEGRA124_CLK_PWM 17
+#define TEGRA124_CLK_I2S2 18
+/* 20 (register bit affects vi and vi_sensor) */
+/* 21 */
+#define TEGRA124_CLK_USBD 22
+#define TEGRA124_CLK_ISP 23
+/* 26 */
+/* 25 */
+#define TEGRA124_CLK_DISP2 26
+#define TEGRA124_CLK_DISP1 27
+#define TEGRA124_CLK_HOST1X 28
+#define TEGRA124_CLK_VCP 29
+#define TEGRA124_CLK_I2S0 30
+/* 31 */
+
+/* 32 */
+/* 33 */
+#define TEGRA124_CLK_APBDMA 34
+/* 35 */
+#define TEGRA124_CLK_KBC 36
+/* 37 */
+/* 38 */
+/* 39 (register bit affects fuse and fuse_burn) */
+#define TEGRA124_CLK_KFUSE 40
+#define TEGRA124_CLK_SBC1 41
+#define TEGRA124_CLK_NOR 42
+/* 43 */
+#define TEGRA124_CLK_SBC2 44
+/* 45 */
+#define TEGRA124_CLK_SBC3 46
+#define TEGRA124_CLK_I2C5 47
+#define TEGRA124_CLK_DSIA 48
+/* 49 */
+#define TEGRA124_CLK_MIPI 50
+#define TEGRA124_CLK_HDMI 51
+#define TEGRA124_CLK_CSI 52
+/* 53 */
+#define TEGRA124_CLK_I2C2 54
+#define TEGRA124_CLK_UARTC 55
+#define TEGRA124_CLK_MIPI_CAL 56
+#define TEGRA124_CLK_EMC 57
+#define TEGRA124_CLK_USB2 58
+#define TEGRA124_CLK_USB3 59
+/* 60 */
+#define TEGRA124_CLK_VDE 61
+#define TEGRA124_CLK_BSEA 62
+#define TEGRA124_CLK_BSEV 63
+
+/* 64 */
+#define TEGRA124_CLK_UARTD 65
+/* 66 */
+#define TEGRA124_CLK_I2C3 67
+#define TEGRA124_CLK_SBC4 68
+#define TEGRA124_CLK_SDMMC3 69
+#define TEGRA124_CLK_PCIE 70
+#define TEGRA124_CLK_OWR 71
+#define TEGRA124_CLK_AFI 72
+#define TEGRA124_CLK_CSITE 73
+/* 74 */
+/* 75 */
+#define TEGRA124_CLK_LA 76
+#define TEGRA124_CLK_TRACE 77
+#define TEGRA124_CLK_SOC_THERM 78
+#define TEGRA124_CLK_DTV 79
+/* 80 */
+#define TEGRA124_CLK_I2CSLOW 81
+#define TEGRA124_CLK_DSIB 82
+#define TEGRA124_CLK_TSEC 83
+/* 84 */
+/* 85 */
+/* 86 */
+/* 87 */
+/* 88 */
+#define TEGRA124_CLK_XUSB_HOST 89
+/* 90 */
+#define TEGRA124_CLK_MSENC 91
+#define TEGRA124_CLK_CSUS 92
+/* 93 */
+/* 94 */
+/* 95 (bit affects xusb_dev and xusb_dev_src) */
+
+/* 96 */
+/* 97 */
+/* 98 */
+#define TEGRA124_CLK_MSELECT 99
+#define TEGRA124_CLK_TSENSOR 100
+#define TEGRA124_CLK_I2S3 101
+#define TEGRA124_CLK_I2S4 102
+#define TEGRA124_CLK_I2C4 103
+#define TEGRA124_CLK_SBC5 104
+#define TEGRA124_CLK_SBC6 105
+#define TEGRA124_CLK_D_AUDIO 106
+#define TEGRA124_CLK_APBIF 107
+#define TEGRA124_CLK_DAM0 108
+#define TEGRA124_CLK_DAM1 109
+#define TEGRA124_CLK_DAM2 110
+#define TEGRA124_CLK_HDA2CODEC_2X 111
+/* 112 */
+#define TEGRA124_CLK_AUDIO0_2X 113
+#define TEGRA124_CLK_AUDIO1_2X 114
+#define TEGRA124_CLK_AUDIO2_2X 115
+#define TEGRA124_CLK_AUDIO3_2X 116
+#define TEGRA124_CLK_AUDIO4_2X 117
+#define TEGRA124_CLK_SPDIF_2X 118
+#define TEGRA124_CLK_ACTMON 119
+#define TEGRA124_CLK_EXTERN1 120
+#define TEGRA124_CLK_EXTERN2 121
+#define TEGRA124_CLK_EXTERN3 122
+#define TEGRA124_CLK_SATA_OOB 123
+#define TEGRA124_CLK_SATA 124
+#define TEGRA124_CLK_HDA 125
+/* 126 */
+#define TEGRA124_CLK_SE 127
+
+#define TEGRA124_CLK_HDA2HDMI 128
+#define TEGRA124_CLK_SATA_COLD 129
+/* 130 */
+/* 131 */
+/* 132 */
+/* 133 */
+/* 134 */
+/* 135 */
+/* 136 */
+/* 137 */
+/* 138 */
+/* 139 */
+/* 140 */
+/* 141 */
+/* 142 */
+/* 143 (bit affects xusb_falcon_src, xusb_fs_src, */
+/*      xusb_host_src and xusb_ss_src) */
+#define TEGRA124_CLK_CILAB 144
+#define TEGRA124_CLK_CILCD 145
+#define TEGRA124_CLK_CILE 146
+#define TEGRA124_CLK_DSIALP 147
+#define TEGRA124_CLK_DSIBLP 148
+#define TEGRA124_CLK_ENTROPY 149
+#define TEGRA124_CLK_DDS 150
+/* 151 */
+#define TEGRA124_CLK_DP2 152
+#define TEGRA124_CLK_AMX 153
+#define TEGRA124_CLK_ADX 154
+/* 155 (bit affects dfll_ref and dfll_soc) */
+#define TEGRA124_CLK_XUSB_SS 156
+/* 157 */
+/* 158 */
+/* 159 */
+
+/* 160 */
+/* 161 */
+/* 162 */
+/* 163 */
+/* 164 */
+/* 165 */
+#define TEGRA124_CLK_I2C6 166
+/* 167 */
+/* 168 */
+/* 169 */
+/* 170 */
+#define TEGRA124_CLK_VIM2_CLK 171
+/* 172 */
+/* 173 */
+/* 174 */
+/* 175 */
+#define TEGRA124_CLK_HDMI_AUDIO 176
+#define TEGRA124_CLK_CLK72MHZ 177
+#define TEGRA124_CLK_VIC03 178
+/* 179 */
+#define TEGRA124_CLK_ADX1 180
+#define TEGRA124_CLK_DPAUX 181
+#define TEGRA124_CLK_SOR0 182
+/* 183 */
+#define TEGRA124_CLK_GPU 184
+#define TEGRA124_CLK_AMX1 185
+/* 186 */
+/* 187 */
+/* 188 */
+/* 189 */
+/* 190 */
+/* 191 */
+#define TEGRA124_CLK_UARTB 192
+#define TEGRA124_CLK_VFIR 193
+#define TEGRA124_CLK_SPDIF_IN 194
+#define TEGRA124_CLK_SPDIF_OUT 195
+#define TEGRA124_CLK_VI 196
+#define TEGRA124_CLK_VI_SENSOR 197
+#define TEGRA124_CLK_FUSE 198
+#define TEGRA124_CLK_FUSE_BURN 199
+#define TEGRA124_CLK_CLK_32K 200
+#define TEGRA124_CLK_CLK_M 201
+#define TEGRA124_CLK_CLK_M_DIV2 202
+#define TEGRA124_CLK_CLK_M_DIV4 203
+#define TEGRA124_CLK_PLL_REF 204
+#define TEGRA124_CLK_PLL_C 205
+#define TEGRA124_CLK_PLL_C_OUT1 206
+#define TEGRA124_CLK_PLL_C2 207
+#define TEGRA124_CLK_PLL_C3 208
+#define TEGRA124_CLK_PLL_M 209
+#define TEGRA124_CLK_PLL_M_OUT1 210
+#define TEGRA124_CLK_PLL_P 211
+#define TEGRA124_CLK_PLL_P_OUT1 212
+#define TEGRA124_CLK_PLL_P_OUT2 213
+#define TEGRA124_CLK_PLL_P_OUT3 214
+#define TEGRA124_CLK_PLL_P_OUT4 215
+#define TEGRA124_CLK_PLL_A 216
+#define TEGRA124_CLK_PLL_A_OUT0 217
+#define TEGRA124_CLK_PLL_D 218
+#define TEGRA124_CLK_PLL_D_OUT0 219
+#define TEGRA124_CLK_PLL_D2 220
+#define TEGRA124_CLK_PLL_D2_OUT0 221
+#define TEGRA124_CLK_PLL_U 222
+#define TEGRA124_CLK_PLL_U_480M 223
+
+#define TEGRA124_CLK_PLL_U_60M 224
+#define TEGRA124_CLK_PLL_U_48M 225
+#define TEGRA124_CLK_PLL_U_12M 226
+#define TEGRA124_CLK_PLL_X 227
+#define TEGRA124_CLK_PLL_X_OUT0 228
+#define TEGRA124_CLK_PLL_RE_VCO 229
+#define TEGRA124_CLK_PLL_RE_OUT 230
+#define TEGRA124_CLK_PLL_E 231
+#define TEGRA124_CLK_SPDIF_IN_SYNC 232
+#define TEGRA124_CLK_I2S0_SYNC 233
+#define TEGRA124_CLK_I2S1_SYNC 234
+#define TEGRA124_CLK_I2S2_SYNC 235
+#define TEGRA124_CLK_I2S3_SYNC 236
+#define TEGRA124_CLK_I2S4_SYNC 237
+#define TEGRA124_CLK_VIMCLK_SYNC 238
+#define TEGRA124_CLK_AUDIO0 239
+#define TEGRA124_CLK_AUDIO1 240
+#define TEGRA124_CLK_AUDIO2 241
+#define TEGRA124_CLK_AUDIO3 242
+#define TEGRA124_CLK_AUDIO4 243
+#define TEGRA124_CLK_SPDIF 244
+#define TEGRA124_CLK_CLK_OUT_1 245
+#define TEGRA124_CLK_CLK_OUT_2 246
+#define TEGRA124_CLK_CLK_OUT_3 247
+#define TEGRA124_CLK_BLINK 248
+/* 249 */
+/* 250 */
+/* 251 */
+#define TEGRA124_CLK_XUSB_HOST_SRC 252
+#define TEGRA124_CLK_XUSB_FALCON_SRC 253
+#define TEGRA124_CLK_XUSB_FS_SRC 254
+#define TEGRA124_CLK_XUSB_SS_SRC 255
+
+#define TEGRA124_CLK_XUSB_DEV_SRC 256
+#define TEGRA124_CLK_XUSB_DEV 257
+#define TEGRA124_CLK_XUSB_HS_SRC 258
+#define TEGRA124_CLK_SCLK 259
+#define TEGRA124_CLK_HCLK 260
+#define TEGRA124_CLK_PCLK 261
+#define TEGRA124_CLK_CCLK_G 262
+#define TEGRA124_CLK_CCLK_LP 263
+#define TEGRA124_CLK_DFLL_REF 264
+#define TEGRA124_CLK_DFLL_SOC 265
+#define TEGRA124_CLK_VI_SENSOR2 266
+#define TEGRA124_CLK_PLL_P_OUT5 267
+#define TEGRA124_CLK_CML0 268
+#define TEGRA124_CLK_CML1 269
+#define TEGRA124_CLK_PLL_C4 270
+#define TEGRA124_CLK_PLL_DP 271
+#define TEGRA124_CLK_PLL_E_MUX 272
+/* 273 */
+/* 274 */
+/* 275 */
+/* 276 */
+/* 277 */
+/* 278 */
+/* 279 */
+/* 280 */
+/* 281 */
+/* 282 */
+/* 283 */
+/* 284 */
+/* 285 */
+/* 286 */
+/* 287 */
+
+/* 288 */
+/* 289 */
+/* 290 */
+/* 291 */
+/* 292 */
+/* 293 */
+/* 294 */
+/* 295 */
+/* 296 */
+/* 297 */
+/* 298 */
+/* 299 */
+#define TEGRA124_CLK_AUDIO0_MUX 300
+#define TEGRA124_CLK_AUDIO1_MUX 301
+#define TEGRA124_CLK_AUDIO2_MUX 302
+#define TEGRA124_CLK_AUDIO3_MUX 303
+#define TEGRA124_CLK_AUDIO4_MUX 304
+#define TEGRA124_CLK_SPDIF_MUX 305
+#define TEGRA124_CLK_CLK_OUT_1_MUX 306
+#define TEGRA124_CLK_CLK_OUT_2_MUX 307
+#define TEGRA124_CLK_CLK_OUT_3_MUX 308
+#define TEGRA124_CLK_DSIA_MUX 309
+#define TEGRA124_CLK_DSIB_MUX 310
+#define TEGRA124_CLK_SOR0_LVDS 311
+#define TEGRA124_CLK_CLK_MAX 312
+
+#endif	/* _DT_BINDINGS_CLOCK_TEGRA124_CAR_H */
-- 
2.0.4

^ permalink raw reply related	[flat|nested] 95+ messages in thread

* [U-Boot] [PATCH 23/23] ARM: tegra: Enable PCIe on Jetson TK1
  2014-08-18  7:16 [U-Boot] [PATCH 00/23] ARM: tegra: Add PCIe support Thierry Reding
                   ` (21 preceding siblings ...)
  2014-08-18  7:16 ` [U-Boot] [PATCH 22/23] ARM: tegra: Add Tegra124 PCIe device tree node Thierry Reding
@ 2014-08-18  7:16 ` Thierry Reding
  2014-08-18 18:37   ` Simon Glass
                     ` (3 more replies)
  22 siblings, 4 replies; 95+ messages in thread
From: Thierry Reding @ 2014-08-18  7:16 UTC (permalink / raw)
  To: u-boot

From: Thierry Reding <treding@nvidia.com>

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.

Signed-off-by: Thierry Reding <treding@nvidia.com>
---
 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(+)

diff --git a/arch/arm/dts/tegra124-jetson-tk1.dts b/arch/arm/dts/tegra124-jetson-tk1.dts
index f61736f0ef0f..f594644de74e 100644
--- a/arch/arm/dts/tegra124-jetson-tk1.dts
+++ b/arch/arm/dts/tegra124-jetson-tk1.dts
@@ -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>;
+		};
+	};
 };
diff --git a/board/nvidia/jetson-tk1/jetson-tk1.c b/board/nvidia/jetson-tk1/jetson-tk1.c
index 5d37718f3b89..c1deaa11d63e 100644
--- a/board/nvidia/jetson-tk1/jetson-tk1.c
+++ b/board/nvidia/jetson-tk1/jetson-tk1.c
@@ -6,9 +6,25 @@
  */
 
 #include <common.h>
+#include <errno.h>
 #include <asm/arch/gpio.h>
 #include <asm/arch/pinmux.h>
 #include "pinmux-config-jetson-tk1.h"
+#include <i2c.h>
+#include <netdev.h>
+
+#define PMU_I2C_ADDRESS 0x40
+#define AS3722_DEVICE_ID 0x0c
+
+#define AS3722_SD_VOLTAGE(n) (0x00 + (n))
+#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_INVERT (1 << 7)
+#define AS3722_GPIO_SIGNAL_OUT 0x20
+#define AS3722_SD_CONTROL 0x4d
+#define AS3722_ASIC_ID1 0x90
+#define AS3722_ASIC_ID2 0x91
 
 /*
  * Routine: pinmux_init
@@ -27,3 +43,205 @@ void pinmux_init(void)
 	pinmux_config_drvgrp_table(jetson_tk1_drvgrps,
 				   ARRAY_SIZE(jetson_tk1_drvgrps));
 }
+
+#ifdef CONFIG_PCI_TEGRA
+static int as3722_read(u8 reg, u8 *value)
+{
+	int err;
+
+	err = i2c_read(PMU_I2C_ADDRESS, reg, 1, value, 1);
+	if (err < 0)
+		return err;
+
+	return 0;
+}
+
+static int as3722_write(u8 reg, u8 value)
+{
+	int err;
+
+	err = i2c_write(PMU_I2C_ADDRESS, reg, 1, &value, 1);
+	if (err < 0)
+		return err;
+
+	return 0;
+}
+
+static int as3722_read_id(u8 *id, u8 *revision)
+{
+	int err;
+
+	err = as3722_read(AS3722_ASIC_ID1, id);
+	if (err) {
+		error("as3722: failed to read ID1 register: %d\n", err);
+		return err;
+	}
+
+	err = as3722_read(AS3722_ASIC_ID2, revision);
+	if (err) {
+		error("as3722: failed to read ID2 register: %d\n", err);
+		return err;
+	}
+
+	return 0;
+}
+
+static int as3722_sd_enable(u8 sd)
+{
+	u8 value;
+	int err;
+
+	err = as3722_read(AS3722_SD_CONTROL, &value);
+	if (err) {
+		error("as3722: failed to read SD control register: %d\n", err);
+		return err;
+	}
+
+	value |= 1 << sd;
+
+	err = as3722_write(AS3722_SD_CONTROL, value);
+	if (err < 0) {
+		error("as3722: failed to write SD control register: %d\n", err);
+		return err;
+	}
+
+	return 0;
+}
+
+static int as3722_sd_set_voltage(u8 sd, u8 value)
+{
+	int err;
+
+	if (sd > 6)
+		return -EINVAL;
+
+	err = as3722_write(AS3722_SD_VOLTAGE(sd), value);
+	if (err < 0) {
+		error("as3722: failed to write SD%u voltage register: %d\n", sd, err);
+		return err;
+	}
+
+	return 0;
+}
+
+static int as3722_gpio_set(u8 gpio, u8 level)
+{
+	u8 value;
+	int err;
+
+	if (gpio > 7)
+		return -EINVAL;
+
+	err = as3722_read(AS3722_GPIO_SIGNAL_OUT, &value);
+	if (err < 0) {
+		error("as3722: failed to read GPIO signal out register: %d\n",
+		      err);
+		return err;
+	}
+
+	if (level == 0)
+		value &= ~(1 << gpio);
+	else
+		value |= 1 << gpio;
+
+	err = as3722_write(AS3722_GPIO_SIGNAL_OUT, value);
+	if (err) {
+		error("as3722: failed to set GPIO#%u %s: %d\n", gpio,
+		      (level == 0) ? "low" : "high", err);
+		return err;
+	}
+
+	return 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;
+	}
+
+	return 0;
+}
+
+int tegra_pcie_board_init(void)
+{
+	u8 id, revision, value;
+	unsigned int old_bus;
+	int err;
+
+	old_bus = i2c_get_bus_num();
+
+	err = i2c_set_bus_num(0);
+	if (err) {
+		error("failed to set I2C bus\n");
+		return err;
+	}
+
+	err = as3722_read_id(&id, &revision);
+	if (err < 0) {
+		error("as3722: failed to read ID: %d\n", err);
+		return err;
+	}
+
+	if (id != AS3722_DEVICE_ID) {
+		error("as3722: PMIC is not an AS3722\n");
+		return -ENODEV;
+	}
+
+	err = as3722_sd_enable(4);
+	if (err < 0) {
+		error("as3722: failed to enable SD4: %d\n", err);
+		return err;
+	}
+
+	err = as3722_sd_set_voltage(4, 0x24);
+	if (err < 0) {
+		error("as3722: failed to set SD4 voltage: %d\n", err);
+		return err;
+	}
+
+	value = AS3722_GPIO_CONTROL_MODE_OUTPUT_VDDH |
+		AS3722_GPIO_CONTROL_INVERT;
+
+	err = as3722_write(AS3722_GPIO_CONTROL(1), value);
+	if (err) {
+		error("as3722: failed to configure GPIO#1 as output: %d\n", err);
+		return err;
+	}
+
+	err = as3722_gpio_direction_output(2, 1);
+	if (err < 0) {
+		error("as3722: failed to set GPIO#2 high: %d\n", err);
+		return err;
+	}
+
+	i2c_set_bus_num(old_bus);
+
+	return 0;
+}
+
+int board_eth_init(bd_t *bis)
+{
+	return pci_eth_init(bis);
+}
+#endif /* PCI */
diff --git a/include/configs/jetson-tk1.h b/include/configs/jetson-tk1.h
index 0b9e5b699fa6..b0393509681c 100644
--- a/include/configs/jetson-tk1.h
+++ b/include/configs/jetson-tk1.h
@@ -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
-- 
2.0.4

^ permalink raw reply related	[flat|nested] 95+ messages in thread

* [U-Boot] [PATCH 01/23] fdt: Add functions to query a node's #address- and #size-cells
  2014-08-18  7:16 ` [U-Boot] [PATCH 01/23] fdt: Add functions to query a node's #address- and #size-cells Thierry Reding
@ 2014-08-18 17:52   ` Simon Glass
  2014-08-19 10:59     ` Thierry Reding
  0 siblings, 1 reply; 95+ messages in thread
From: Simon Glass @ 2014-08-18 17:52 UTC (permalink / raw)
  To: u-boot

Hi Thierry,

On 18 August 2014 01:16, Thierry Reding <thierry.reding@gmail.com> wrote:
> From: Thierry Reding <treding@nvidia.com>
>
> 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.
>
> Signed-off-by: Thierry Reding <treding@nvidia.com>
> ---
>  include/libfdt.h    | 28 ++++++++++++++++++++++++++++
>  lib/libfdt/fdt_ro.c | 36 ++++++++++++++++++++++++++++++++++++
>  2 files changed, 64 insertions(+)
>
> diff --git a/include/libfdt.h b/include/libfdt.h
> index a1ef1e15df3d..e7f991b388cf 100644
> --- a/include/libfdt.h
> +++ b/include/libfdt.h
> @@ -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);

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

> +
> +/**
> + * fdt_n_size_cells() - find the number of size cells required by a node

Also fdt_size_cells().

Regards,
Simon

^ permalink raw reply	[flat|nested] 95+ messages in thread

* [U-Boot] [PATCH 02/23] fdt: Add a function to get the index of a string
  2014-08-18  7:16 ` [U-Boot] [PATCH 02/23] fdt: Add a function to get the index of a string Thierry Reding
@ 2014-08-18 17:58   ` Simon Glass
  2014-08-19 11:13     ` Thierry Reding
  0 siblings, 1 reply; 95+ messages in thread
From: Simon Glass @ 2014-08-18 17:58 UTC (permalink / raw)
  To: u-boot

Hi Thierry,

On 18 August 2014 01:16, Thierry Reding <thierry.reding@gmail.com> wrote:
> From: Thierry Reding <treding@nvidia.com>
>
> 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.
>
> Signed-off-by: Thierry Reding <treding@nvidia.com>
> ---
>  include/libfdt.h    | 11 +++++++++++
>  lib/libfdt/fdt_ro.c | 28 ++++++++++++++++++++++++++++
>  2 files changed, 39 insertions(+)
>
> diff --git a/include/libfdt.h b/include/libfdt.h
> index e7f991b388cf..4d7fb2681669 100644
> --- a/include/libfdt.h
> +++ b/include/libfdt.h
> @@ -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)                           */
>  /**********************************************************************/
> diff --git a/lib/libfdt/fdt_ro.c b/lib/libfdt/fdt_ro.c
> index 17cd11333c1e..f211c64ca7ca 100644
> --- a/lib/libfdt/fdt_ro.c
> +++ b/lib/libfdt/fdt_ro.c
> @@ -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);

This can go outside the loop.

> +               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?

> +               index++;
> +       }
> +
> +       return -FDT_ERR_NOTFOUND;
> +}
> +
>  int fdt_node_check_compatible(const void *fdt, int nodeoffset,
>                               const char *compatible)
>  {
> --
> 2.0.4
>

Regards,
Simon

^ permalink raw reply	[flat|nested] 95+ messages in thread

* [U-Boot] [PATCH 03/23] fdt: Add resource parsing functions
  2014-08-18  7:16 ` [U-Boot] [PATCH 03/23] fdt: Add resource parsing functions Thierry Reding
@ 2014-08-18 18:06   ` Simon Glass
  2014-08-19 11:35     ` Thierry Reding
  0 siblings, 1 reply; 95+ messages in thread
From: Simon Glass @ 2014-08-18 18:06 UTC (permalink / raw)
  To: u-boot

Hi Thierry,

On 18 August 2014 01:16, Thierry Reding <thierry.reding@gmail.com> wrote:
> From: Thierry Reding <treding@nvidia.com>
>
> 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.
>
> Signed-off-by: Thierry Reding <treding@nvidia.com>
> ---
>  include/fdtdec.h | 48 ++++++++++++++++++++++++++++++++++++++++++++++++
>  lib/fdtdec.c     | 43 +++++++++++++++++++++++++++++++++++++++++++
>  2 files changed, 91 insertions(+)
>
> diff --git a/include/fdtdec.h b/include/fdtdec.h
> index 856e6cf766de..e9091eee6bae 100644
> --- a/include/fdtdec.h
> +++ b/include/fdtdec.h
> @@ -40,6 +40,23 @@ struct fdt_memory {
>         fdt_addr_t end;
>  };
>
> +/* information about a resource */

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

> +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

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

> + * @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
> diff --git a/lib/fdtdec.c b/lib/fdtdec.c
> index eb5aa20526fd..fbfae4a7cbaf 100644
> --- a/lib/fdtdec.c
> +++ b/lib/fdtdec.c
> @@ -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/

> +{
> +       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.

> +
> +       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)?

> +                       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
> --
> 2.0.4
>

Regards,
Simon

^ permalink raw reply	[flat|nested] 95+ messages in thread

* [U-Boot] [PATCH 05/23] fdt: Add a subnodes iterator macro
  2014-08-18  7:16 ` [U-Boot] [PATCH 05/23] fdt: Add a subnodes iterator macro Thierry Reding
@ 2014-08-18 18:11   ` Simon Glass
  2014-08-19 12:22     ` Thierry Reding
  0 siblings, 1 reply; 95+ messages in thread
From: Simon Glass @ 2014-08-18 18:11 UTC (permalink / raw)
  To: u-boot

On 18 August 2014 01:16, Thierry Reding <thierry.reding@gmail.com> wrote:
> From: Thierry Reding <treding@nvidia.com>
>
> 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.
>
> Signed-off-by: Thierry Reding <treding@nvidia.com>

Acked-by: Simon Glass <sjg@chromium.org>

Will this go upstream to dtc at some point?

> ---
>  include/libfdt.h | 20 ++++++++++++++++++++
>  1 file changed, 20 insertions(+)
>
> diff --git a/include/libfdt.h b/include/libfdt.h
> index 4d7fb2681669..0330d7a29a58 100644
> --- a/include/libfdt.h
> +++ b/include/libfdt.h
> @@ -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

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

> + */
> +#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                                                  */
>  /**********************************************************************/
> --
> 2.0.4
>

Regards,
Simon

^ permalink raw reply	[flat|nested] 95+ messages in thread

* [U-Boot] [PATCH 04/23] fdt: Add a function to return PCI BDF triplet
  2014-08-18  7:16 ` [U-Boot] [PATCH 04/23] fdt: Add a function to return PCI BDF triplet Thierry Reding
@ 2014-08-18 18:20   ` Simon Glass
  0 siblings, 0 replies; 95+ messages in thread
From: Simon Glass @ 2014-08-18 18:20 UTC (permalink / raw)
  To: u-boot

On 18 August 2014 01:16, Thierry Reding <thierry.reding@gmail.com> wrote:
> From: Thierry Reding <treding@nvidia.com>
>
> 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.
>
> Signed-off-by: Thierry Reding <treding@nvidia.com>

Acked-by: Simon Glass <sjg@chromium.org>

^ permalink raw reply	[flat|nested] 95+ messages in thread

* [U-Boot] [PATCH 08/23] Add pr_fmt() macro
  2014-08-18  7:16 ` [U-Boot] [PATCH 08/23] Add pr_fmt() macro Thierry Reding
@ 2014-08-18 18:24   ` Simon Glass
  2014-08-19 12:27     ` Thierry Reding
  0 siblings, 1 reply; 95+ messages in thread
From: Simon Glass @ 2014-08-18 18:24 UTC (permalink / raw)
  To: u-boot

On 18 August 2014 01:16, Thierry Reding <thierry.reding@gmail.com> wrote:
> From: Thierry Reding <treding@nvidia.com>
>
> 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
>
> Signed-off-by: Thierry Reding <treding@nvidia.com>

Acked-by: Simon Glass <sjg@chromium.org>

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);    \

> ---
>  include/common.h | 14 +++++++++-----
>  1 file changed, 9 insertions(+), 5 deletions(-)
>
> diff --git a/include/common.h b/include/common.h
> index 1d6cb48ff078..65db04b452d7 100644
> --- a/include/common.h
> +++ b/include/common.h
> @@ -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)
>
> --
> 2.0.4
>

Regards,
Simon

^ permalink raw reply	[flat|nested] 95+ messages in thread

* [U-Boot] [PATCH 23/23] ARM: tegra: Enable PCIe on Jetson TK1
  2014-08-18  7:16 ` [U-Boot] [PATCH 23/23] ARM: tegra: Enable PCIe on Jetson TK1 Thierry Reding
@ 2014-08-18 18:37   ` Simon Glass
  2014-08-19 12:29     ` Thierry Reding
  2014-08-20 18:51   ` Stephen Warren
                     ` (2 subsequent siblings)
  3 siblings, 1 reply; 95+ messages in thread
From: Simon Glass @ 2014-08-18 18:37 UTC (permalink / raw)
  To: u-boot

Hi Thierry,

On 18 August 2014 01:16, Thierry Reding <thierry.reding@gmail.com> wrote:
> From: Thierry Reding <treding@nvidia.com>
>
> 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.
>
> Signed-off-by: Thierry Reding <treding@nvidia.com>

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

Regards,
Simon

^ permalink raw reply	[flat|nested] 95+ messages in thread

* [U-Boot] [PATCH 01/23] fdt: Add functions to query a node's #address- and #size-cells
  2014-08-18 17:52   ` Simon Glass
@ 2014-08-19 10:59     ` Thierry Reding
  2014-08-19 12:52       ` Simon Glass
  0 siblings, 1 reply; 95+ messages in thread
From: Thierry Reding @ 2014-08-19 10:59 UTC (permalink / raw)
  To: u-boot

On Mon, Aug 18, 2014 at 11:52:36AM -0600, Simon Glass wrote:
> Hi Thierry,
> 
> On 18 August 2014 01:16, Thierry Reding <thierry.reding@gmail.com> wrote:
> > From: Thierry Reding <treding@nvidia.com>
> >
> > 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.
> >
> > Signed-off-by: Thierry Reding <treding@nvidia.com>
> > ---
> >  include/libfdt.h    | 28 ++++++++++++++++++++++++++++
> >  lib/libfdt/fdt_ro.c | 36 ++++++++++++++++++++++++++++++++++++
> >  2 files changed, 64 insertions(+)
> >
> > diff --git a/include/libfdt.h b/include/libfdt.h
> > index a1ef1e15df3d..e7f991b388cf 100644
> > --- a/include/libfdt.h
> > +++ b/include/libfdt.h
> > @@ -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);
> 
> There is a new fdt_address_cells() recently that looks suitable.
> 
> > +
> > +/**
> > + * 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>

^ permalink raw reply	[flat|nested] 95+ messages in thread

* [U-Boot] [PATCH 02/23] fdt: Add a function to get the index of a string
  2014-08-18 17:58   ` Simon Glass
@ 2014-08-19 11:13     ` Thierry Reding
  0 siblings, 0 replies; 95+ messages in thread
From: Thierry Reding @ 2014-08-19 11:13 UTC (permalink / raw)
  To: u-boot

On Mon, Aug 18, 2014 at 11:58:09AM -0600, Simon Glass wrote:
> On 18 August 2014 01:16, Thierry Reding <thierry.reding@gmail.com> wrote:
[...]
> > +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);
> 
> This can go outside the loop.

Indeed.

> > +               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>

^ permalink raw reply	[flat|nested] 95+ messages in thread

* [U-Boot] [PATCH 03/23] fdt: Add resource parsing functions
  2014-08-18 18:06   ` Simon Glass
@ 2014-08-19 11:35     ` Thierry Reding
  2014-08-19 12:55       ` Simon Glass
  0 siblings, 1 reply; 95+ messages in thread
From: Thierry Reding @ 2014-08-19 11:35 UTC (permalink / raw)
  To: u-boot

On Mon, Aug 18, 2014 at 12:06:26PM -0600, Simon Glass wrote:
> Hi Thierry,
> 
> On 18 August 2014 01:16, Thierry Reding <thierry.reding@gmail.com> wrote:
> > From: Thierry Reding <treding@nvidia.com>
> >
> > 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.
> >
> > Signed-off-by: Thierry Reding <treding@nvidia.com>
> > ---
> >  include/fdtdec.h | 48 ++++++++++++++++++++++++++++++++++++++++++++++++
> >  lib/fdtdec.c     | 43 +++++++++++++++++++++++++++++++++++++++++++
> >  2 files changed, 91 insertions(+)
> >
> > diff --git a/include/fdtdec.h b/include/fdtdec.h
> > index 856e6cf766de..e9091eee6bae 100644
> > --- a/include/fdtdec.h
> > +++ b/include/fdtdec.h
> > @@ -40,6 +40,23 @@ struct fdt_memory {
> >         fdt_addr_t end;
> >  };
> >
> > +/* 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?

> > +/**
> > + * 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?

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.

> > +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.

> > +       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.

> > +
> > +       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>

^ permalink raw reply	[flat|nested] 95+ messages in thread

* [U-Boot] [PATCH 05/23] fdt: Add a subnodes iterator macro
  2014-08-18 18:11   ` Simon Glass
@ 2014-08-19 12:22     ` Thierry Reding
  2014-08-19 12:57       ` Simon Glass
  0 siblings, 1 reply; 95+ messages in thread
From: Thierry Reding @ 2014-08-19 12:22 UTC (permalink / raw)
  To: u-boot

On Mon, Aug 18, 2014 at 12:11:03PM -0600, Simon Glass wrote:
> On 18 August 2014 01:16, Thierry Reding <thierry.reding@gmail.com> wrote:
> > From: Thierry Reding <treding@nvidia.com>
> >
> > 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.
> >
> > Signed-off-by: Thierry Reding <treding@nvidia.com>
> 
> Acked-by: Simon Glass <sjg@chromium.org>
> 
> 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.

> > ---
> >  include/libfdt.h | 20 ++++++++++++++++++++
> >  1 file changed, 20 insertions(+)
> >
> > diff --git a/include/libfdt.h b/include/libfdt.h
> > index 4d7fb2681669..0330d7a29a58 100644
> > --- a/include/libfdt.h
> > +++ b/include/libfdt.h
> > @@ -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
> 
> 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>

^ permalink raw reply	[flat|nested] 95+ messages in thread

* [U-Boot] [PATCH 08/23] Add pr_fmt() macro
  2014-08-18 18:24   ` Simon Glass
@ 2014-08-19 12:27     ` Thierry Reding
  2014-08-19 12:58       ` Simon Glass
  0 siblings, 1 reply; 95+ messages in thread
From: Thierry Reding @ 2014-08-19 12:27 UTC (permalink / raw)
  To: u-boot

On Mon, Aug 18, 2014 at 12:24:06PM -0600, Simon Glass wrote:
> On 18 August 2014 01:16, Thierry Reding <thierry.reding@gmail.com> wrote:
> > From: Thierry Reding <treding@nvidia.com>
> >
> > 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
> >
> > Signed-off-by: Thierry Reding <treding@nvidia.com>
> 
> Acked-by: Simon Glass <sjg@chromium.org>
> 
> Seems OK. But I wonder if a string might be simpler?
> 
> #define DEBUG_PREFIX "foo: "
> 
> +#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>

^ permalink raw reply	[flat|nested] 95+ messages in thread

* [U-Boot] [PATCH 23/23] ARM: tegra: Enable PCIe on Jetson TK1
  2014-08-18 18:37   ` Simon Glass
@ 2014-08-19 12:29     ` Thierry Reding
  2014-08-19 13:07       ` Simon Glass
  0 siblings, 1 reply; 95+ messages in thread
From: Thierry Reding @ 2014-08-19 12:29 UTC (permalink / raw)
  To: u-boot

On Mon, Aug 18, 2014 at 12:37:46PM -0600, Simon Glass wrote:
> Hi Thierry,
> 
> On 18 August 2014 01:16, Thierry Reding <thierry.reding@gmail.com> wrote:
> > From: Thierry Reding <treding@nvidia.com>
> >
> > 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.
> >
> > Signed-off-by: Thierry Reding <treding@nvidia.com>
> 
> 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>

^ permalink raw reply	[flat|nested] 95+ messages in thread

* [U-Boot] [PATCH 01/23] fdt: Add functions to query a node's #address- and #size-cells
  2014-08-19 10:59     ` Thierry Reding
@ 2014-08-19 12:52       ` Simon Glass
  2014-08-19 13:06           ` [U-Boot] " Thierry Reding
  0 siblings, 1 reply; 95+ messages in thread
From: Simon Glass @ 2014-08-19 12:52 UTC (permalink / raw)
  To: u-boot

Hi Theirry,


On 19 August 2014 04:59, Thierry Reding <thierry.reding@gmail.com> wrote:

> On Mon, Aug 18, 2014 at 11:52:36AM -0600, Simon Glass wrote:
> > Hi Thierry,
> >
> > On 18 August 2014 01:16, Thierry Reding <thierry.reding@gmail.com>
> wrote:
> > > From: Thierry Reding <treding@nvidia.com>
> > >
> > > 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.
> > >
> > > Signed-off-by: Thierry Reding <treding@nvidia.com>
> > > ---
> > >  include/libfdt.h    | 28 ++++++++++++++++++++++++++++
> > >  lib/libfdt/fdt_ro.c | 36 ++++++++++++++++++++++++++++++++++++
> > >  2 files changed, 64 insertions(+)
> > >
> > > diff --git a/include/libfdt.h b/include/libfdt.h
> > > index a1ef1e15df3d..e7f991b388cf 100644
> > > --- a/include/libfdt.h
> > > +++ b/include/libfdt.h
> > > @@ -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);
> >
> > There is a new fdt_address_cells() recently that looks suitable.
> >
> > > +
> > > +/**
> > > + * 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.
>

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

^ permalink raw reply	[flat|nested] 95+ messages in thread

* [U-Boot] [PATCH 03/23] fdt: Add resource parsing functions
  2014-08-19 11:35     ` Thierry Reding
@ 2014-08-19 12:55       ` Simon Glass
  2014-08-19 13:12         ` Thierry Reding
  0 siblings, 1 reply; 95+ messages in thread
From: Simon Glass @ 2014-08-19 12:55 UTC (permalink / raw)
  To: u-boot

Hi Thierry,

On 19 August 2014 05:35, Thierry Reding <thierry.reding@gmail.com> wrote:
>
> On Mon, Aug 18, 2014 at 12:06:26PM -0600, Simon Glass wrote:
> > Hi Thierry,
> >
> > On 18 August 2014 01:16, Thierry Reding <thierry.reding@gmail.com> wrote:
> > > From: Thierry Reding <treding@nvidia.com>
> > >
> > > 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.
> > >
> > > Signed-off-by: Thierry Reding <treding@nvidia.com>
> > > ---
> > >  include/fdtdec.h | 48 ++++++++++++++++++++++++++++++++++++++++++++++++
> > >  lib/fdtdec.c     | 43 +++++++++++++++++++++++++++++++++++++++++++
> > >  2 files changed, 91 insertions(+)
> > >
> > > diff --git a/include/fdtdec.h b/include/fdtdec.h
> > > index 856e6cf766de..e9091eee6bae 100644
> > > --- a/include/fdtdec.h
> > > +++ b/include/fdtdec.h
> > > @@ -40,6 +40,23 @@ struct fdt_memory {
> > >         fdt_addr_t end;
> > >  };
> > >
> > > +/* 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?


LGTM

>
>
> > > +/**
> > > + * 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?
>
> 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

>
>
> > > +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

>
>
> > > +       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.

>
> > > +
> > > +       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.


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

^ permalink raw reply	[flat|nested] 95+ messages in thread

* [U-Boot] [PATCH 05/23] fdt: Add a subnodes iterator macro
  2014-08-19 12:22     ` Thierry Reding
@ 2014-08-19 12:57       ` Simon Glass
  2014-08-19 13:12         ` Thierry Reding
  0 siblings, 1 reply; 95+ messages in thread
From: Simon Glass @ 2014-08-19 12:57 UTC (permalink / raw)
  To: u-boot

Hi Thierry,

On 19 August 2014 06:22, Thierry Reding <thierry.reding@gmail.com> wrote:
> On Mon, Aug 18, 2014 at 12:11:03PM -0600, Simon Glass wrote:
>> On 18 August 2014 01:16, Thierry Reding <thierry.reding@gmail.com> wrote:
>> > From: Thierry Reding <treding@nvidia.com>
>> >
>> > 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.
>> >
>> > Signed-off-by: Thierry Reding <treding@nvidia.com>
>>
>> Acked-by: Simon Glass <sjg@chromium.org>
>>
>> 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

^ permalink raw reply	[flat|nested] 95+ messages in thread

* [U-Boot] [PATCH 08/23] Add pr_fmt() macro
  2014-08-19 12:27     ` Thierry Reding
@ 2014-08-19 12:58       ` Simon Glass
  0 siblings, 0 replies; 95+ messages in thread
From: Simon Glass @ 2014-08-19 12:58 UTC (permalink / raw)
  To: u-boot

Hi Thierry,

On 19 August 2014 06:27, Thierry Reding <thierry.reding@gmail.com> wrote:
> On Mon, Aug 18, 2014 at 12:24:06PM -0600, Simon Glass wrote:
>> On 18 August 2014 01:16, Thierry Reding <thierry.reding@gmail.com> wrote:
>> > From: Thierry Reding <treding@nvidia.com>
>> >
>> > 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
>> >
>> > Signed-off-by: Thierry Reding <treding@nvidia.com>
>>
>> Acked-by: Simon Glass <sjg@chromium.org>
>>
>> Seems OK. But I wonder if a string might be simpler?
>>
>> #define DEBUG_PREFIX "foo: "
>>
>> +#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.

>
> Thierry

Regards,
Simon

^ permalink raw reply	[flat|nested] 95+ messages in thread

* Re: [PATCH 01/23] fdt: Add functions to query a node's #address- and #size-cells
  2014-08-19 12:52       ` Simon Glass
@ 2014-08-19 13:06           ` Thierry Reding
  0 siblings, 0 replies; 95+ messages in thread
From: Thierry Reding @ 2014-08-19 13:06 UTC (permalink / raw)
  To: Simon Glass; +Cc: Stephen Warren, devicetree, U-Boot Mailing List, Tom Warren


[-- Attachment #1.1: Type: text/plain, Size: 4162 bytes --]

On Tue, Aug 19, 2014 at 06:52:22AM -0600, Simon Glass wrote:
> Hi Theirry,
> 
> 
> On 19 August 2014 04:59, Thierry Reding <thierry.reding@gmail.com> wrote:
> 
> > On Mon, Aug 18, 2014 at 11:52:36AM -0600, Simon Glass wrote:
> > > Hi Thierry,
> > >
> > > On 18 August 2014 01:16, Thierry Reding <thierry.reding@gmail.com>
> > wrote:
> > > > From: Thierry Reding <treding@nvidia.com>
> > > >
> > > > 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.
> > > >
> > > > Signed-off-by: Thierry Reding <treding@nvidia.com>
> > > > ---
> > > >  include/libfdt.h    | 28 ++++++++++++++++++++++++++++
> > > >  lib/libfdt/fdt_ro.c | 36 ++++++++++++++++++++++++++++++++++++
> > > >  2 files changed, 64 insertions(+)
> > > >
> > > > diff --git a/include/libfdt.h b/include/libfdt.h
> > > > index a1ef1e15df3d..e7f991b388cf 100644
> > > > --- a/include/libfdt.h
> > > > +++ b/include/libfdt.h
> > > > @@ -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);
> > >
> > > There is a new fdt_address_cells() recently that looks suitable.
> > >
> > > > +
> > > > +/**
> > > > + * 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.
> >
> 
> 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 devicetree@vger.kernel.org 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

[-- Attachment #1.2: Type: application/pgp-signature, Size: 819 bytes --]

[-- Attachment #2: Type: text/plain, Size: 134 bytes --]

_______________________________________________
U-Boot mailing list
U-Boot@lists.denx.de
http://lists.denx.de/mailman/listinfo/u-boot

^ permalink raw reply	[flat|nested] 95+ messages in thread

* [U-Boot] [PATCH 01/23] fdt: Add functions to query a node's #address- and #size-cells
@ 2014-08-19 13:06           ` Thierry Reding
  0 siblings, 0 replies; 95+ messages in thread
From: Thierry Reding @ 2014-08-19 13:06 UTC (permalink / raw)
  To: u-boot

On Tue, Aug 19, 2014 at 06:52:22AM -0600, Simon Glass wrote:
> Hi Theirry,
> 
> 
> On 19 August 2014 04:59, Thierry Reding <thierry.reding@gmail.com> wrote:
> 
> > On Mon, Aug 18, 2014 at 11:52:36AM -0600, Simon Glass wrote:
> > > Hi Thierry,
> > >
> > > On 18 August 2014 01:16, Thierry Reding <thierry.reding@gmail.com>
> > wrote:
> > > > From: Thierry Reding <treding@nvidia.com>
> > > >
> > > > 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.
> > > >
> > > > Signed-off-by: Thierry Reding <treding@nvidia.com>
> > > > ---
> > > >  include/libfdt.h    | 28 ++++++++++++++++++++++++++++
> > > >  lib/libfdt/fdt_ro.c | 36 ++++++++++++++++++++++++++++++++++++
> > > >  2 files changed, 64 insertions(+)
> > > >
> > > > diff --git a/include/libfdt.h b/include/libfdt.h
> > > > index a1ef1e15df3d..e7f991b388cf 100644
> > > > --- a/include/libfdt.h
> > > > +++ b/include/libfdt.h
> > > > @@ -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);
> > >
> > > There is a new fdt_address_cells() recently that looks suitable.
> > >
> > > > +
> > > > +/**
> > > > + * 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.
> >
> 
> 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 devicetree at vger.kernel.org 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
-------------- 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/77322a8f/attachment.pgp>

^ permalink raw reply	[flat|nested] 95+ messages in thread

* [U-Boot] [PATCH 23/23] ARM: tegra: Enable PCIe on Jetson TK1
  2014-08-19 12:29     ` Thierry Reding
@ 2014-08-19 13:07       ` Simon Glass
  0 siblings, 0 replies; 95+ messages in thread
From: Simon Glass @ 2014-08-19 13:07 UTC (permalink / raw)
  To: u-boot

Hi Thierry,

On 19 August 2014 06:29, Thierry Reding <thierry.reding@gmail.com> wrote:
> On Mon, Aug 18, 2014 at 12:37:46PM -0600, Simon Glass wrote:
>> Hi Thierry,
>>
>> On 18 August 2014 01:16, Thierry Reding <thierry.reding@gmail.com> wrote:
>> > From: Thierry Reding <treding@nvidia.com>
>> >
>> > 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.
>> >
>> > Signed-off-by: Thierry Reding <treding@nvidia.com>
>>
>> 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

^ permalink raw reply	[flat|nested] 95+ messages in thread

* [U-Boot] [PATCH 03/23] fdt: Add resource parsing functions
  2014-08-19 12:55       ` Simon Glass
@ 2014-08-19 13:12         ` Thierry Reding
  2014-08-19 21:28           ` Simon Glass
  0 siblings, 1 reply; 95+ messages in thread
From: Thierry Reding @ 2014-08-19 13:12 UTC (permalink / raw)
  To: u-boot

On Tue, Aug 19, 2014 at 06:55:18AM -0600, Simon Glass wrote:
> On 19 August 2014 05:35, Thierry Reding <thierry.reding@gmail.com> wrote:
[...]
> > 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.
> 
> 
> 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>

^ permalink raw reply	[flat|nested] 95+ messages in thread

* [U-Boot] [PATCH 05/23] fdt: Add a subnodes iterator macro
  2014-08-19 12:57       ` Simon Glass
@ 2014-08-19 13:12         ` Thierry Reding
  0 siblings, 0 replies; 95+ messages in thread
From: Thierry Reding @ 2014-08-19 13:12 UTC (permalink / raw)
  To: u-boot

On Tue, Aug 19, 2014 at 06:57:54AM -0600, Simon Glass wrote:
> Hi Thierry,
> 
> On 19 August 2014 06:22, Thierry Reding <thierry.reding@gmail.com> wrote:
> > On Mon, Aug 18, 2014 at 12:11:03PM -0600, Simon Glass wrote:
> >> On 18 August 2014 01:16, Thierry Reding <thierry.reding@gmail.com> wrote:
> >> > From: Thierry Reding <treding@nvidia.com>
> >> >
> >> > 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.
> >> >
> >> > Signed-off-by: Thierry Reding <treding@nvidia.com>
> >>
> >> Acked-by: Simon Glass <sjg@chromium.org>
> >>
> >> 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.

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>

^ permalink raw reply	[flat|nested] 95+ messages in thread

* [U-Boot] [PATCH 19/23] ARM: tegra: Enable PCIe on Beaver
  2014-08-18  7:16 ` [U-Boot] [PATCH 19/23] ARM: tegra: Enable PCIe on Beaver Thierry Reding
@ 2014-08-19 13:48   ` Marcel Ziswiler
  2014-08-20  6:38     ` Thierry Reding
  2014-08-20 18:43   ` Stephen Warren
  1 sibling, 1 reply; 95+ messages in thread
From: Marcel Ziswiler @ 2014-08-19 13:48 UTC (permalink / raw)
  To: u-boot

> +	/* 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.

> +	if (err) {
> +		debug("failed to set AVDD supply\n");
> +		return err;
> +	}

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

^ permalink raw reply	[flat|nested] 95+ messages in thread

* [U-Boot] [PATCH 03/23] fdt: Add resource parsing functions
  2014-08-19 13:12         ` Thierry Reding
@ 2014-08-19 21:28           ` Simon Glass
  2014-08-20  6:36             ` Thierry Reding
  0 siblings, 1 reply; 95+ messages in thread
From: Simon Glass @ 2014-08-19 21:28 UTC (permalink / raw)
  To: u-boot

Hi Thierry,

On 19 August 2014 07:12, Thierry Reding <thierry.reding@gmail.com> wrote:
> On Tue, Aug 19, 2014 at 06:55:18AM -0600, Simon Glass wrote:
>> On 19 August 2014 05:35, Thierry Reding <thierry.reding@gmail.com> wrote:
> [...]
>> > 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.
>>
>>
>> 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++);

Odd warning! Does 32UL help?

>
>         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.

>
> 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.

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

Regards,
Simon

^ permalink raw reply	[flat|nested] 95+ messages in thread

* [U-Boot] [PATCH 03/23] fdt: Add resource parsing functions
  2014-08-19 21:28           ` Simon Glass
@ 2014-08-20  6:36             ` Thierry Reding
  2014-08-20 14:05               ` Simon Glass
  0 siblings, 1 reply; 95+ messages in thread
From: Thierry Reding @ 2014-08-20  6:36 UTC (permalink / raw)
  To: u-boot

On Tue, Aug 19, 2014 at 03:28:09PM -0600, Simon Glass wrote:
> Hi Thierry,
> 
> On 19 August 2014 07:12, Thierry Reding <thierry.reding@gmail.com> wrote:
> > On Tue, Aug 19, 2014 at 06:55:18AM -0600, Simon Glass wrote:
> >> On 19 August 2014 05:35, Thierry Reding <thierry.reding@gmail.com> wrote:
> > [...]
> >> > 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.
> >>
> >>
> >> 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++);
> 
> 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.

> > 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.
> 
> 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>

^ permalink raw reply	[flat|nested] 95+ messages in thread

* [U-Boot] [PATCH 19/23] ARM: tegra: Enable PCIe on Beaver
  2014-08-19 13:48   ` Marcel Ziswiler
@ 2014-08-20  6:38     ` Thierry Reding
  2014-08-20  8:56       ` Marcel Ziswiler
  0 siblings, 1 reply; 95+ messages in thread
From: Thierry Reding @ 2014-08-20  6:38 UTC (permalink / raw)
  To: u-boot

On Tue, Aug 19, 2014 at 01:48:55PM +0000, Marcel Ziswiler wrote:
> > +	/* 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.
> 
> > +	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>

^ permalink raw reply	[flat|nested] 95+ messages in thread

* [U-Boot] [PATCH 19/23] ARM: tegra: Enable PCIe on Beaver
  2014-08-20  6:38     ` Thierry Reding
@ 2014-08-20  8:56       ` Marcel Ziswiler
  2014-08-20  9:46         ` Thierry Reding
  0 siblings, 1 reply; 95+ messages in thread
From: Marcel Ziswiler @ 2014-08-20  8:56 UTC (permalink / raw)
  To: u-boot

On Wed, 2014-08-20 at 08:38 +0200, Thierry Reding wrote:
> 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).

> 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 # 

^ permalink raw reply	[flat|nested] 95+ messages in thread

* [U-Boot] [PATCH 19/23] ARM: tegra: Enable PCIe on Beaver
  2014-08-20  8:56       ` Marcel Ziswiler
@ 2014-08-20  9:46         ` Thierry Reding
  2014-08-20 13:13           ` Marcel Ziswiler
  0 siblings, 1 reply; 95+ messages in thread
From: Thierry Reding @ 2014-08-20  9:46 UTC (permalink / raw)
  To: u-boot

On Wed, Aug 20, 2014 at 10:56:58AM +0200, Marcel Ziswiler wrote:
> On Wed, 2014-08-20 at 08:38 +0200, Thierry Reding wrote:
> > 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).
> 
> > 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.

> 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 # 


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>

^ permalink raw reply	[flat|nested] 95+ messages in thread

* [U-Boot] [PATCH 19/23] ARM: tegra: Enable PCIe on Beaver
  2014-08-20  9:46         ` Thierry Reding
@ 2014-08-20 13:13           ` Marcel Ziswiler
  0 siblings, 0 replies; 95+ messages in thread
From: Marcel Ziswiler @ 2014-08-20 13:13 UTC (permalink / raw)
  To: u-boot

On Wed, 2014-08-20 at 11:46 +0200, Thierry Reding wrote:
> 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)

^ permalink raw reply	[flat|nested] 95+ messages in thread

* [U-Boot] [PATCH 03/23] fdt: Add resource parsing functions
  2014-08-20  6:36             ` Thierry Reding
@ 2014-08-20 14:05               ` Simon Glass
  0 siblings, 0 replies; 95+ messages in thread
From: Simon Glass @ 2014-08-20 14:05 UTC (permalink / raw)
  To: u-boot

Hi Thierry,

On 20 August 2014 00:36, Thierry Reding <thierry.reding@gmail.com> wrote:
> On Tue, Aug 19, 2014 at 03:28:09PM -0600, Simon Glass wrote:
>> Hi Thierry,
>>
>> On 19 August 2014 07:12, Thierry Reding <thierry.reding@gmail.com> wrote:
>> > On Tue, Aug 19, 2014 at 06:55:18AM -0600, Simon Glass wrote:
>> >> On 19 August 2014 05:35, Thierry Reding <thierry.reding@gmail.com> wrote:
>> > [...]
>> >> > 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.
>> >>
>> >>
>> >> 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++);
>>
>> 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.

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).

>
>> > 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.
>>
>> 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.

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

Regards,
Simon

^ permalink raw reply	[flat|nested] 95+ messages in thread

* [U-Boot] [PATCH 09/23] ARM: tegra: Implement tegra_plle_enable()
  2014-08-18  7:16 ` [U-Boot] [PATCH 09/23] ARM: tegra: Implement tegra_plle_enable() Thierry Reding
@ 2014-08-20 18:12   ` Stephen Warren
  0 siblings, 0 replies; 95+ messages in thread
From: Stephen Warren @ 2014-08-20 18:12 UTC (permalink / raw)
  To: u-boot

On 08/18/2014 01:16 AM, Thierry Reding wrote:
> From: Thierry Reding <treding@nvidia.com>
>
> 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,
Acked-by: Stephen Warren <swarren@nvidia.com>

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...

^ permalink raw reply	[flat|nested] 95+ messages in thread

* [U-Boot] [PATCH 10/23] ARM: tegra: Provide PCIEXCLK reset ID
  2014-08-18  7:16 ` [U-Boot] [PATCH 10/23] ARM: tegra: Provide PCIEXCLK reset ID Thierry Reding
@ 2014-08-20 18:20   ` Stephen Warren
  2014-08-22 12:38     ` Thierry Reding
  0 siblings, 1 reply; 95+ messages in thread
From: Stephen Warren @ 2014-08-20 18:20 UTC (permalink / raw)
  To: u-boot

On 08/18/2014 01:16 AM, Thierry Reding wrote:
> From: Thierry Reding <treding@nvidia.com>
>
> 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,
Acked-by: Stephen Warren <swarren@nvidia.com>

^ permalink raw reply	[flat|nested] 95+ messages in thread

* [U-Boot] [PATCH 11/23] ARM: tegra: Implement powergate support
  2014-08-18  7:16 ` [U-Boot] [PATCH 11/23] ARM: tegra: Implement powergate support Thierry Reding
@ 2014-08-20 18:24   ` Stephen Warren
  2014-08-22 13:54     ` Thierry Reding
  0 siblings, 1 reply; 95+ messages in thread
From: Stephen Warren @ 2014-08-20 18:24 UTC (permalink / raw)
  To: u-boot

On 08/18/2014 01:16 AM, Thierry Reding wrote:
> From: Thierry Reding <treding@nvidia.com>
>
> Implement the powergate API that allows various power partitions to be
> power up and down.

> diff --git a/arch/arm/cpu/tegra-common/powergate.c b/arch/arm/cpu/tegra-common/powergate.c

> +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?

> +	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?

> diff --git a/arch/arm/include/asm/arch-tegra/powergate.h b/arch/arm/include/asm/arch-tegra/powergate.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,
> +};

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,
Acked-by: Stephen Warren <swarren@nvidia.com>

^ permalink raw reply	[flat|nested] 95+ messages in thread

* [U-Boot] [PATCH 12/23] ARM: tegra: Implement XUSB pad controller
  2014-08-18  7:16 ` [U-Boot] [PATCH 12/23] ARM: tegra: Implement XUSB pad controller Thierry Reding
@ 2014-08-20 18:32   ` Stephen Warren
  2014-08-22 14:11     ` Thierry Reding
  2014-08-22 14:38     ` Thierry Reding
  0 siblings, 2 replies; 95+ messages in thread
From: Stephen Warren @ 2014-08-20 18:32 UTC (permalink / raw)
  To: u-boot

On 08/18/2014 01:16 AM, Thierry Reding wrote:
> From: Thierry Reding <treding@nvidia.com>
>
> 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/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.

> diff --git a/arch/arm/cpu/tegra124-common/Makefile b/arch/arm/cpu/tegra124-common/Makefile

>   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?

> diff --git a/arch/arm/cpu/tegra124-common/xusb-padctl.c b/arch/arm/cpu/tegra124-common/xusb-padctl.c

> +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.

> diff --git a/arch/arm/include/asm/arch-tegra/xusb-padctl.h b/arch/arm/include/asm/arch-tegra/xusb-padctl.h

> +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,
Acked-by: Stephen Warren <swarren@nvidia.com>

^ permalink raw reply	[flat|nested] 95+ messages in thread

* [U-Boot] [PATCH 13/23] ARM: tegra: Add XUSB pad controller on Tegra124
  2014-08-18  7:16 ` [U-Boot] [PATCH 13/23] ARM: tegra: Add XUSB pad controller on Tegra124 Thierry Reding
@ 2014-08-20 18:33   ` Stephen Warren
  0 siblings, 0 replies; 95+ messages in thread
From: Stephen Warren @ 2014-08-20 18:33 UTC (permalink / raw)
  To: u-boot

On 08/18/2014 01:16 AM, Thierry Reding wrote:
> From: Thierry Reding <treding@nvidia.com>
>
> 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,

Acked-by: Stephen Warren <swarren@nvidia.com>

^ permalink raw reply	[flat|nested] 95+ messages in thread

* [U-Boot] [PATCH 14/23] ARM: tegra: Enable XUSB pad controller on Jetson TK1
  2014-08-18  7:16 ` [U-Boot] [PATCH 14/23] ARM: tegra: Enable XUSB pad controller on Jetson TK1 Thierry Reding
@ 2014-08-20 18:34   ` Stephen Warren
  0 siblings, 0 replies; 95+ messages in thread
From: Stephen Warren @ 2014-08-20 18:34 UTC (permalink / raw)
  To: u-boot

On 08/18/2014 01:16 AM, Thierry Reding wrote:
> From: Thierry Reding <treding@nvidia.com>
>
> 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,

Acked-by: Stephen Warren <swarren@nvidia.com>

^ permalink raw reply	[flat|nested] 95+ messages in thread

* [U-Boot] [PATCH 16/23] ARM: tegra: Add Tegra20 PCIe device tree node
  2014-08-18  7:16 ` [U-Boot] [PATCH 16/23] ARM: tegra: Add Tegra20 PCIe device tree node Thierry Reding
@ 2014-08-20 18:37   ` Stephen Warren
  0 siblings, 0 replies; 95+ messages in thread
From: Stephen Warren @ 2014-08-20 18:37 UTC (permalink / raw)
  To: u-boot

On 08/18/2014 01:16 AM, Thierry Reding wrote:
> From: Thierry Reding <treding@nvidia.com>
>
> Add the device tree node for the PCIe controller found on Tegra20 SoCs.

This matches the kernel, so
Acked-by: Stephen Warren <swarren@nvidia.com>

^ permalink raw reply	[flat|nested] 95+ messages in thread

* [U-Boot] [PATCH 17/23] ARM: tegra: Enable PCIe on TrimSlice
  2014-08-18  7:16 ` [U-Boot] [PATCH 17/23] ARM: tegra: Enable PCIe on TrimSlice Thierry Reding
@ 2014-08-20 18:38   ` Stephen Warren
  2014-08-22 14:44     ` Thierry Reding
  0 siblings, 1 reply; 95+ messages in thread
From: Stephen Warren @ 2014-08-20 18:38 UTC (permalink / raw)
  To: u-boot

On 08/18/2014 01:16 AM, Thierry Reding wrote:
> From: Thierry Reding <treding@nvidia.com>
>
> 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.

> diff --git a/arch/arm/dts/tegra20-trimslice.dts b/arch/arm/dts/tegra20-trimslice.dts

> +	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?

^ permalink raw reply	[flat|nested] 95+ messages in thread

* [U-Boot] [PATCH 18/23] ARM: tegra: Add Tegra30 PCIe device tree node
  2014-08-18  7:16 ` [U-Boot] [PATCH 18/23] ARM: tegra: Add Tegra30 PCIe device tree node Thierry Reding
@ 2014-08-20 18:39   ` Stephen Warren
  2014-08-22 14:51     ` Thierry Reding
  0 siblings, 1 reply; 95+ messages in thread
From: Stephen Warren @ 2014-08-20 18:39 UTC (permalink / raw)
  To: u-boot

On 08/18/2014 01:16 AM, Thierry Reding wrote:
> From: Thierry Reding <treding@nvidia.com>
>
> Add the device tree node for the PCIe controller found on Tegra30 SoCs.

> diff --git a/arch/arm/dts/tegra30.dtsi b/arch/arm/dts/tegra30.dtsi

> +	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?

^ permalink raw reply	[flat|nested] 95+ messages in thread

* [U-Boot] [PATCH 19/23] ARM: tegra: Enable PCIe on Beaver
  2014-08-18  7:16 ` [U-Boot] [PATCH 19/23] ARM: tegra: Enable PCIe on Beaver Thierry Reding
  2014-08-19 13:48   ` Marcel Ziswiler
@ 2014-08-20 18:43   ` Stephen Warren
  2014-08-22 12:33     ` Thierry Reding
  1 sibling, 1 reply; 95+ messages in thread
From: Stephen Warren @ 2014-08-20 18:43 UTC (permalink / raw)
  To: u-boot

On 08/18/2014 01:16 AM, Thierry Reding wrote:
> From: Thierry Reding <treding@nvidia.com>
>
> 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.

> diff --git a/arch/arm/dts/tegra30-beaver.dts b/arch/arm/dts/tegra30-beaver.dts

> +	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)

> +	regulators {
...
> +		vdd_5v_in_reg: regulator at 0 {
...
> +		sys_3v3_reg: regulator at 6 {
...
> +		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?

> diff --git a/board/nvidia/cardhu/cardhu.c b/board/nvidia/cardhu/cardhu.c

The commit description says Beaver...

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

^ permalink raw reply	[flat|nested] 95+ messages in thread

* [U-Boot] [PATCH 21/23] ARM: tegra: Add GIC for Tegra124
  2014-08-18  7:16 ` [U-Boot] [PATCH 21/23] ARM: tegra: Add GIC for Tegra124 Thierry Reding
@ 2014-08-20 18:45   ` Stephen Warren
  0 siblings, 0 replies; 95+ messages in thread
From: Stephen Warren @ 2014-08-20 18:45 UTC (permalink / raw)
  To: u-boot

On 08/18/2014 01:16 AM, Thierry Reding wrote:
> From: Thierry Reding <treding@nvidia.com>
>
> 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,
Acked-by: Stephen Warren <swarren@nvidia.com>

^ permalink raw reply	[flat|nested] 95+ messages in thread

* [U-Boot] [PATCH 22/23] ARM: tegra: Add Tegra124 PCIe device tree node
  2014-08-18  7:16 ` [U-Boot] [PATCH 22/23] ARM: tegra: Add Tegra124 PCIe device tree node Thierry Reding
@ 2014-08-20 18:46   ` Stephen Warren
  0 siblings, 0 replies; 95+ messages in thread
From: Stephen Warren @ 2014-08-20 18:46 UTC (permalink / raw)
  To: u-boot

On 08/18/2014 01:16 AM, Thierry Reding wrote:
> From: Thierry Reding <treding@nvidia.com>
>
> Add the device tree node for the PCIe controller found on Tegra124 SoCs.

This matches what's proposed for the kernel, so,
Acked-by: Stephen Warren <swarren@nvidia.com>

^ permalink raw reply	[flat|nested] 95+ messages in thread

* [U-Boot] [PATCH 23/23] ARM: tegra: Enable PCIe on Jetson TK1
  2014-08-18  7:16 ` [U-Boot] [PATCH 23/23] ARM: tegra: Enable PCIe on Jetson TK1 Thierry Reding
  2014-08-18 18:37   ` Simon Glass
@ 2014-08-20 18:51   ` Stephen Warren
  2014-08-22 12:09     ` Thierry Reding
  2014-08-20 18:54   ` Stephen Warren
  2014-08-26 12:54   ` Tuomas Tynkkynen
  3 siblings, 1 reply; 95+ messages in thread
From: Stephen Warren @ 2014-08-20 18:51 UTC (permalink / raw)
  To: u-boot

On 08/18/2014 01:16 AM, Thierry Reding wrote:
> From: Thierry Reding <treding@nvidia.com>
>
> 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

> diff --git a/arch/arm/dts/tegra124-jetson-tk1.dts b/arch/arm/dts/tegra124-jetson-tk1.dts

> +	regulators {

> +		/* Molex power connector */
> +		vdd_5v0_sata: regulator at 13 {
...
> +		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:-)

> diff --git a/board/nvidia/jetson-tk1/jetson-tk1.c b/board/nvidia/jetson-tk1/jetson-tk1.c

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.

^ permalink raw reply	[flat|nested] 95+ messages in thread

* [U-Boot] [PATCH 23/23] ARM: tegra: Enable PCIe on Jetson TK1
  2014-08-18  7:16 ` [U-Boot] [PATCH 23/23] ARM: tegra: Enable PCIe on Jetson TK1 Thierry Reding
  2014-08-18 18:37   ` Simon Glass
  2014-08-20 18:51   ` Stephen Warren
@ 2014-08-20 18:54   ` Stephen Warren
  2014-08-26 12:54   ` Tuomas Tynkkynen
  3 siblings, 0 replies; 95+ messages in thread
From: Stephen Warren @ 2014-08-20 18:54 UTC (permalink / raw)
  To: u-boot

On 08/18/2014 01:16 AM, Thierry Reding wrote:
> From: Thierry Reding <treding@nvidia.com>
>
> 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.

> diff --git a/arch/arm/dts/tegra124-jetson-tk1.dts b/arch/arm/dts/tegra124-jetson-tk1.dts

>   	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.

^ permalink raw reply	[flat|nested] 95+ messages in thread

* [U-Boot] [PATCH 15/23] pci: tegra: Add Tegra PCIe driver
  2014-08-18  7:16 ` [U-Boot] [PATCH 15/23] pci: tegra: Add Tegra PCIe driver Thierry Reding
@ 2014-08-20 19:04   ` Stephen Warren
  2014-08-22 15:24     ` Thierry Reding
  2014-08-22 17:33     ` Stephen Warren
  0 siblings, 2 replies; 95+ messages in thread
From: Stephen Warren @ 2014-08-20 19:04 UTC (permalink / raw)
  To: u-boot

On 08/18/2014 01:16 AM, Thierry Reding wrote:
> From: Thierry Reding <treding@nvidia.com>
>
> 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.

> diff --git a/drivers/pci/pci_tegra.c b/drivers/pci/pci_tegra.c

> + * Copyright (c) 2010, CompuLab, Ltd.
> + * Author: Mike Rapoport <mike@compulab.co.il>
> + *
> + * 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?

> +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.

> +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)
> +				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.

> +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()?

^ permalink raw reply	[flat|nested] 95+ messages in thread

* [U-Boot] [PATCH 23/23] ARM: tegra: Enable PCIe on Jetson TK1
  2014-08-20 18:51   ` Stephen Warren
@ 2014-08-22 12:09     ` Thierry Reding
  2014-08-22 18:50       ` Stephen Warren
  2014-08-22 19:27       ` Simon Glass
  0 siblings, 2 replies; 95+ messages in thread
From: Thierry Reding @ 2014-08-22 12:09 UTC (permalink / raw)
  To: u-boot

On Wed, Aug 20, 2014 at 12:51:35PM -0600, Stephen Warren wrote:
> On 08/18/2014 01:16 AM, Thierry Reding wrote:
> >From: Thierry Reding <treding@nvidia.com>
> >
> >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
> 
> >diff --git a/arch/arm/dts/tegra124-jetson-tk1.dts b/arch/arm/dts/tegra124-jetson-tk1.dts
> 
> >+	regulators {
> 
> >+		/* Molex power connector */
> >+		vdd_5v0_sata: regulator at 13 {
> ...
> >+		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:-)
> 
> >diff --git a/board/nvidia/jetson-tk1/jetson-tk1.c b/board/nvidia/jetson-tk1/jetson-tk1.c
> 
> 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>

^ permalink raw reply	[flat|nested] 95+ messages in thread

* [U-Boot] [PATCH 19/23] ARM: tegra: Enable PCIe on Beaver
  2014-08-20 18:43   ` Stephen Warren
@ 2014-08-22 12:33     ` Thierry Reding
  0 siblings, 0 replies; 95+ messages in thread
From: Thierry Reding @ 2014-08-22 12:33 UTC (permalink / raw)
  To: u-boot

On Wed, Aug 20, 2014 at 12:43:58PM -0600, Stephen Warren wrote:
> On 08/18/2014 01:16 AM, Thierry Reding wrote:
> >From: Thierry Reding <treding@nvidia.com>
> >
> >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.
> 
> >diff --git a/arch/arm/dts/tegra30-beaver.dts b/arch/arm/dts/tegra30-beaver.dts
> 
> >+	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)

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

> >+	regulators {
> ...
> >+		vdd_5v_in_reg: regulator at 0 {
> ...
> >+		sys_3v3_reg: regulator at 6 {
> ...
> >+		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.

> >diff --git a/board/nvidia/cardhu/cardhu.c b/board/nvidia/cardhu/cardhu.c
> 
> 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>

^ permalink raw reply	[flat|nested] 95+ messages in thread

* [U-Boot] [PATCH 10/23] ARM: tegra: Provide PCIEXCLK reset ID
  2014-08-20 18:20   ` Stephen Warren
@ 2014-08-22 12:38     ` Thierry Reding
  0 siblings, 0 replies; 95+ messages in thread
From: Thierry Reding @ 2014-08-22 12:38 UTC (permalink / raw)
  To: u-boot

On Wed, Aug 20, 2014 at 12:20:20PM -0600, Stephen Warren wrote:
> On 08/18/2014 01:16 AM, Thierry Reding wrote:
> >From: Thierry Reding <treding@nvidia.com>
> >
> >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.

> Aside from that,
> Acked-by: Stephen Warren <swarren@nvidia.com>

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>

^ permalink raw reply	[flat|nested] 95+ messages in thread

* [U-Boot] [PATCH 11/23] ARM: tegra: Implement powergate support
  2014-08-20 18:24   ` Stephen Warren
@ 2014-08-22 13:54     ` Thierry Reding
  0 siblings, 0 replies; 95+ messages in thread
From: Thierry Reding @ 2014-08-22 13:54 UTC (permalink / raw)
  To: u-boot

On Wed, Aug 20, 2014 at 12:24:11PM -0600, Stephen Warren wrote:
> On 08/18/2014 01:16 AM, Thierry Reding wrote:
> >From: Thierry Reding <treding@nvidia.com>
> >
> >Implement the powergate API that allows various power partitions to be
> >power up and down.
> 
> >diff --git a/arch/arm/cpu/tegra-common/powergate.c b/arch/arm/cpu/tegra-common/powergate.c
> 
> >+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.

> >+	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?

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.

> >diff --git a/arch/arm/include/asm/arch-tegra/powergate.h b/arch/arm/include/asm/arch-tegra/powergate.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,
> >+};
> 
> 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>

^ permalink raw reply	[flat|nested] 95+ messages in thread

* [U-Boot] [PATCH 12/23] ARM: tegra: Implement XUSB pad controller
  2014-08-20 18:32   ` Stephen Warren
@ 2014-08-22 14:11     ` Thierry Reding
  2014-08-22 14:38     ` Thierry Reding
  1 sibling, 0 replies; 95+ messages in thread
From: Thierry Reding @ 2014-08-22 14:11 UTC (permalink / raw)
  To: u-boot

On Wed, Aug 20, 2014 at 12:32:45PM -0600, Stephen Warren wrote:
> On 08/18/2014 01:16 AM, Thierry Reding wrote:
> >From: Thierry Reding <treding@nvidia.com>
> >
> >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/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.

Done.

> >diff --git a/arch/arm/cpu/tegra124-common/Makefile b/arch/arm/cpu/tegra124-common/Makefile
> 
> >  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?

> >diff --git a/arch/arm/cpu/tegra124-common/xusb-padctl.c b/arch/arm/cpu/tegra124-common/xusb-padctl.c
> 
> >+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.

> >diff --git a/arch/arm/include/asm/arch-tegra/xusb-padctl.h b/arch/arm/include/asm/arch-tegra/xusb-padctl.h
> 
> >+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>

^ permalink raw reply	[flat|nested] 95+ messages in thread

* [U-Boot] [PATCH 12/23] ARM: tegra: Implement XUSB pad controller
  2014-08-20 18:32   ` Stephen Warren
  2014-08-22 14:11     ` Thierry Reding
@ 2014-08-22 14:38     ` Thierry Reding
  1 sibling, 0 replies; 95+ messages in thread
From: Thierry Reding @ 2014-08-22 14:38 UTC (permalink / raw)
  To: u-boot

On Wed, Aug 20, 2014 at 12:32:45PM -0600, Stephen Warren wrote:
> On 08/18/2014 01:16 AM, Thierry Reding wrote:
[...]
> >diff --git a/arch/arm/cpu/tegra124-common/xusb-padctl.c b/arch/arm/cpu/tegra124-common/xusb-padctl.c
> 
> >+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>

^ permalink raw reply	[flat|nested] 95+ messages in thread

* [U-Boot] [PATCH 17/23] ARM: tegra: Enable PCIe on TrimSlice
  2014-08-20 18:38   ` Stephen Warren
@ 2014-08-22 14:44     ` Thierry Reding
  0 siblings, 0 replies; 95+ messages in thread
From: Thierry Reding @ 2014-08-22 14:44 UTC (permalink / raw)
  To: u-boot

On Wed, Aug 20, 2014 at 12:38:15PM -0600, Stephen Warren wrote:
> On 08/18/2014 01:16 AM, Thierry Reding wrote:
> >From: Thierry Reding <treding@nvidia.com>
> >
> >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.
> 
> >diff --git a/arch/arm/dts/tegra20-trimslice.dts b/arch/arm/dts/tegra20-trimslice.dts
> 
> >+	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>

^ permalink raw reply	[flat|nested] 95+ messages in thread

* [U-Boot] [PATCH 18/23] ARM: tegra: Add Tegra30 PCIe device tree node
  2014-08-20 18:39   ` Stephen Warren
@ 2014-08-22 14:51     ` Thierry Reding
  0 siblings, 0 replies; 95+ messages in thread
From: Thierry Reding @ 2014-08-22 14:51 UTC (permalink / raw)
  To: u-boot

On Wed, Aug 20, 2014 at 12:39:14PM -0600, Stephen Warren wrote:
> On 08/18/2014 01:16 AM, Thierry Reding wrote:
> >From: Thierry Reding <treding@nvidia.com>
> >
> >Add the device tree node for the PCIe controller found on Tegra30 SoCs.
> 
> >diff --git a/arch/arm/dts/tegra30.dtsi b/arch/arm/dts/tegra30.dtsi
> 
> >+	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>

^ permalink raw reply	[flat|nested] 95+ messages in thread

* [U-Boot] [PATCH 15/23] pci: tegra: Add Tegra PCIe driver
  2014-08-20 19:04   ` Stephen Warren
@ 2014-08-22 15:24     ` Thierry Reding
  2014-08-22 17:33     ` Stephen Warren
  1 sibling, 0 replies; 95+ messages in thread
From: Thierry Reding @ 2014-08-22 15:24 UTC (permalink / raw)
  To: u-boot

On Wed, Aug 20, 2014 at 01:04:22PM -0600, Stephen Warren wrote:
> On 08/18/2014 01:16 AM, Thierry Reding wrote:
> >From: Thierry Reding <treding@nvidia.com>
> >
> >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.
> 
> >diff --git a/drivers/pci/pci_tegra.c b/drivers/pci/pci_tegra.c
> 
> >+ * Copyright (c) 2010, CompuLab, Ltd.
> >+ * Author: Mike Rapoport <mike@compulab.co.il>
> >+ *
> >+ * Based on NVIDIA PCIe driver
> >+ * Copyright (c) 2008-2009, NVIDIA Corporation.
> 
> Presumably also at least (c) 2013-2014 NVIDIA too?

Yes.

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

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

> >+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.

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);
	}

> >+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)
> >+				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.

> >+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>

^ permalink raw reply	[flat|nested] 95+ messages in thread

* [U-Boot] [PATCH 15/23] pci: tegra: Add Tegra PCIe driver
  2014-08-20 19:04   ` Stephen Warren
  2014-08-22 15:24     ` Thierry Reding
@ 2014-08-22 17:33     ` Stephen Warren
  2014-08-22 19:41       ` Thierry Reding
  1 sibling, 1 reply; 95+ messages in thread
From: Stephen Warren @ 2014-08-22 17:33 UTC (permalink / raw)
  To: u-boot

On 08/20/2014 01:04 PM, Stephen Warren wrote:
> On 08/18/2014 01:16 AM, Thierry Reding wrote:
>> From: Thierry Reding <treding@nvidia.com>
>>
>> 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.
>
>> diff --git a/drivers/pci/pci_tegra.c b/drivers/pci/pci_tegra.c

>> +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)
>> +                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.

^ permalink raw reply	[flat|nested] 95+ messages in thread

* [U-Boot] [PATCH 23/23] ARM: tegra: Enable PCIe on Jetson TK1
  2014-08-22 12:09     ` Thierry Reding
@ 2014-08-22 18:50       ` Stephen Warren
  2014-08-22 19:27       ` Simon Glass
  1 sibling, 0 replies; 95+ messages in thread
From: Stephen Warren @ 2014-08-22 18:50 UTC (permalink / raw)
  To: u-boot

On 08/22/2014 06:09 AM, Thierry Reding wrote:
> On Wed, Aug 20, 2014 at 12:51:35PM -0600, Stephen Warren wrote:
>> On 08/18/2014 01:16 AM, Thierry Reding wrote:
>>> From: Thierry Reding <treding@nvidia.com>
>>>
>>> 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
>>
>>> diff --git a/arch/arm/dts/tegra124-jetson-tk1.dts b/arch/arm/dts/tegra124-jetson-tk1.dts
>>
>>> +	regulators {
>>
>>> +		/* Molex power connector */
>>> +		vdd_5v0_sata: regulator at 13 {
>> ...
>>> +		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:-)
>>
>>> diff --git a/board/nvidia/jetson-tk1/jetson-tk1.c b/board/nvidia/jetson-tk1/jetson-tk1.c
>>
>> 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.

Ah yes. That makes sense.

> 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
>

^ permalink raw reply	[flat|nested] 95+ messages in thread

* [U-Boot] [PATCH 23/23] ARM: tegra: Enable PCIe on Jetson TK1
  2014-08-22 12:09     ` Thierry Reding
  2014-08-22 18:50       ` Stephen Warren
@ 2014-08-22 19:27       ` Simon Glass
  2014-08-22 19:40         ` Thierry Reding
  1 sibling, 1 reply; 95+ messages in thread
From: Simon Glass @ 2014-08-22 19:27 UTC (permalink / raw)
  To: u-boot

Hi Thierry,

On 22 August 2014 06:09, Thierry Reding <thierry.reding@gmail.com> wrote:

> On Wed, Aug 20, 2014 at 12:51:35PM -0600, Stephen Warren wrote:
> > On 08/18/2014 01:16 AM, Thierry Reding wrote:
> > >From: Thierry Reding <treding@nvidia.com>
> > >
> > >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
> >
> > >diff --git a/arch/arm/dts/tegra124-jetson-tk1.dts
> b/arch/arm/dts/tegra124-jetson-tk1.dts
> >
> > >+    regulators {
> >
> > >+            /* Molex power connector */
> > >+            vdd_5v0_sata: regulator at 13 {
> > ...
> > >+            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:-)
> >
> > >diff --git a/board/nvidia/jetson-tk1/jetson-tk1.c
> b/board/nvidia/jetson-tk1/jetson-tk1.c
> >
> > 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.
>

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


>
> 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

^ permalink raw reply	[flat|nested] 95+ messages in thread

* [U-Boot] [PATCH 23/23] ARM: tegra: Enable PCIe on Jetson TK1
  2014-08-22 19:27       ` Simon Glass
@ 2014-08-22 19:40         ` Thierry Reding
  2014-08-22 20:12           ` Simon Glass
  0 siblings, 1 reply; 95+ messages in thread
From: Thierry Reding @ 2014-08-22 19:40 UTC (permalink / raw)
  To: u-boot

On Fri, Aug 22, 2014 at 01:27:57PM -0600, Simon Glass wrote:
> On 22 August 2014 06:09, Thierry Reding <thierry.reding@gmail.com> wrote:
[...]
> > 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>

^ permalink raw reply	[flat|nested] 95+ messages in thread

* [U-Boot] [PATCH 15/23] pci: tegra: Add Tegra PCIe driver
  2014-08-22 17:33     ` Stephen Warren
@ 2014-08-22 19:41       ` Thierry Reding
  0 siblings, 0 replies; 95+ messages in thread
From: Thierry Reding @ 2014-08-22 19:41 UTC (permalink / raw)
  To: u-boot

On Fri, Aug 22, 2014 at 11:33:39AM -0600, Stephen Warren wrote:
> On 08/20/2014 01:04 PM, Stephen Warren wrote:
> >On 08/18/2014 01:16 AM, Thierry Reding wrote:
> >>From: Thierry Reding <treding@nvidia.com>
> >>
> >>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.
> >
> >>diff --git a/drivers/pci/pci_tegra.c b/drivers/pci/pci_tegra.c
> 
> >>+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)
> >>+                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.

Hey, that's great news.

> 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>

^ permalink raw reply	[flat|nested] 95+ messages in thread

* [U-Boot] [PATCH 23/23] ARM: tegra: Enable PCIe on Jetson TK1
  2014-08-22 19:40         ` Thierry Reding
@ 2014-08-22 20:12           ` Simon Glass
  2014-08-22 22:03             ` Thierry Reding
  0 siblings, 1 reply; 95+ messages in thread
From: Simon Glass @ 2014-08-22 20:12 UTC (permalink / raw)
  To: u-boot

Hi Thierry,

On 22 August 2014 13:40, Thierry Reding <thierry.reding@gmail.com> wrote:
> On Fri, Aug 22, 2014 at 01:27:57PM -0600, Simon Glass wrote:
>> On 22 August 2014 06:09, Thierry Reding <thierry.reding@gmail.com> wrote:
> [...]
>> > 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.

Yes that's right.

>
> 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

^ permalink raw reply	[flat|nested] 95+ messages in thread

* [U-Boot] [PATCH 23/23] ARM: tegra: Enable PCIe on Jetson TK1
  2014-08-22 20:12           ` Simon Glass
@ 2014-08-22 22:03             ` Thierry Reding
  2014-08-23  1:47               ` Simon Glass
  0 siblings, 1 reply; 95+ messages in thread
From: Thierry Reding @ 2014-08-22 22:03 UTC (permalink / raw)
  To: u-boot

On Fri, Aug 22, 2014 at 02:12:19PM -0600, Simon Glass wrote:
> On 22 August 2014 13:40, Thierry Reding <thierry.reding@gmail.com> wrote:
[...]
> > 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>

^ permalink raw reply	[flat|nested] 95+ messages in thread

* [U-Boot] [PATCH 23/23] ARM: tegra: Enable PCIe on Jetson TK1
  2014-08-22 22:03             ` Thierry Reding
@ 2014-08-23  1:47               ` Simon Glass
  2014-08-23 11:33                 ` Thierry Reding
  0 siblings, 1 reply; 95+ messages in thread
From: Simon Glass @ 2014-08-23  1:47 UTC (permalink / raw)
  To: u-boot

Hi Thierry,

On 22 August 2014 16:03, Thierry Reding <thierry.reding@gmail.com> wrote:
> On Fri, Aug 22, 2014 at 02:12:19PM -0600, Simon Glass wrote:
>> On 22 August 2014 13:40, Thierry Reding <thierry.reding@gmail.com> wrote:
> [...]
>> > 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.

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

^ permalink raw reply	[flat|nested] 95+ messages in thread

* Re: [PATCH 01/23] fdt: Add functions to query a node's #address- and #size-cells
  2014-08-19 13:06           ` [U-Boot] " Thierry Reding
@ 2014-08-23  3:03             ` Simon Glass
  -1 siblings, 0 replies; 95+ messages in thread
From: Simon Glass @ 2014-08-23  3:03 UTC (permalink / raw)
  To: Thierry Reding
  Cc: Tom Warren, Albert Aribaud, Stephen Warren, Stefan Agner,
	U-Boot Mailing List, Devicetree Discuss

Hi Thierry,

On 19 August 2014 07:06, Thierry Reding <thierry.reding-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> wrote:
> On Tue, Aug 19, 2014 at 06:52:22AM -0600, Simon Glass wrote:
>> Hi Theirry,
>>
>>
>> On 19 August 2014 04:59, Thierry Reding <thierry.reding-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> wrote:
>>
>> > On Mon, Aug 18, 2014 at 11:52:36AM -0600, Simon Glass wrote:
>> > > Hi Thierry,
>> > >
>> > > On 18 August 2014 01:16, Thierry Reding <thierry.reding-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
>> > wrote:
>> > > > From: Thierry Reding <treding-DDmLM1+adcrQT0dZR+AlfA@public.gmane.org>
>> > > >
>> > > > 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.
>> > > >
>> > > > Signed-off-by: Thierry Reding <treding-DDmLM1+adcrQT0dZR+AlfA@public.gmane.org>
>> > > > ---
>> > > >  include/libfdt.h    | 28 ++++++++++++++++++++++++++++
>> > > >  lib/libfdt/fdt_ro.c | 36 ++++++++++++++++++++++++++++++++++++
>> > > >  2 files changed, 64 insertions(+)
>> > > >
>> > > > diff --git a/include/libfdt.h b/include/libfdt.h
>> > > > index a1ef1e15df3d..e7f991b388cf 100644
>> > > > --- a/include/libfdt.h
>> > > > +++ b/include/libfdt.h
>> > > > @@ -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);
>> > >
>> > > There is a new fdt_address_cells() recently that looks suitable.
>> > >
>> > > > +
>> > > > +/**
>> > > > + * 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.
>> >
>>
>> 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 devicetree-u79uwXL29TY76Z2rM5mHXA@public.gmane.org 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 majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 95+ messages in thread

* [U-Boot] [PATCH 01/23] fdt: Add functions to query a node's #address- and #size-cells
@ 2014-08-23  3:03             ` Simon Glass
  0 siblings, 0 replies; 95+ messages in thread
From: Simon Glass @ 2014-08-23  3:03 UTC (permalink / raw)
  To: u-boot

Hi Thierry,

On 19 August 2014 07:06, Thierry Reding <thierry.reding@gmail.com> wrote:
> On Tue, Aug 19, 2014 at 06:52:22AM -0600, Simon Glass wrote:
>> Hi Theirry,
>>
>>
>> On 19 August 2014 04:59, Thierry Reding <thierry.reding@gmail.com> wrote:
>>
>> > On Mon, Aug 18, 2014 at 11:52:36AM -0600, Simon Glass wrote:
>> > > Hi Thierry,
>> > >
>> > > On 18 August 2014 01:16, Thierry Reding <thierry.reding@gmail.com>
>> > wrote:
>> > > > From: Thierry Reding <treding@nvidia.com>
>> > > >
>> > > > 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.
>> > > >
>> > > > Signed-off-by: Thierry Reding <treding@nvidia.com>
>> > > > ---
>> > > >  include/libfdt.h    | 28 ++++++++++++++++++++++++++++
>> > > >  lib/libfdt/fdt_ro.c | 36 ++++++++++++++++++++++++++++++++++++
>> > > >  2 files changed, 64 insertions(+)
>> > > >
>> > > > diff --git a/include/libfdt.h b/include/libfdt.h
>> > > > index a1ef1e15df3d..e7f991b388cf 100644
>> > > > --- a/include/libfdt.h
>> > > > +++ b/include/libfdt.h
>> > > > @@ -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);
>> > >
>> > > There is a new fdt_address_cells() recently that looks suitable.
>> > >
>> > > > +
>> > > > +/**
>> > > > + * 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.
>> >
>>
>> 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 devicetree at vger.kernel.org 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

^ permalink raw reply	[flat|nested] 95+ messages in thread

* Re: [PATCH 01/23] fdt: Add functions to query a node's #address- and #size-cells
  2014-08-23  3:03             ` [U-Boot] " Simon Glass
@ 2014-08-23 11:26                 ` Thierry Reding
  -1 siblings, 0 replies; 95+ messages in thread
From: Thierry Reding @ 2014-08-23 11:26 UTC (permalink / raw)
  To: Simon Glass
  Cc: Tom Warren, Albert Aribaud, Stephen Warren, Stefan Agner,
	U-Boot Mailing List, Devicetree Discuss

[-- Attachment #1: Type: text/plain, Size: 4997 bytes --]

On Fri, Aug 22, 2014 at 09:03:49PM -0600, Simon Glass wrote:
> Hi Thierry,
> 
> On 19 August 2014 07:06, Thierry Reding <thierry.reding-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> wrote:
> > On Tue, Aug 19, 2014 at 06:52:22AM -0600, Simon Glass wrote:
> >> Hi Theirry,
> >>
> >>
> >> On 19 August 2014 04:59, Thierry Reding <thierry.reding-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> wrote:
> >>
> >> > On Mon, Aug 18, 2014 at 11:52:36AM -0600, Simon Glass wrote:
> >> > > Hi Thierry,
> >> > >
> >> > > On 18 August 2014 01:16, Thierry Reding <thierry.reding-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
> >> > wrote:
> >> > > > From: Thierry Reding <treding-DDmLM1+adcrQT0dZR+AlfA@public.gmane.org>
> >> > > >
> >> > > > 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.
> >> > > >
> >> > > > Signed-off-by: Thierry Reding <treding-DDmLM1+adcrQT0dZR+AlfA@public.gmane.org>
> >> > > > ---
> >> > > >  include/libfdt.h    | 28 ++++++++++++++++++++++++++++
> >> > > >  lib/libfdt/fdt_ro.c | 36 ++++++++++++++++++++++++++++++++++++
> >> > > >  2 files changed, 64 insertions(+)
> >> > > >
> >> > > > diff --git a/include/libfdt.h b/include/libfdt.h
> >> > > > index a1ef1e15df3d..e7f991b388cf 100644
> >> > > > --- a/include/libfdt.h
> >> > > > +++ b/include/libfdt.h
> >> > > > @@ -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);
> >> > >
> >> > > There is a new fdt_address_cells() recently that looks suitable.
> >> > >
> >> > > > +
> >> > > > +/**
> >> > > > + * 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.
> >> >
> >>
> >> 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 devicetree-u79uwXL29TY76Z2rM5mHXA@public.gmane.org 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

[-- Attachment #2: Type: application/pgp-signature, Size: 836 bytes --]

^ permalink raw reply	[flat|nested] 95+ messages in thread

* [U-Boot] [PATCH 01/23] fdt: Add functions to query a node's #address- and #size-cells
@ 2014-08-23 11:26                 ` Thierry Reding
  0 siblings, 0 replies; 95+ messages in thread
From: Thierry Reding @ 2014-08-23 11:26 UTC (permalink / raw)
  To: u-boot

On Fri, Aug 22, 2014 at 09:03:49PM -0600, Simon Glass wrote:
> Hi Thierry,
> 
> On 19 August 2014 07:06, Thierry Reding <thierry.reding@gmail.com> wrote:
> > On Tue, Aug 19, 2014 at 06:52:22AM -0600, Simon Glass wrote:
> >> Hi Theirry,
> >>
> >>
> >> On 19 August 2014 04:59, Thierry Reding <thierry.reding@gmail.com> wrote:
> >>
> >> > On Mon, Aug 18, 2014 at 11:52:36AM -0600, Simon Glass wrote:
> >> > > Hi Thierry,
> >> > >
> >> > > On 18 August 2014 01:16, Thierry Reding <thierry.reding@gmail.com>
> >> > wrote:
> >> > > > From: Thierry Reding <treding@nvidia.com>
> >> > > >
> >> > > > 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.
> >> > > >
> >> > > > Signed-off-by: Thierry Reding <treding@nvidia.com>
> >> > > > ---
> >> > > >  include/libfdt.h    | 28 ++++++++++++++++++++++++++++
> >> > > >  lib/libfdt/fdt_ro.c | 36 ++++++++++++++++++++++++++++++++++++
> >> > > >  2 files changed, 64 insertions(+)
> >> > > >
> >> > > > diff --git a/include/libfdt.h b/include/libfdt.h
> >> > > > index a1ef1e15df3d..e7f991b388cf 100644
> >> > > > --- a/include/libfdt.h
> >> > > > +++ b/include/libfdt.h
> >> > > > @@ -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);
> >> > >
> >> > > There is a new fdt_address_cells() recently that looks suitable.
> >> > >
> >> > > > +
> >> > > > +/**
> >> > > > + * 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.
> >> >
> >>
> >> 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 devicetree at vger.kernel.org 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
-------------- 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/ac9b544f/attachment.pgp>

^ permalink raw reply	[flat|nested] 95+ messages in thread

* [U-Boot] [PATCH 23/23] ARM: tegra: Enable PCIe on Jetson TK1
  2014-08-23  1:47               ` Simon Glass
@ 2014-08-23 11:33                 ` Thierry Reding
  0 siblings, 0 replies; 95+ messages in thread
From: Thierry Reding @ 2014-08-23 11:33 UTC (permalink / raw)
  To: u-boot

On Fri, Aug 22, 2014 at 07:47:36PM -0600, Simon Glass wrote:
> Hi Thierry,
> 
> On 22 August 2014 16:03, Thierry Reding <thierry.reding@gmail.com> wrote:
> > On Fri, Aug 22, 2014 at 02:12:19PM -0600, Simon Glass wrote:
> >> On 22 August 2014 13:40, Thierry Reding <thierry.reding@gmail.com> wrote:
> > [...]
> >> > 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.
> 
> 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>

^ permalink raw reply	[flat|nested] 95+ messages in thread

* [U-Boot] [PATCH 23/23] ARM: tegra: Enable PCIe on Jetson TK1
  2014-08-18  7:16 ` [U-Boot] [PATCH 23/23] ARM: tegra: Enable PCIe on Jetson TK1 Thierry Reding
                     ` (2 preceding siblings ...)
  2014-08-20 18:54   ` Stephen Warren
@ 2014-08-26 12:54   ` Tuomas Tynkkynen
  2014-08-27 13:28     ` Thierry Reding
  3 siblings, 1 reply; 95+ messages in thread
From: Tuomas Tynkkynen @ 2014-08-26 12:54 UTC (permalink / raw)
  To: u-boot

On 18/08/14 10:16, Thierry Reding wrote:
[...]
> +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;
> +	}
> +
> +	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)...

> +
> +int tegra_pcie_board_init(void)
> +{
[...]
> +
> +	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.

-- 
nvpublic

^ permalink raw reply	[flat|nested] 95+ messages in thread

* [U-Boot] [PATCH 23/23] ARM: tegra: Enable PCIe on Jetson TK1
  2014-08-26 12:54   ` Tuomas Tynkkynen
@ 2014-08-27 13:28     ` Thierry Reding
  2014-08-27 14:34       ` Thierry Reding
  0 siblings, 1 reply; 95+ messages in thread
From: Thierry Reding @ 2014-08-27 13:28 UTC (permalink / raw)
  To: u-boot

On Tue, Aug 26, 2014 at 03:54:50PM +0300, Tuomas Tynkkynen wrote:
> On 18/08/14 10:16, Thierry Reding wrote:
> [...]
> > +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;
> > +	}
> > +
> > +	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.

> > +
> > +int tegra_pcie_board_init(void)
> > +{
> [...]
> > +
> > +	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.

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>

^ permalink raw reply	[flat|nested] 95+ messages in thread

* [U-Boot] [PATCH 23/23] ARM: tegra: Enable PCIe on Jetson TK1
  2014-08-27 13:28     ` Thierry Reding
@ 2014-08-27 14:34       ` Thierry Reding
  2014-08-27 16:52         ` Tuomas Tynkkynen
  0 siblings, 1 reply; 95+ messages in thread
From: Thierry Reding @ 2014-08-27 14:34 UTC (permalink / raw)
  To: u-boot

On Wed, Aug 27, 2014 at 03:28:06PM +0200, Thierry Reding wrote:
> On Tue, Aug 26, 2014 at 03:54:50PM +0300, Tuomas Tynkkynen wrote:
> > On 18/08/14 10:16, Thierry Reding wrote:
> > [...]
> > > +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;
> > > +	}
> > > +
> > > +	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.
> 
> > > +
> > > +int tegra_pcie_board_init(void)
> > > +{
> > [...]
> > > +
> > > +	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.
> 
> 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 --------------
diff --git a/drivers/power/as3722.c b/drivers/power/as3722.c
index 59d1bf1b50b0..393dc8608d07 100644
--- a/drivers/power/as3722.c
+++ b/drivers/power/as3722.c
@@ -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>

^ permalink raw reply related	[flat|nested] 95+ messages in thread

* [U-Boot] [PATCH 23/23] ARM: tegra: Enable PCIe on Jetson TK1
  2014-08-27 14:34       ` Thierry Reding
@ 2014-08-27 16:52         ` Tuomas Tynkkynen
  0 siblings, 0 replies; 95+ messages in thread
From: Tuomas Tynkkynen @ 2014-08-27 16:52 UTC (permalink / raw)
  To: u-boot



On 27/08/14 17:34, Thierry Reding wrote:
[...]
>>> 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.
>>
>> 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.

-- 
nvpublic

^ permalink raw reply	[flat|nested] 95+ messages in thread

end of thread, other threads:[~2014-08-27 16:52 UTC | newest]

Thread overview: 95+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2014-08-18  7:16 [U-Boot] [PATCH 00/23] ARM: tegra: Add PCIe support Thierry Reding
2014-08-18  7:16 ` [U-Boot] [PATCH 01/23] fdt: Add functions to query a node's #address- and #size-cells Thierry Reding
2014-08-18 17:52   ` Simon Glass
2014-08-19 10:59     ` Thierry Reding
2014-08-19 12:52       ` Simon Glass
2014-08-19 13:06         ` Thierry Reding
2014-08-19 13:06           ` [U-Boot] " Thierry Reding
2014-08-23  3:03           ` Simon Glass
2014-08-23  3:03             ` [U-Boot] " Simon Glass
     [not found]             ` <CAPnjgZ06b3UeeXra5STLht15jU00yAKCwM+UYuqc=50Th9Jd_g-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>
2014-08-23 11:26               ` Thierry Reding
2014-08-23 11:26                 ` [U-Boot] " Thierry Reding
2014-08-18  7:16 ` [U-Boot] [PATCH 02/23] fdt: Add a function to get the index of a string Thierry Reding
2014-08-18 17:58   ` Simon Glass
2014-08-19 11:13     ` Thierry Reding
2014-08-18  7:16 ` [U-Boot] [PATCH 03/23] fdt: Add resource parsing functions Thierry Reding
2014-08-18 18:06   ` Simon Glass
2014-08-19 11:35     ` Thierry Reding
2014-08-19 12:55       ` Simon Glass
2014-08-19 13:12         ` Thierry Reding
2014-08-19 21:28           ` Simon Glass
2014-08-20  6:36             ` Thierry Reding
2014-08-20 14:05               ` Simon Glass
2014-08-18  7:16 ` [U-Boot] [PATCH 04/23] fdt: Add a function to return PCI BDF triplet Thierry Reding
2014-08-18 18:20   ` Simon Glass
2014-08-18  7:16 ` [U-Boot] [PATCH 05/23] fdt: Add a subnodes iterator macro Thierry Reding
2014-08-18 18:11   ` Simon Glass
2014-08-19 12:22     ` Thierry Reding
2014-08-19 12:57       ` Simon Glass
2014-08-19 13:12         ` Thierry Reding
2014-08-18  7:16 ` [U-Boot] [PATCH 06/23] pci: Abort early if bus does not exist Thierry Reding
2014-08-18  7:16 ` [U-Boot] [PATCH 07/23] pci: Honour pci_skip_dev() Thierry Reding
2014-08-18  7:16 ` [U-Boot] [PATCH 08/23] Add pr_fmt() macro Thierry Reding
2014-08-18 18:24   ` Simon Glass
2014-08-19 12:27     ` Thierry Reding
2014-08-19 12:58       ` Simon Glass
2014-08-18  7:16 ` [U-Boot] [PATCH 09/23] ARM: tegra: Implement tegra_plle_enable() Thierry Reding
2014-08-20 18:12   ` Stephen Warren
2014-08-18  7:16 ` [U-Boot] [PATCH 10/23] ARM: tegra: Provide PCIEXCLK reset ID Thierry Reding
2014-08-20 18:20   ` Stephen Warren
2014-08-22 12:38     ` Thierry Reding
2014-08-18  7:16 ` [U-Boot] [PATCH 11/23] ARM: tegra: Implement powergate support Thierry Reding
2014-08-20 18:24   ` Stephen Warren
2014-08-22 13:54     ` Thierry Reding
2014-08-18  7:16 ` [U-Boot] [PATCH 12/23] ARM: tegra: Implement XUSB pad controller Thierry Reding
2014-08-20 18:32   ` Stephen Warren
2014-08-22 14:11     ` Thierry Reding
2014-08-22 14:38     ` Thierry Reding
2014-08-18  7:16 ` [U-Boot] [PATCH 13/23] ARM: tegra: Add XUSB pad controller on Tegra124 Thierry Reding
2014-08-20 18:33   ` Stephen Warren
2014-08-18  7:16 ` [U-Boot] [PATCH 14/23] ARM: tegra: Enable XUSB pad controller on Jetson TK1 Thierry Reding
2014-08-20 18:34   ` Stephen Warren
2014-08-18  7:16 ` [U-Boot] [PATCH 15/23] pci: tegra: Add Tegra PCIe driver Thierry Reding
2014-08-20 19:04   ` Stephen Warren
2014-08-22 15:24     ` Thierry Reding
2014-08-22 17:33     ` Stephen Warren
2014-08-22 19:41       ` Thierry Reding
2014-08-18  7:16 ` [U-Boot] [PATCH 16/23] ARM: tegra: Add Tegra20 PCIe device tree node Thierry Reding
2014-08-20 18:37   ` Stephen Warren
2014-08-18  7:16 ` [U-Boot] [PATCH 17/23] ARM: tegra: Enable PCIe on TrimSlice Thierry Reding
2014-08-20 18:38   ` Stephen Warren
2014-08-22 14:44     ` Thierry Reding
2014-08-18  7:16 ` [U-Boot] [PATCH 18/23] ARM: tegra: Add Tegra30 PCIe device tree node Thierry Reding
2014-08-20 18:39   ` Stephen Warren
2014-08-22 14:51     ` Thierry Reding
2014-08-18  7:16 ` [U-Boot] [PATCH 19/23] ARM: tegra: Enable PCIe on Beaver Thierry Reding
2014-08-19 13:48   ` Marcel Ziswiler
2014-08-20  6:38     ` Thierry Reding
2014-08-20  8:56       ` Marcel Ziswiler
2014-08-20  9:46         ` Thierry Reding
2014-08-20 13:13           ` Marcel Ziswiler
2014-08-20 18:43   ` Stephen Warren
2014-08-22 12:33     ` Thierry Reding
2014-08-18  7:16 ` [U-Boot] [PATCH 20/23] ARM: tegra: Enable PCIe on Cardhu Thierry Reding
2014-08-18  7:16 ` [U-Boot] [PATCH 21/23] ARM: tegra: Add GIC for Tegra124 Thierry Reding
2014-08-20 18:45   ` Stephen Warren
2014-08-18  7:16 ` [U-Boot] [PATCH 22/23] ARM: tegra: Add Tegra124 PCIe device tree node Thierry Reding
2014-08-20 18:46   ` Stephen Warren
2014-08-18  7:16 ` [U-Boot] [PATCH 23/23] ARM: tegra: Enable PCIe on Jetson TK1 Thierry Reding
2014-08-18 18:37   ` Simon Glass
2014-08-19 12:29     ` Thierry Reding
2014-08-19 13:07       ` Simon Glass
2014-08-20 18:51   ` Stephen Warren
2014-08-22 12:09     ` Thierry Reding
2014-08-22 18:50       ` Stephen Warren
2014-08-22 19:27       ` Simon Glass
2014-08-22 19:40         ` Thierry Reding
2014-08-22 20:12           ` Simon Glass
2014-08-22 22:03             ` Thierry Reding
2014-08-23  1:47               ` Simon Glass
2014-08-23 11:33                 ` Thierry Reding
2014-08-20 18:54   ` Stephen Warren
2014-08-26 12:54   ` Tuomas Tynkkynen
2014-08-27 13:28     ` Thierry Reding
2014-08-27 14:34       ` Thierry Reding
2014-08-27 16:52         ` Tuomas Tynkkynen

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.