All of lore.kernel.org
 help / color / mirror / Atom feed
* [U-Boot] [PATCH v2 00/40] ARM: tegra: Add PCIe support
@ 2014-08-26 15:33 Thierry Reding
  2014-08-26 15:33 ` [U-Boot] [PATCH v2 01/40] vsprintf: Add modifier for phys_addr_t Thierry Reding
                   ` (42 more replies)
  0 siblings, 43 replies; 104+ messages in thread
From: Thierry Reding @ 2014-08-26 15:33 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). In this version I've included
all patches that were previously split into three separate series. Spreading
them over multiple series is probably not worth it since there might be some
dependencies between them and only the end result gives a completely working
setup.

Patch 1 adds a %pa modifier to printf() to print physical addresses. This is
required to allow code to output such addresses irrespective of whether a 64
bit or 32 bit architecture is built for.

Patches 2-7 add various FDT helpers to make it easier to parse complex device
trees.

Patch 8 is a minor cleanup to the PCI command that prevents a spew of error
messages if a bus does not exist. Patch 9 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 10 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 11-14 are some cleanup and refactoring of I2C core code, the addition
of a higher level API that makes it easier for I2C client drivers to talk to
devices. The Tegra I2C driver now implements i2c_get_bus_num_fdt() to obtain
bus numbers corresponding to a DT node.

Patch 15 implements a driver for the AS3722 PMIC used on the Venice2 and
Jetson TK1 boards.

Patches 16-21 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 22 adds the PCIe controller driver for Tegra20, Tegra30 and Tegra124.

Device tree nodes and configurations options to enable PCIe on the TrimSlice
(Tegra20), Beaver, Cardhu (Tegra30) and Jetson TK1 (Tegra124) boards are
added in patches 23-31.

Patches 32-35 implement non-cached memory support that will be used in the
last batch of patches to implement more reliable packet transfers in the
r8169 driver. Patch 36 enables non-cached memory support on Tegra.

Finally, patches 37-40 implement non-cached memory support and various fixes
in the r8169 driver and add support for the revision of the NIC found on the
Jetson TK1.

The above boards all have an ethernet NIC connected to PCIe, which is what
I tested with.

Thierry Reding (40):
  vsprintf: Add modifier for phys_addr_t
  fdt: Add a function to count strings
  fdt: Add a function to get the index of a string
  fdt: Add functions to retrieve strings
  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
  i2c: Initialize the correct bus
  i2c: Refactor adapter initialization
  i2c: Add high-level API
  i2c: tegra: Implement i2c_get_bus_num_fdt()
  power: Add AMS AS3722 PMIC support
  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 GIC for Tegra30
  ARM: tegra: Add Tegra30 PCIe device tree node
  ARM: tegra: Enable PCIe on Cardhu
  ARM: tegra: Enable PCIe on Beaver
  ARM: tegra: Add GIC for Tegra124
  ARM: tegra: Add Tegra124 PCIe device tree node
  ARM: tegra: Enable PCIe on Jetson TK1
  ARM: cache_v7: Various minor cleanups
  ARM: cache-cp15: Use more accurate types
  malloc: Output region when debugging
  ARM: Implement non-cached memory support
  ARM: tegra: Enable non-cached memory
  net: rtl8169: Honor CONFIG_SYS_RX_ETH_BUFFER
  net: rtl8169: Properly align buffers
  net: rtl8169: Use non-cached memory if available
  net: rtl8169: Add support for RTL-8168/8111g

 README                                           |   19 +
 arch/arm/cpu/armv7/cache_v7.c                    |   14 +-
 arch/arm/cpu/tegra-common/Makefile               |    2 +
 arch/arm/cpu/tegra-common/powergate.c            |  102 ++
 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       |  716 ++++++++++++++
 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               |   69 ++
 arch/arm/dts/tegra20.dtsi                        |   60 ++
 arch/arm/dts/tegra30-beaver.dts                  |  245 +++++
 arch/arm/dts/tegra30-cardhu.dts                  |  362 +++++++
 arch/arm/dts/tegra30.dtsi                        |   84 ++
 arch/arm/include/asm/arch-tegra/powergate.h      |   38 +
 arch/arm/include/asm/arch-tegra/xusb-padctl.h    |   24 +
 arch/arm/include/asm/arch-tegra114/powergate.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-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-tegra30/clock.h        |    2 +
 arch/arm/include/asm/arch-tegra30/powergate.h    |    6 +
 arch/arm/include/asm/system.h                    |    7 +-
 arch/arm/lib/cache-cp15.c                        |    6 +-
 arch/arm/lib/cache.c                             |   42 +
 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             |   52 +
 common/board_r.c                                 |   11 +
 common/cmd_pci.c                                 |    7 +
 common/dlmalloc.c                                |    3 +
 drivers/i2c/i2c_core.c                           |   80 +-
 drivers/i2c/tegra_i2c.c                          |   13 +
 drivers/net/rtl8169.c                            |  127 ++-
 drivers/pci/Makefile                             |    1 +
 drivers/pci/pci.c                                |    3 +
 drivers/pci/pci_tegra.c                          | 1143 ++++++++++++++++++++++
 drivers/power/Makefile                           |    1 +
 drivers/power/as3722.c                           |  300 ++++++
 include/common.h                                 |   14 +-
 include/configs/beaver.h                         |   10 +
 include/configs/cardhu.h                         |   10 +
 include/configs/jetson-tk1.h                     |   13 +
 include/configs/tegra-common.h                   |    1 +
 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                                 |   69 ++
 include/i2c.h                                    |   96 ++
 include/libfdt.h                                 |   72 ++
 include/pci.h                                    |    1 +
 include/power/as3722.h                           |   27 +
 lib/fdtdec.c                                     |   76 ++
 lib/libfdt/fdt_ro.c                              |   76 ++
 lib/vsprintf.c                                   |   16 +-
 63 files changed, 5736 insertions(+), 64 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-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
 create mode 100644 drivers/pci/pci_tegra.c
 create mode 100644 drivers/power/as3722.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
 create mode 100644 include/power/as3722.h

-- 
2.0.4

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

* [U-Boot] [PATCH v2 01/40] vsprintf: Add modifier for phys_addr_t
  2014-08-26 15:33 [U-Boot] [PATCH v2 00/40] ARM: tegra: Add PCIe support Thierry Reding
@ 2014-08-26 15:33 ` Thierry Reding
  2014-08-26 17:04   ` Stephen Warren
  2014-08-26 23:14   ` [U-Boot] [PATCH v2 " Simon Glass
  2014-08-26 15:33 ` [U-Boot] [PATCH v2 02/40] fdt: Add a function to count strings Thierry Reding
                   ` (41 subsequent siblings)
  42 siblings, 2 replies; 104+ messages in thread
From: Thierry Reding @ 2014-08-26 15:33 UTC (permalink / raw)
  To: u-boot

From: Thierry Reding <treding@nvidia.com>

Provide a new modifier to vsprintf() to print phys_addr_t variables to
avoid having to cast or #ifdef when printing them out. The %pa modifier
is used for this purpose, so phys_addr_t variables need to be passed by
reference, like so:

	phys_addr_t start = 0;

	printf("start: %pa\n", &start);

Depending on the size of phys_addr_t this will print out the address
with 8 or 16 hexadecimal digits following a 0x prefix.

Signed-off-by: Thierry Reding <treding@nvidia.com>
---
 lib/vsprintf.c | 16 ++++++++++++++--
 1 file changed, 14 insertions(+), 2 deletions(-)

diff --git a/lib/vsprintf.c b/lib/vsprintf.c
index 7ec758e40fc5..044d5551bdd0 100644
--- a/lib/vsprintf.c
+++ b/lib/vsprintf.c
@@ -518,6 +518,8 @@ static char *ip4_addr_string(char *buf, char *end, u8 *addr, int field_width,
 static char *pointer(const char *fmt, char *buf, char *end, void *ptr,
 		int field_width, int precision, int flags)
 {
+	u64 num = (uintptr_t)ptr;
+
 	/*
 	 * Being a boot loader, we explicitly allow pointers to
 	 * (physical) address null.
@@ -530,6 +532,17 @@ static char *pointer(const char *fmt, char *buf, char *end, void *ptr,
 
 #ifdef CONFIG_CMD_NET
 	switch (*fmt) {
+	case 'a':
+		flags |= SPECIAL | ZEROPAD;
+
+		switch (fmt[1]) {
+		case 'p':
+		default:
+			field_width = sizeof(phys_addr_t) * 2 + 2;
+			num = *(phys_addr_t *)ptr;
+			break;
+		}
+		break;
 	case 'm':
 		flags |= SPECIAL;
 		/* Fallthrough */
@@ -555,8 +568,7 @@ static char *pointer(const char *fmt, char *buf, char *end, void *ptr,
 		field_width = 2*sizeof(void *);
 		flags |= ZEROPAD;
 	}
-	return number(buf, end, (unsigned long)ptr, 16, field_width,
-		      precision, flags);
+	return number(buf, end, num, 16, field_width, precision, flags);
 }
 
 static int vsnprintf_internal(char *buf, size_t size, const char *fmt,
-- 
2.0.4

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

* [U-Boot] [PATCH v2 02/40] fdt: Add a function to count strings
  2014-08-26 15:33 [U-Boot] [PATCH v2 00/40] ARM: tegra: Add PCIe support Thierry Reding
  2014-08-26 15:33 ` [U-Boot] [PATCH v2 01/40] vsprintf: Add modifier for phys_addr_t Thierry Reding
@ 2014-08-26 15:33 ` Thierry Reding
  2014-08-27 18:51   ` Simon Glass
  2014-08-26 15:33 ` [U-Boot] [PATCH v2 03/40] fdt: Add a function to get the index of a string Thierry Reding
                   ` (40 subsequent siblings)
  42 siblings, 1 reply; 104+ messages in thread
From: Thierry Reding @ 2014-08-26 15:33 UTC (permalink / raw)
  To: u-boot

From: Thierry Reding <treding@nvidia.com>

Given a device tree node and a property name, the fdt_count_strings()
function counts the number of strings found in the property value.

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

diff --git a/include/libfdt.h b/include/libfdt.h
index a1ef1e15df3d..cf97bf0b3b52 100644
--- a/include/libfdt.h
+++ b/include/libfdt.h
@@ -857,6 +857,15 @@ int fdt_node_offset_by_compatible(const void *fdt, int startoffset,
  */
 int fdt_stringlist_contains(const char *strlist, int listlen, const char *str);
 
+/**
+ * fdt_count_strings - count the number of strings 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
+ * @return: the number of strings in the given property
+ */
+int fdt_count_strings(const void *fdt, int node, const char *property);
+
 /**********************************************************************/
 /* Read-only functions (addressing related)                           */
 /**********************************************************************/
diff --git a/lib/libfdt/fdt_ro.c b/lib/libfdt/fdt_ro.c
index 36af0435254b..cb06a9b50d85 100644
--- a/lib/libfdt/fdt_ro.c
+++ b/lib/libfdt/fdt_ro.c
@@ -491,6 +491,26 @@ int fdt_stringlist_contains(const char *strlist, int listlen, const char *str)
 	return 0;
 }
 
+int fdt_count_strings(const void *fdt, int node, const char *property)
+{
+	int length, i, count = 0;
+	const char *list;
+
+	list = fdt_getprop(fdt, node, property, &length);
+	if (!list)
+		return -length;
+
+	for (i = 0; i < length; i++) {
+		int len = strlen(list);
+
+		list += len + 1;
+		i += len;
+		count++;
+	}
+
+	return count;
+}
+
 int fdt_node_check_compatible(const void *fdt, int nodeoffset,
 			      const char *compatible)
 {
-- 
2.0.4

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

* [U-Boot] [PATCH v2 03/40] fdt: Add a function to get the index of a string
  2014-08-26 15:33 [U-Boot] [PATCH v2 00/40] ARM: tegra: Add PCIe support Thierry Reding
  2014-08-26 15:33 ` [U-Boot] [PATCH v2 01/40] vsprintf: Add modifier for phys_addr_t Thierry Reding
  2014-08-26 15:33 ` [U-Boot] [PATCH v2 02/40] fdt: Add a function to count strings Thierry Reding
@ 2014-08-26 15:33 ` Thierry Reding
  2014-08-27 18:51   ` Simon Glass
  2014-08-26 15:33 ` [U-Boot] [PATCH v2 04/40] fdt: Add functions to retrieve strings Thierry Reding
                   ` (39 subsequent siblings)
  42 siblings, 1 reply; 104+ messages in thread
From: Thierry Reding @ 2014-08-26 15:33 UTC (permalink / raw)
  To: u-boot

From: Thierry Reding <treding@nvidia.com>

Given a device tree node and a property name, the new fdt_find_string()
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>
---
Changes in v2:
- rename to fdt_find_string() to remove naming conflicts with other new
  functions
- correctly increment string list pointer

 include/libfdt.h    | 11 +++++++++++
 lib/libfdt/fdt_ro.c | 26 ++++++++++++++++++++++++++
 2 files changed, 37 insertions(+)

diff --git a/include/libfdt.h b/include/libfdt.h
index cf97bf0b3b52..d0dea668eea2 100644
--- a/include/libfdt.h
+++ b/include/libfdt.h
@@ -866,6 +866,17 @@ int fdt_stringlist_contains(const char *strlist, int listlen, const char *str);
  */
 int fdt_count_strings(const void *fdt, int node, const char *property);
 
+/**
+ * fdt_find_string - find a string in a string list and return its index
+ * @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_find_string(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 cb06a9b50d85..fec4a0a141fd 100644
--- a/lib/libfdt/fdt_ro.c
+++ b/lib/libfdt/fdt_ro.c
@@ -511,6 +511,32 @@ int fdt_count_strings(const void *fdt, int node, const char *property)
 	return count;
 }
 
+int fdt_find_string(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;
+	len = strlen(string);
+
+	while (list < end) {
+		int l = strlen(list);
+
+		if (l == len && memcmp(list, string, len) == 0)
+			return index;
+
+		list += l + 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] 104+ messages in thread

* [U-Boot] [PATCH v2 04/40] fdt: Add functions to retrieve strings
  2014-08-26 15:33 [U-Boot] [PATCH v2 00/40] ARM: tegra: Add PCIe support Thierry Reding
                   ` (2 preceding siblings ...)
  2014-08-26 15:33 ` [U-Boot] [PATCH v2 03/40] fdt: Add a function to get the index of a string Thierry Reding
@ 2014-08-26 15:33 ` Thierry Reding
  2014-08-27 18:53   ` Simon Glass
  2014-08-26 15:33 ` [U-Boot] [PATCH v2 05/40] fdt: Add resource parsing functions Thierry Reding
                   ` (38 subsequent siblings)
  42 siblings, 1 reply; 104+ messages in thread
From: Thierry Reding @ 2014-08-26 15:33 UTC (permalink / raw)
  To: u-boot

From: Thierry Reding <treding@nvidia.com>

Given a device tree node, a property name and an index, the new function
fdt_get_string_index() will return in an output argument a pointer to
the index'th string in the property's value.

The fdt_get_string() is a shortcut for the above with the index being 0.

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

diff --git a/include/libfdt.h b/include/libfdt.h
index d0dea668eea2..2dfc6d9e5ce7 100644
--- a/include/libfdt.h
+++ b/include/libfdt.h
@@ -877,6 +877,33 @@ int fdt_count_strings(const void *fdt, int node, const char *property);
 int fdt_find_string(const void *fdt, int node, const char *property,
 		    const char *string);
 
+/**
+ * fdt_get_string_index() - obtain the string at a given index 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
+ * @index: index of the string to return
+ * @output: return location for the string
+ * @return: 0 if the string was found or a negative error code otherwise
+ */
+int fdt_get_string_index(const void *fdt, int node, const char *property,
+			 int index, const char **output);
+
+/**
+ * fdt_get_string() - obtain the string at a given index 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
+ * @output: return location for the string
+ * @return: 0 if the string was found or a negative error code otherwise
+ *
+ * This is a shortcut for:
+ *
+ *	fdt_get_string_index(fdt, node, property, 0, output).
+ */
+int fdt_get_string(const void *fdt, int node, const char *property,
+		   const char **output);
+
 /**********************************************************************/
 /* Read-only functions (addressing related)                           */
 /**********************************************************************/
diff --git a/lib/libfdt/fdt_ro.c b/lib/libfdt/fdt_ro.c
index fec4a0a141fd..03733e574f71 100644
--- a/lib/libfdt/fdt_ro.c
+++ b/lib/libfdt/fdt_ro.c
@@ -537,6 +537,36 @@ int fdt_find_string(const void *fdt, int node, const char *property,
 	return -FDT_ERR_NOTFOUND;
 }
 
+int fdt_get_string_index(const void *fdt, int node, const char *property,
+			 int index, const char **output)
+{
+	const char *list;
+	int length, i;
+
+	list = fdt_getprop(fdt, node, property, &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 fdt_get_string(const void *fdt, int node, const char *property,
+		   const char **output)
+{
+	return fdt_get_string_index(fdt, node, property, 0, output);
+}
+
 int fdt_node_check_compatible(const void *fdt, int nodeoffset,
 			      const char *compatible)
 {
-- 
2.0.4

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

* [U-Boot] [PATCH v2 05/40] fdt: Add resource parsing functions
  2014-08-26 15:33 [U-Boot] [PATCH v2 00/40] ARM: tegra: Add PCIe support Thierry Reding
                   ` (3 preceding siblings ...)
  2014-08-26 15:33 ` [U-Boot] [PATCH v2 04/40] fdt: Add functions to retrieve strings Thierry Reding
@ 2014-08-26 15:33 ` Thierry Reding
  2014-08-27 18:53   ` Simon Glass
  2014-09-08 15:02   ` Simon Glass
  2014-08-26 15:33 ` [U-Boot] [PATCH v2 06/40] fdt: Add a function to return PCI BDF triplet Thierry Reding
                   ` (37 subsequent siblings)
  42 siblings, 2 replies; 104+ messages in thread
From: Thierry Reding @ 2014-08-26 15:33 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>
---
Changes in v2:
- use existing fdt_address_cells() and fdt_size_cells() functions
- add clarifying comments to struct fdt_resource declaration
- rename names variable to prop_names for clarity
- properly handle 64-bit addresses (compile-tested only)
- update for fdt_get_string_index() -> fdt_find_string() rename

 include/fdtdec.h | 52 +++++++++++++++++++++++++++++++++++++++++++++++++++
 lib/fdtdec.c     | 57 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 109 insertions(+)

diff --git a/include/fdtdec.h b/include/fdtdec.h
index 856e6cf766de..c35d378602d2 100644
--- a/include/fdtdec.h
+++ b/include/fdtdec.h
@@ -40,6 +40,27 @@ struct fdt_memory {
 	fdt_addr_t end;
 };
 
+/*
+ * 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.
+ */
+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 +604,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 prop_names	name of the property containing the list of names
+ * @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 *prop_names, const char *name,
+			   struct fdt_resource *res);
+
 #endif
diff --git a/lib/fdtdec.c b/lib/fdtdec.c
index eb5aa20526fd..c3fa82f1a28a 100644
--- a/lib/fdtdec.c
+++ b/lib/fdtdec.c
@@ -691,4 +691,61 @@ int fdtdec_read_fmap_entry(const void *blob, int node, const char *name,
 
 	return 0;
 }
+
+static u64 fdtdec_get_number(const fdt32_t *ptr, unsigned int cells)
+{
+	u64 number = 0;
+
+	while (cells--)
+		number = (number << 32) | fdt32_to_cpu(*ptr++);
+
+	return number;
+}
+
+int fdt_get_resource(const void *fdt, int node, const char *property,
+		     unsigned int index, struct fdt_resource *res)
+{
+	const fdt32_t *ptr, *end;
+	int na, ns, len, parent;
+	unsigned int i = 0;
+
+	parent = fdt_parent_offset(fdt, node);
+	if (parent < 0)
+		return parent;
+
+	na = fdt_address_cells(fdt, parent);
+	ns = fdt_size_cells(fdt, parent);
+
+	ptr = fdt_getprop(fdt, node, property, &len);
+	if (!ptr)
+		return len;
+
+	end = ptr + len / sizeof(*ptr);
+
+	while (ptr + na + ns <= end) {
+		if (i == index) {
+			res->start = res->end = fdtdec_get_number(ptr, na);
+			res->end += fdtdec_get_number(&ptr[na], ns) - 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 *prop_names, const char *name,
+			   struct fdt_resource *res)
+{
+	int index;
+
+	index = fdt_find_string(fdt, node, prop_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] 104+ messages in thread

* [U-Boot] [PATCH v2 06/40] fdt: Add a function to return PCI BDF triplet
  2014-08-26 15:33 [U-Boot] [PATCH v2 00/40] ARM: tegra: Add PCIe support Thierry Reding
                   ` (4 preceding siblings ...)
  2014-08-26 15:33 ` [U-Boot] [PATCH v2 05/40] fdt: Add resource parsing functions Thierry Reding
@ 2014-08-26 15:33 ` Thierry Reding
  2014-09-08 15:03   ` Simon Glass
  2014-08-26 15:33 ` [U-Boot] [PATCH v2 07/40] fdt: Add a subnodes iterator macro Thierry Reding
                   ` (36 subsequent siblings)
  42 siblings, 1 reply; 104+ messages in thread
From: Thierry Reding @ 2014-08-26 15:33 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.

Acked-by: Simon Glass <sjg@chromium.org>
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 c35d378602d2..5c669a5c8e03 100644
--- a/include/fdtdec.h
+++ b/include/fdtdec.h
@@ -635,4 +635,15 @@ int fdt_get_named_resource(const void *fdt, int node, const char *property,
 			   const char *prop_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 c3fa82f1a28a..fa5da0c0147d 100644
--- a/lib/fdtdec.c
+++ b/lib/fdtdec.c
@@ -748,4 +748,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] 104+ messages in thread

* [U-Boot] [PATCH v2 07/40] fdt: Add a subnodes iterator macro
  2014-08-26 15:33 [U-Boot] [PATCH v2 00/40] ARM: tegra: Add PCIe support Thierry Reding
                   ` (5 preceding siblings ...)
  2014-08-26 15:33 ` [U-Boot] [PATCH v2 06/40] fdt: Add a function to return PCI BDF triplet Thierry Reding
@ 2014-08-26 15:33 ` Thierry Reding
  2014-09-08 15:03   ` Simon Glass
  2014-08-26 15:33 ` [U-Boot] [PATCH v2 08/40] pci: Abort early if bus does not exist Thierry Reding
                   ` (35 subsequent siblings)
  42 siblings, 1 reply; 104+ messages in thread
From: Thierry Reding @ 2014-08-26 15:33 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.

Acked-by: Simon Glass <sjg@chromium.org>
Signed-off-by: Thierry Reding <treding@nvidia.com>
---
Changes in v2:
- specify the data types in the comment because the macro doesn't have them

 include/libfdt.h | 25 +++++++++++++++++++++++++
 1 file changed, 25 insertions(+)

diff --git a/include/libfdt.h b/include/libfdt.h
index 2dfc6d9e5ce7..f3cbb637be41 100644
--- a/include/libfdt.h
+++ b/include/libfdt.h
@@ -163,6 +163,31 @@ 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
+ *		...
+ *	}
+ *
+ * Note that this is implemented as a macro and node is used as iterator in
+ * the loop. It should therefore be a locally allocated variable. The parent
+ * variable on the other hand is never modified, so it can be constant or
+ * even a literal.
+ *
+ * @fdt:	FDT blob (const void *)
+ * @node:	child node (int)
+ * @parent:	parent node (int)
+ */
+#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] 104+ messages in thread

* [U-Boot] [PATCH v2 08/40] pci: Abort early if bus does not exist
  2014-08-26 15:33 [U-Boot] [PATCH v2 00/40] ARM: tegra: Add PCIe support Thierry Reding
                   ` (6 preceding siblings ...)
  2014-08-26 15:33 ` [U-Boot] [PATCH v2 07/40] fdt: Add a subnodes iterator macro Thierry Reding
@ 2014-08-26 15:33 ` Thierry Reding
  2014-08-26 15:33 ` [U-Boot] [PATCH v2 09/40] pci: Honour pci_skip_dev() Thierry Reding
                   ` (34 subsequent siblings)
  42 siblings, 0 replies; 104+ messages in thread
From: Thierry Reding @ 2014-08-26 15:33 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] 104+ messages in thread

* [U-Boot] [PATCH v2 09/40] pci: Honour pci_skip_dev()
  2014-08-26 15:33 [U-Boot] [PATCH v2 00/40] ARM: tegra: Add PCIe support Thierry Reding
                   ` (7 preceding siblings ...)
  2014-08-26 15:33 ` [U-Boot] [PATCH v2 08/40] pci: Abort early if bus does not exist Thierry Reding
@ 2014-08-26 15:33 ` Thierry Reding
  2014-08-26 15:33 ` [U-Boot] [PATCH v2 10/40] Add pr_fmt() macro Thierry Reding
                   ` (33 subsequent siblings)
  42 siblings, 0 replies; 104+ messages in thread
From: Thierry Reding @ 2014-08-26 15:33 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] 104+ messages in thread

* [U-Boot] [PATCH v2 10/40] Add pr_fmt() macro
  2014-08-26 15:33 [U-Boot] [PATCH v2 00/40] ARM: tegra: Add PCIe support Thierry Reding
                   ` (8 preceding siblings ...)
  2014-08-26 15:33 ` [U-Boot] [PATCH v2 09/40] pci: Honour pci_skip_dev() Thierry Reding
@ 2014-08-26 15:33 ` Thierry Reding
  2014-08-26 15:33 ` [U-Boot] [PATCH v2 11/40] i2c: Initialize the correct bus Thierry Reding
                   ` (32 subsequent siblings)
  42 siblings, 0 replies; 104+ messages in thread
From: Thierry Reding @ 2014-08-26 15:33 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

Acked-by: Simon Glass <sjg@chromium.org>
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] 104+ messages in thread

* [U-Boot] [PATCH v2 11/40] i2c: Initialize the correct bus
  2014-08-26 15:33 [U-Boot] [PATCH v2 00/40] ARM: tegra: Add PCIe support Thierry Reding
                   ` (9 preceding siblings ...)
  2014-08-26 15:33 ` [U-Boot] [PATCH v2 10/40] Add pr_fmt() macro Thierry Reding
@ 2014-08-26 15:33 ` Thierry Reding
  2014-08-27  4:52   ` Heiko Schocher
  2014-08-26 15:34 ` [U-Boot] [PATCH v2 12/40] i2c: Refactor adapter initialization Thierry Reding
                   ` (31 subsequent siblings)
  42 siblings, 1 reply; 104+ messages in thread
From: Thierry Reding @ 2014-08-26 15:33 UTC (permalink / raw)
  To: u-boot

From: Thierry Reding <treding@nvidia.com>

i2c_bus_init() takes a bus number but relies on the currently selected
bus to determine which adapter to initialize. Make the function use the
bus passed in as parameter rather than the currently selected bus. While
at it, keep a pointer to the specified bus to avoid having to look it up
repeatedly.

Signed-off-by: Thierry Reding <treding@nvidia.com>
---
 drivers/i2c/i2c_core.c | 15 +++++++++------
 1 file changed, 9 insertions(+), 6 deletions(-)

diff --git a/drivers/i2c/i2c_core.c b/drivers/i2c/i2c_core.c
index 18d6736601c1..cca455bc9c63 100644
--- a/drivers/i2c/i2c_core.c
+++ b/drivers/i2c/i2c_core.c
@@ -214,17 +214,20 @@ static int i2c_mux_disconnet_all(void)
  * Initializes one bus. Will initialize the parent adapter. No current bus
  * changes, no mux (if any) setup.
  */
-static void i2c_init_bus(unsigned int bus_no, int speed, int slaveaddr)
+static void i2c_init_bus(unsigned int bus, int speed, int slaveaddr)
 {
-	if (bus_no >= CONFIG_SYS_NUM_I2C_BUSES)
+	struct i2c_adapter *adapter;
+
+	if (bus >= CONFIG_SYS_NUM_I2C_BUSES)
 		return;
 
-	I2C_ADAP->init(I2C_ADAP, speed, slaveaddr);
+	adapter = i2c_get_adapter(I2C_ADAPTER(bus));
+	adapter->init(adapter, speed, slaveaddr);
 
 	if (gd->flags & GD_FLG_RELOC) {
-		I2C_ADAP->init_done = 1;
-		I2C_ADAP->speed = speed;
-		I2C_ADAP->slaveaddr = slaveaddr;
+		adapter->init_done = 1;
+		adapter->speed = speed;
+		adapter->slaveaddr = slaveaddr;
 	}
 }
 
-- 
2.0.4

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

* [U-Boot] [PATCH v2 12/40] i2c: Refactor adapter initialization
  2014-08-26 15:33 [U-Boot] [PATCH v2 00/40] ARM: tegra: Add PCIe support Thierry Reding
                   ` (10 preceding siblings ...)
  2014-08-26 15:33 ` [U-Boot] [PATCH v2 11/40] i2c: Initialize the correct bus Thierry Reding
@ 2014-08-26 15:34 ` Thierry Reding
  2014-08-26 15:34 ` [U-Boot] [PATCH v2 13/40] i2c: Add high-level API Thierry Reding
                   ` (30 subsequent siblings)
  42 siblings, 0 replies; 104+ messages in thread
From: Thierry Reding @ 2014-08-26 15:34 UTC (permalink / raw)
  To: u-boot

From: Thierry Reding <treding@nvidia.com>

A subsequent patch will introduce a new API to access I2C adapters
directly rather than going through the bus number and constantly looking
up the same adapter. In order to share the adapter initialization code,
move it into a separate function and make i2c_init_bus() use it to avoid
code duplication.

Signed-off-by: Thierry Reding <treding@nvidia.com>
---
 drivers/i2c/i2c_core.c | 20 +++++++++++++-------
 1 file changed, 13 insertions(+), 7 deletions(-)

diff --git a/drivers/i2c/i2c_core.c b/drivers/i2c/i2c_core.c
index cca455bc9c63..f6179a16244b 100644
--- a/drivers/i2c/i2c_core.c
+++ b/drivers/i2c/i2c_core.c
@@ -207,6 +207,18 @@ static int i2c_mux_disconnet_all(void)
 }
 #endif
 
+static void i2c_adapter_init(struct i2c_adapter *adapter, unsigned int speed,
+			     unsigned int slaveaddr)
+{
+	adapter->init(adapter, speed, slaveaddr);
+
+	if (gd->flags & GD_FLG_RELOC) {
+		adapter->slaveaddr = slaveaddr;
+		adapter->speed = speed;
+		adapter->init_done = 1;
+	}
+}
+
 /*
  * i2c_init_bus():
  * ---------------
@@ -222,13 +234,7 @@ static void i2c_init_bus(unsigned int bus, int speed, int slaveaddr)
 		return;
 
 	adapter = i2c_get_adapter(I2C_ADAPTER(bus));
-	adapter->init(adapter, speed, slaveaddr);
-
-	if (gd->flags & GD_FLG_RELOC) {
-		adapter->init_done = 1;
-		adapter->speed = speed;
-		adapter->slaveaddr = slaveaddr;
-	}
+	i2c_adapter_init(adapter, speed, slaveaddr);
 }
 
 /* implement possible board specific board init */
-- 
2.0.4

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

* [U-Boot] [PATCH v2 13/40] i2c: Add high-level API
  2014-08-26 15:33 [U-Boot] [PATCH v2 00/40] ARM: tegra: Add PCIe support Thierry Reding
                   ` (11 preceding siblings ...)
  2014-08-26 15:34 ` [U-Boot] [PATCH v2 12/40] i2c: Refactor adapter initialization Thierry Reding
@ 2014-08-26 15:34 ` Thierry Reding
  2014-08-27  5:21   ` Heiko Schocher
  2014-08-26 15:34 ` [U-Boot] [PATCH v2 14/40] i2c: tegra: Implement i2c_get_bus_num_fdt() Thierry Reding
                   ` (29 subsequent siblings)
  42 siblings, 1 reply; 104+ messages in thread
From: Thierry Reding @ 2014-08-26 15:34 UTC (permalink / raw)
  To: u-boot

From: Thierry Reding <treding@nvidia.com>

This API operates on I2C adapters or I2C clients (a new type of object
that refers to a particular slave connected to an adapter). This is
useful to avoid having to call i2c_set_bus_num() whenever a device is
being accessed.

Drivers for I2C devices are supposed to embed a struct i2c_client within
a driver-specific data structure and call i2c_client_init() on it,
passing in a pointer to the parent I2C adapter and the slave address of
the device.

Signed-off-by: Thierry Reding <treding@nvidia.com>
---
 drivers/i2c/i2c_core.c | 53 ++++++++++++++++++++++++++++
 include/i2c.h          | 96 ++++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 149 insertions(+)

diff --git a/drivers/i2c/i2c_core.c b/drivers/i2c/i2c_core.c
index f6179a16244b..88c7af546b0b 100644
--- a/drivers/i2c/i2c_core.c
+++ b/drivers/i2c/i2c_core.c
@@ -410,3 +410,56 @@ void __i2c_init(int speed, int slaveaddr)
 }
 void i2c_init(int speed, int slaveaddr)
 	__attribute__((weak, alias("__i2c_init")));
+
+struct i2c_adapter *i2c_adapter_get(unsigned int index)
+{
+	struct i2c_adapter *adapter = ll_entry_start(struct i2c_adapter, i2c);
+	unsigned int num = ll_entry_count(struct i2c_adapter, i2c);
+	unsigned int i;
+
+	if (index >= num)
+		return NULL;
+
+	for (i = 0; i < index; i++)
+		adapter++;
+
+	i2c_adapter_init(adapter, adapter->speed, adapter->slaveaddr);
+	return adapter;
+}
+
+int i2c_adapter_read(struct i2c_adapter *adapter, uint8_t chip,
+		     unsigned int address, size_t alen, void *buffer,
+		     size_t size)
+{
+	return adapter->read(adapter, chip, address, alen, buffer, size);
+}
+
+int i2c_adapter_write(struct i2c_adapter *adapter, uint8_t chip,
+		      unsigned int address, size_t alen, void *buffer,
+		      size_t size)
+{
+	return adapter->write(adapter, chip, address, alen, buffer, size);
+}
+
+int i2c_client_init(struct i2c_client *client, struct i2c_adapter *adapter,
+		    uint8_t address)
+{
+	client->adapter = adapter;
+	client->address = address;
+
+	return 0;
+}
+
+int i2c_client_read(struct i2c_client *client, unsigned int address,
+		    size_t alen, void *buffer, size_t size)
+{
+	return i2c_adapter_read(client->adapter, client->address, address,
+				alen, buffer, size);
+}
+
+int i2c_client_write(struct i2c_client *client, unsigned int address,
+		     size_t alen, void *buffer, size_t size)
+{
+	return i2c_adapter_write(client->adapter, client->address, address,
+				 alen, buffer, size);
+}
diff --git a/include/i2c.h b/include/i2c.h
index 1b4078ed62fe..8f73ba93c614 100644
--- a/include/i2c.h
+++ b/include/i2c.h
@@ -55,6 +55,20 @@
 #define CONFIG_SYS_SPD_BUS_NUM		0
 #endif
 
+/**
+ * struct i2c_adapter - I2C adapter
+ * @init: initialize I2C adapter
+ * @probe: probe for a device on the I2C bus
+ * @read: read data from a device on the I2C bus
+ * @write: write data to a device on the I2C bus
+ * @set_bus_speed: configure the I2C bus speed
+ * @speed: current I2C bus speed
+ * @waitdelay:
+ * @slaveaddr: own address (when used as a slave)
+ * @init_done: flag to indicate whether or not the adapter has been initialized
+ * @hwadapnr: the hardware number of this adapter
+ * @name: name of this adapter
+ */
 struct i2c_adapter {
 	void		(*init)(struct i2c_adapter *adap, int speed,
 				int slaveaddr);
@@ -75,6 +89,16 @@ struct i2c_adapter {
 	char		*name;
 };
 
+/**
+ * struct i2c_client - I2C slave
+ * @adapter: I2C adapter providing the slave's parent bus
+ * address: address of the I2C slave on the parent bus
+ */
+struct i2c_client {
+	struct i2c_adapter *adapter;
+	unsigned int address;
+};
+
 #define U_BOOT_I2C_MKENT_COMPLETE(_init, _probe, _read, _write, \
 		_set_speed, _speed, _slaveaddr, _hwadapnr, _name) \
 	{ \
@@ -271,6 +295,78 @@ unsigned int i2c_get_bus_speed(void);
  * Adjusts I2C pointers after U-Boot is relocated to DRAM
  */
 void i2c_reloc_fixup(void);
+
+/*
+ * i2c_adapter_get() - get the I2C adapter associated with a given index
+ * @index: index of the I2C adapter
+ */
+struct i2c_adapter *i2c_adapter_get(unsigned int index);
+
+/*
+ * i2c_adapter_read() - read data from an I2C slave at a given address
+ * @adapter: I2C adapter
+ * @chip: address of the I2C slave to read from
+ * @address: address within the I2C slave to read from
+ * @alen: length of address
+ * @buffer: buffer to receive data from I2C slave
+ * @size: number of bytes to read
+ */
+int i2c_adapter_read(struct i2c_adapter *adapter, uint8_t chip,
+		     unsigned int address, size_t alen, void *buffer,
+		     size_t size);
+
+/*
+ * i2c_adapter_write() - write data to an I2C slave at a given address
+ * @adapter: I2C adapter
+ * @chip: address of the I2C slave to write to
+ * @address: address within the I2C slave to write to
+ * @alen: length of address
+ * @buffer: buffer containing the data to write
+ * @size: number of bytes to write
+ *
+ * Ideally the function would take a const void * buffer, but the underlying
+ * infrastructure doesn't properly propagate const and adding it here would
+ * cause a lot of build warnings.
+ */
+int i2c_adapter_write(struct i2c_adapter *adapter, uint8_t chip,
+		      unsigned int address, size_t alen, void *buffer,
+		      size_t size);
+
+/*
+ * i2c_client_init() - initialize an I2C slave
+ * @client: I2C slave
+ * @adapter: parent I2C adapter
+ * @address: address of I2C slave
+ */
+int i2c_client_init(struct i2c_client *client, struct i2c_adapter *adapter,
+		    uint8_t address);
+
+/*
+ * i2c_client_read() - read data from an I2C slave
+ * @client: I2C slave
+ * @address: address within the I2C slave to read from
+ * @alen: length of address
+ * @buffer: buffer to receive data from I2C slave
+ * @size: number of bytes to read
+ */
+int i2c_client_read(struct i2c_client *client, unsigned int address,
+		    size_t alen, void *buffer, size_t size);
+
+/*
+ * i2c_client_write() - write data to an I2C slave
+ * @client: I2C slave
+ * @address: address within the I2C slave to write to
+ * @alen: length of address
+ * @buffer: buffer containing the data to write
+ * @size: number of bytes to write
+ *
+ * Ideally the function would take a const void * buffer, but the underlying
+ * infrastructure doesn't properly propagate const and adding it here would
+ * cause a lot of build warnings.
+ */
+int i2c_client_write(struct i2c_client *client, unsigned int address,
+		     size_t alen, void *buffer, size_t size);
+
 #if defined(CONFIG_SYS_I2C_SOFT)
 void i2c_soft_init(void);
 void i2c_soft_active(void);
-- 
2.0.4

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

* [U-Boot] [PATCH v2 14/40] i2c: tegra: Implement i2c_get_bus_num_fdt()
  2014-08-26 15:33 [U-Boot] [PATCH v2 00/40] ARM: tegra: Add PCIe support Thierry Reding
                   ` (12 preceding siblings ...)
  2014-08-26 15:34 ` [U-Boot] [PATCH v2 13/40] i2c: Add high-level API Thierry Reding
@ 2014-08-26 15:34 ` Thierry Reding
  2014-09-02 19:24   ` Simon Glass
  2014-08-26 15:34 ` [U-Boot] [PATCH v2 15/40] power: Add AMS AS3722 PMIC support Thierry Reding
                   ` (28 subsequent siblings)
  42 siblings, 1 reply; 104+ messages in thread
From: Thierry Reding @ 2014-08-26 15:34 UTC (permalink / raw)
  To: u-boot

From: Thierry Reding <treding@nvidia.com>

This is useful to retrieve the U-Boot bus number of an I2C controller
given a device tree node.

Signed-off-by: Thierry Reding <treding@nvidia.com>
---
 drivers/i2c/tegra_i2c.c | 13 +++++++++++++
 1 file changed, 13 insertions(+)

diff --git a/drivers/i2c/tegra_i2c.c b/drivers/i2c/tegra_i2c.c
index 257b72f0f7cd..94453765369d 100644
--- a/drivers/i2c/tegra_i2c.c
+++ b/drivers/i2c/tegra_i2c.c
@@ -21,6 +21,7 @@ DECLARE_GLOBAL_DATA_PTR;
 
 /* Information about i2c controller */
 struct i2c_bus {
+	int			node;
 	int			id;
 	enum periph_id		periph_id;
 	int			speed;
@@ -400,6 +401,7 @@ static int process_nodes(const void *blob, int node_list[], int count,
 			continue;
 
 		i2c_bus = &i2c_controllers[i];
+		i2c_bus->node = node;
 		i2c_bus->id = i;
 
 		if (i2c_get_config(blob, node, i2c_bus)) {
@@ -624,6 +626,17 @@ int tegra_i2c_get_dvc_bus_num(void)
 	return -1;
 }
 
+int i2c_get_bus_num_fdt(int node)
+{
+	unsigned int i;
+
+	for (i = 0; i < TEGRA_I2C_NUM_CONTROLLERS; i++)
+		if (node == i2c_controllers[i].node)
+			return i;
+
+	return -1;
+}
+
 /*
  * Register soft i2c adapters
  */
-- 
2.0.4

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

* [U-Boot] [PATCH v2 15/40] power: Add AMS AS3722 PMIC support
  2014-08-26 15:33 [U-Boot] [PATCH v2 00/40] ARM: tegra: Add PCIe support Thierry Reding
                   ` (13 preceding siblings ...)
  2014-08-26 15:34 ` [U-Boot] [PATCH v2 14/40] i2c: tegra: Implement i2c_get_bus_num_fdt() Thierry Reding
@ 2014-08-26 15:34 ` Thierry Reding
  2014-08-27  5:26   ` Heiko Schocher
  2014-08-26 15:34 ` [U-Boot] [PATCH v2 16/40] ARM: tegra: Implement tegra_plle_enable() Thierry Reding
                   ` (27 subsequent siblings)
  42 siblings, 1 reply; 104+ messages in thread
From: Thierry Reding @ 2014-08-26 15:34 UTC (permalink / raw)
  To: u-boot

From: Thierry Reding <treding@nvidia.com>

The AS3722 provides a number of DC/DC converters and LDOs as well as 8
GPIOs.

Signed-off-by: Thierry Reding <treding@nvidia.com>
---
 drivers/power/Makefile |   1 +
 drivers/power/as3722.c | 300 +++++++++++++++++++++++++++++++++++++++++++++++++
 include/fdtdec.h       |   1 +
 include/power/as3722.h |  27 +++++
 lib/fdtdec.c           |   1 +
 5 files changed, 330 insertions(+)
 create mode 100644 drivers/power/as3722.c
 create mode 100644 include/power/as3722.h

diff --git a/drivers/power/Makefile b/drivers/power/Makefile
index dc64e4d32bff..b3097316e27e 100644
--- a/drivers/power/Makefile
+++ b/drivers/power/Makefile
@@ -5,6 +5,7 @@
 # SPDX-License-Identifier:	GPL-2.0+
 #
 
+obj-$(CONFIG_AS3722_POWER)	+= as3722.o
 obj-$(CONFIG_AXP152_POWER)	+= axp152.o
 obj-$(CONFIG_AXP209_POWER)	+= axp209.o
 obj-$(CONFIG_EXYNOS_TMU)	+= exynos-tmu.o
diff --git a/drivers/power/as3722.c b/drivers/power/as3722.c
new file mode 100644
index 000000000000..59d1bf1b50b0
--- /dev/null
+++ b/drivers/power/as3722.c
@@ -0,0 +1,300 @@
+/*
+ * Copyright (C) 2014 NVIDIA Corporation
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+#define pr_fmt(fmt) "as3722: " fmt
+
+#include <common.h>
+#include <errno.h>
+#include <fdtdec.h>
+#include <i2c.h>
+
+#include <power/as3722.h>
+
+#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_LDO_VOLTAGE(n) (0x10 + (n))
+#define AS3722_GPIO_SIGNAL_OUT 0x20
+#define AS3722_SD_CONTROL 0x4d
+#define AS3722_LDO_CONTROL 0x4e
+#define AS3722_ASIC_ID1 0x90
+#define  AS3722_DEVICE_ID 0x0c
+#define AS3722_ASIC_ID2 0x91
+
+struct as3722 {
+	struct i2c_client client;
+	u8 address;
+};
+
+static struct as3722 as3722_pmic;
+
+static int as3722_read(struct as3722 *pmic, u8 reg, u8 *value)
+{
+	int err;
+
+	err = i2c_client_read(&pmic->client, reg, 1, value, 1);
+	if (err < 0)
+		return err;
+
+	return 0;
+}
+
+static int as3722_write(struct as3722 *pmic, u8 reg, u8 value)
+{
+	int err;
+
+	err = i2c_client_write(&pmic->client, reg, 1, &value, 1);
+	if (err < 0)
+		return err;
+
+	return 0;
+}
+
+static int as3722_read_id(struct as3722 *pmic, u8 *id, u8 *revision)
+{
+	int err;
+
+	err = as3722_read(pmic, AS3722_ASIC_ID1, id);
+	if (err) {
+		error("failed to read ID1 register: %d", err);
+		return err;
+	}
+
+	err = as3722_read(pmic, AS3722_ASIC_ID2, revision);
+	if (err) {
+		error("failed to read ID2 register: %d", err);
+		return err;
+	}
+
+	return 0;
+}
+
+int as3722_sd_enable(struct as3722 *pmic, unsigned int sd)
+{
+	u8 value;
+	int err;
+
+	if (sd > 6)
+		return -EINVAL;
+
+	err = as3722_read(pmic, AS3722_SD_CONTROL, &value);
+	if (err) {
+		error("failed to read SD control register: %d", err);
+		return err;
+	}
+
+	value |= 1 << sd;
+
+	err = as3722_write(pmic, AS3722_SD_CONTROL, value);
+	if (err < 0) {
+		error("failed to write SD control register: %d", err);
+		return err;
+	}
+
+	return 0;
+}
+
+int as3722_sd_set_voltage(struct as3722 *pmic, unsigned int sd, u8 value)
+{
+	int err;
+
+	if (sd > 6)
+		return -EINVAL;
+
+	err = as3722_write(pmic, AS3722_SD_VOLTAGE(sd), value);
+	if (err < 0) {
+		error("failed to write SD%u voltage register: %d", sd, err);
+		return err;
+	}
+
+	return 0;
+}
+
+int as3722_ldo_enable(struct as3722 *pmic, unsigned int ldo)
+{
+	u8 value;
+	int err;
+
+	if (ldo > 11)
+		return -EINVAL;
+
+	err = as3722_read(pmic, AS3722_LDO_CONTROL, &value);
+	if (err) {
+		error("failed to read LDO control register: %d", err);
+		return err;
+	}
+
+	value |= 1 << ldo;
+
+	err = as3722_write(pmic, AS3722_LDO_CONTROL, value);
+	if (err < 0) {
+		error("failed to write LDO control register: %d", err);
+		return err;
+	}
+
+	return 0;
+}
+
+int as3722_ldo_set_voltage(struct as3722 *pmic, unsigned int ldo, u8 value)
+{
+	int err;
+
+	if (ldo > 11)
+		return -EINVAL;
+
+	err = as3722_write(pmic, AS3722_LDO_VOLTAGE(ldo), value);
+	if (err < 0) {
+		error("failed to write LDO%u voltage register: %d", ldo,
+		      err);
+		return err;
+	}
+
+	return 0;
+}
+
+int as3722_gpio_configure(struct as3722 *pmic, unsigned int gpio,
+			  unsigned long flags)
+{
+	u8 value = 0;
+	int err;
+
+	if (flags & AS3722_GPIO_OUTPUT_VDDH)
+		value |= AS3722_GPIO_CONTROL_MODE_OUTPUT_VDDH;
+
+	if (flags & AS3722_GPIO_INVERT)
+		value |= AS3722_GPIO_CONTROL_INVERT;
+
+	err = as3722_write(pmic, AS3722_GPIO_CONTROL(gpio), value);
+	if (err) {
+		error("failed to configure GPIO#%u: %d", gpio, err);
+		return err;
+	}
+
+	return 0;
+}
+
+static int as3722_gpio_set(struct as3722 *pmic, unsigned int gpio,
+			   unsigned int level)
+{
+	const char *l;
+	u8 value;
+	int err;
+
+	if (gpio > 7)
+		return -EINVAL;
+
+	err = as3722_read(pmic, AS3722_GPIO_SIGNAL_OUT, &value);
+	if (err < 0) {
+		error("failed to read GPIO signal out register: %d", err);
+		return err;
+	}
+
+	if (level == 0) {
+		value &= ~(1 << gpio);
+		l = "low";
+	} else {
+		value |= 1 << gpio;
+		l = "high";
+	}
+
+	err = as3722_write(pmic, AS3722_GPIO_SIGNAL_OUT, value);
+	if (err) {
+		error("failed to set GPIO#%u %s: %d", gpio, l, err);
+		return err;
+	}
+
+	return 0;
+}
+
+int as3722_gpio_direction_output(struct as3722 *pmic, unsigned int gpio,
+				 unsigned int 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(pmic, AS3722_GPIO_CONTROL(gpio), value);
+	if (err) {
+		error("failed to configure GPIO#%u as output: %d", gpio, err);
+		return err;
+	}
+
+	err = as3722_gpio_set(pmic, gpio, level);
+	if (err < 0) {
+		error("failed to set GPIO#%u high: %d", gpio, err);
+		return err;
+	}
+
+	return 0;
+}
+
+int as3722_init(struct as3722 **pmicp, const void *fdt)
+{
+	struct as3722 *pmic = &as3722_pmic;
+	int count, nodes[1], i;
+	int err;
+
+	count = fdtdec_find_aliases_for_id(fdt, NULL, COMPAT_AMS_AS3722,
+					   nodes, ARRAY_SIZE(nodes));
+	for (i = 0; i < count; i++) {
+		int parent = fdt_parent_offset(fdt, nodes[i]), bus;
+		struct i2c_adapter *adapter;
+		fdt_addr_t address;
+		u8 id, revision;
+
+		bus = i2c_get_bus_num_fdt(parent);
+		if (bus < 0) {
+			error("invalid bus %d", bus);
+			continue;
+		}
+
+		address = fdtdec_get_addr(fdt, nodes[i], "reg");
+		if (address == FDT_ADDR_T_NONE) {
+			error("slave address not found");
+			continue;
+		}
+
+		adapter = i2c_adapter_get(bus);
+		if (!adapter) {
+			error("I2C adapter for bus %d not found", bus);
+			continue;
+		}
+
+		err = i2c_client_init(&pmic->client, adapter, address);
+		if (err < 0) {
+			error("failed to initialize I2C slave: %d", err);
+			continue;
+		}
+
+		err = as3722_read_id(pmic, &id, &revision);
+		if (err < 0) {
+			error("failed to read ID: %d", err);
+			continue;
+		}
+
+		if (id != AS3722_DEVICE_ID) {
+			error("unknown device");
+			continue;
+		}
+
+		debug("AS3722 revision %#x found on I2C bus %u, address %#x\n",
+		      revision, bus, address);
+
+		*pmicp = pmic;
+		return 0;
+	}
+
+	return -ENODEV;
+}
diff --git a/include/fdtdec.h b/include/fdtdec.h
index 5c669a5c8e03..3c38375397df 100644
--- a/include/fdtdec.h
+++ b/include/fdtdec.h
@@ -115,6 +115,7 @@ enum fdt_compat_id {
 	COMPAT_SANDBOX_LCD_SDL,		/* Sandbox LCD emulation with SDL */
 	COMPAT_TI_TPS65090,		/* Texas Instrument TPS65090 */
 	COMPAT_NXP_PTN3460,		/* NXP PTN3460 DP/LVDS bridge */
+	COMPAT_AMS_AS3722,		/* AMS AS3722 PMIC */
 
 	COMPAT_COUNT,
 };
diff --git a/include/power/as3722.h b/include/power/as3722.h
new file mode 100644
index 000000000000..2c2e45a44bab
--- /dev/null
+++ b/include/power/as3722.h
@@ -0,0 +1,27 @@
+/*
+ * Copyright (C) 2014 NVIDIA Corporation
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+#ifndef __POWER_AS3722_H__
+#define __POWER_AS3722_H__
+
+#include <asm/types.h>
+
+#define AS3722_GPIO_OUTPUT_VDDH (1 << 0)
+#define AS3722_GPIO_INVERT (1 << 1)
+
+struct as3722;
+
+int as3722_init(struct as3722 **pmic, const void *fdt);
+int as3722_sd_enable(struct as3722 *pmic, unsigned int sd);
+int as3722_sd_set_voltage(struct as3722 *pmic, unsigned int sd, u8 value);
+int as3722_ldo_enable(struct as3722 *pmic, unsigned int ldo);
+int as3722_ldo_set_voltage(struct as3722 *pmic, unsigned int ldo, u8 value);
+int as3722_gpio_configure(struct as3722 *pmic, unsigned int gpio,
+			  unsigned long flags);
+int as3722_gpio_direction_output(struct as3722 *pmic, unsigned int gpio,
+				 unsigned int level);
+
+#endif /* __POWER_AS3722_H__ */
diff --git a/lib/fdtdec.c b/lib/fdtdec.c
index fa5da0c0147d..cddd86c3186f 100644
--- a/lib/fdtdec.c
+++ b/lib/fdtdec.c
@@ -70,6 +70,7 @@ static const char * const compat_names[COMPAT_COUNT] = {
 	COMPAT(SANDBOX_LCD_SDL, "sandbox,lcd-sdl"),
 	COMPAT(TI_TPS65090, "ti,tps65090"),
 	COMPAT(COMPAT_NXP_PTN3460, "nxp,ptn3460"),
+	COMPAT(AMS_AS3722, "ams,as3722"),
 };
 
 const char *fdtdec_get_compatible(enum fdt_compat_id id)
-- 
2.0.4

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

* [U-Boot] [PATCH v2 16/40] ARM: tegra: Implement tegra_plle_enable()
  2014-08-26 15:33 [U-Boot] [PATCH v2 00/40] ARM: tegra: Add PCIe support Thierry Reding
                   ` (14 preceding siblings ...)
  2014-08-26 15:34 ` [U-Boot] [PATCH v2 15/40] power: Add AMS AS3722 PMIC support Thierry Reding
@ 2014-08-26 15:34 ` Thierry Reding
  2014-08-26 15:34 ` [U-Boot] [PATCH v2 17/40] ARM: tegra: Provide PCIEXCLK reset ID Thierry Reding
                   ` (26 subsequent siblings)
  42 siblings, 0 replies; 104+ messages in thread
From: Thierry Reding @ 2014-08-26 15:34 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.

Acked-by: Stephen Warren <swarren@nvidia.com>
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] 104+ messages in thread

* [U-Boot] [PATCH v2 17/40] ARM: tegra: Provide PCIEXCLK reset ID
  2014-08-26 15:33 [U-Boot] [PATCH v2 00/40] ARM: tegra: Add PCIe support Thierry Reding
                   ` (15 preceding siblings ...)
  2014-08-26 15:34 ` [U-Boot] [PATCH v2 16/40] ARM: tegra: Implement tegra_plle_enable() Thierry Reding
@ 2014-08-26 15:34 ` Thierry Reding
  2014-08-26 15:34 ` [U-Boot] [PATCH v2 18/40] ARM: tegra: Implement powergate support Thierry Reding
                   ` (25 subsequent siblings)
  42 siblings, 0 replies; 104+ messages in thread
From: Thierry Reding @ 2014-08-26 15:34 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. The enumeration value for this was properly defined on
some SoCs but not on others. Similarly, some contained it in the mapping
of peripheral IDs to clock IDs, other didn't. This patch defines it
consistently for all supported SoC generations.

Acked-by: Stephen Warren <swarren@nvidia.com>
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] 104+ messages in thread

* [U-Boot] [PATCH v2 18/40] ARM: tegra: Implement powergate support
  2014-08-26 15:33 [U-Boot] [PATCH v2 00/40] ARM: tegra: Add PCIe support Thierry Reding
                   ` (16 preceding siblings ...)
  2014-08-26 15:34 ` [U-Boot] [PATCH v2 17/40] ARM: tegra: Provide PCIEXCLK reset ID Thierry Reding
@ 2014-08-26 15:34 ` Thierry Reding
  2014-08-26 15:34 ` [U-Boot] [PATCH v2 19/40] ARM: tegra: Implement XUSB pad controller Thierry Reding
                   ` (24 subsequent siblings)
  42 siblings, 0 replies; 104+ messages in thread
From: Thierry Reding @ 2014-08-26 15:34 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>
---
Changes in v2:
- wait for power-up/off operation to complete before returning
- document PCIE/VDEC mixup in REMOVE_CLAMPING register
- add symbolic name for REMOVE_CLAMPING register
- list all partitions available on existing SoCs

 arch/arm/cpu/tegra-common/Makefile             |   1 +
 arch/arm/cpu/tegra-common/powergate.c          | 102 +++++++++++++++++++++++++
 arch/arm/include/asm/arch-tegra/powergate.h    |  38 +++++++++
 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, 165 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..439cff36b951
--- /dev/null
+++ b/arch/arm/cpu/tegra-common/powergate.c
@@ -0,0 +1,102 @@
+/*
+ * Copyright (c) 2014, NVIDIA CORPORATION.  All rights reserved.
+ *
+ * SPDX-License-Identifier: GPL-2.0
+ */
+
+#include <common.h>
+#include <errno.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 REMOVE_CLAMPING 0x34
+
+#define PWRGATE_STATUS 0x38
+
+static int tegra_powergate_set(enum tegra_powergate id, bool state)
+{
+	u32 value, mask = state ? (1 << id) : 0, old_mask;
+	unsigned long start, timeout = 25;
+
+	value = readl(NV_PA_PMC_BASE + PWRGATE_STATUS);
+	old_mask = value & (1 << id);
+
+	if (mask == old_mask)
+		return 0;
+
+	writel(PWRGATE_TOGGLE_START | id, NV_PA_PMC_BASE + PWRGATE_TOGGLE);
+
+	start = get_timer(0);
+
+	while (get_timer(start) < timeout) {
+		value = readl(NV_PA_PMC_BASE + PWRGATE_STATUS);
+		if ((value & (1 << id)) == mask)
+			return 0;
+	}
+
+	return -ETIMEDOUT;
+}
+
+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;
+
+	/*
+	 * The REMOVE_CLAMPING register has the bits for the PCIE and VDEC
+	 * partitions reversed. This was originally introduced on Tegra20 but
+	 * has since been carried forward for backwards-compatibility.
+	 */
+	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 + REMOVE_CLAMPING);
+
+	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..130b58bef1b4
--- /dev/null
+++ b/arch/arm/include/asm/arch-tegra/powergate.h
@@ -0,0 +1,38 @@
+#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,
+	TEGRA_POWERGATE_CPU0,
+	TEGRA_POWERGATE_C0NC,
+	TEGRA_POWERGATE_C1NC,
+	TEGRA_POWERGATE_SOR,
+	TEGRA_POWERGATE_DIS,
+	TEGRA_POWERGATE_DISB,
+	TEGRA_POWERGATE_XUSBA,
+	TEGRA_POWERGATE_XUSBB,
+	TEGRA_POWERGATE_XUSBC,
+	TEGRA_POWERGATE_VIC,
+	TEGRA_POWERGATE_IRAM,
+};
+
+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] 104+ messages in thread

* [U-Boot] [PATCH v2 19/40] ARM: tegra: Implement XUSB pad controller
  2014-08-26 15:33 [U-Boot] [PATCH v2 00/40] ARM: tegra: Add PCIe support Thierry Reding
                   ` (17 preceding siblings ...)
  2014-08-26 15:34 ` [U-Boot] [PATCH v2 18/40] ARM: tegra: Implement powergate support Thierry Reding
@ 2014-08-26 15:34 ` Thierry Reding
  2014-08-26 15:34 ` [U-Boot] [PATCH v2 20/40] ARM: tegra: Add XUSB pad controller on Tegra124 Thierry Reding
                   ` (23 subsequent siblings)
  42 siblings, 0 replies; 104+ messages in thread
From: Thierry Reding @ 2014-08-26 15:34 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>
---
Changes in v2:
- remove needless header files
- move more helpers to libfdt
- describe PHY type

 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       | 716 +++++++++++++++++++++++
 arch/arm/include/asm/arch-tegra/xusb-padctl.h    |  24 +
 board/nvidia/common/board.c                      |   3 +
 include/dt-bindings/pinctrl/pinctrl-tegra-xusb.h |   7 +
 include/fdtdec.h                                 |   2 +
 lib/fdtdec.c                                     |   1 +
 9 files changed, 794 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 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..65f8d2ea967a
--- /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-tegra/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..43af883f2c12
--- /dev/null
+++ b/arch/arm/cpu/tegra124-common/xusb-padctl.c
@@ -0,0 +1,716 @@
+/*
+ * 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-tegra/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,
+		},
+	},
+};
+
+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 = fdt_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 = fdt_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 = fdt_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..b4b4c8ba4d10
--- /dev/null
+++ b/arch/arm/include/asm/arch-tegra/xusb-padctl.h
@@ -0,0 +1,24 @@
+#ifndef _TEGRA_XUSB_PADCTL_H_
+#define _TEGRA_XUSB_PADCTL_H_
+
+struct tegra_xusb_phy;
+
+/**
+ * tegra_xusb_phy_get() - obtain a reference to a specified padctl PHY
+ * @type: the type of PHY to obtain
+ *
+ * The type of PHY varies between SoC generations. Typically there are XUSB,
+ * PCIe and SATA PHYs, though not all generations support all of them. The
+ * value of type can usually be directly parsed from a device tree.
+ *
+ * Return: a pointer to the PHY or NULL if no such PHY exists
+ */
+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/board/nvidia/common/board.c b/board/nvidia/common/board.c
index d01abcee13c1..04573c980189 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-tegra/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 3c38375397df..364da6c67cd2 100644
--- a/include/fdtdec.h
+++ b/include/fdtdec.h
@@ -86,6 +86,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 cddd86c3186f..f4851592687f 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] 104+ messages in thread

* [U-Boot] [PATCH v2 20/40] ARM: tegra: Add XUSB pad controller on Tegra124
  2014-08-26 15:33 [U-Boot] [PATCH v2 00/40] ARM: tegra: Add PCIe support Thierry Reding
                   ` (18 preceding siblings ...)
  2014-08-26 15:34 ` [U-Boot] [PATCH v2 19/40] ARM: tegra: Implement XUSB pad controller Thierry Reding
@ 2014-08-26 15:34 ` Thierry Reding
  2014-08-26 15:34 ` [U-Boot] [PATCH v2 21/40] ARM: tegra: Enable XUSB pad controller on Jetson TK1 Thierry Reding
                   ` (22 subsequent siblings)
  42 siblings, 0 replies; 104+ messages in thread
From: Thierry Reding @ 2014-08-26 15:34 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.

Acked-by: Stephen Warren <swarren@nvidia.com>
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] 104+ messages in thread

* [U-Boot] [PATCH v2 21/40] ARM: tegra: Enable XUSB pad controller on Jetson TK1
  2014-08-26 15:33 [U-Boot] [PATCH v2 00/40] ARM: tegra: Add PCIe support Thierry Reding
                   ` (19 preceding siblings ...)
  2014-08-26 15:34 ` [U-Boot] [PATCH v2 20/40] ARM: tegra: Add XUSB pad controller on Tegra124 Thierry Reding
@ 2014-08-26 15:34 ` Thierry Reding
  2014-08-26 15:34 ` [U-Boot] [PATCH v2 22/40] pci: tegra: Add Tegra PCIe driver Thierry Reding
                   ` (21 subsequent siblings)
  42 siblings, 0 replies; 104+ messages in thread
From: Thierry Reding @ 2014-08-26 15:34 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.

Acked-by: Stephen Warren <swarren@nvidia.com>
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] 104+ messages in thread

* [U-Boot] [PATCH v2 22/40] pci: tegra: Add Tegra PCIe driver
  2014-08-26 15:33 [U-Boot] [PATCH v2 00/40] ARM: tegra: Add PCIe support Thierry Reding
                   ` (20 preceding siblings ...)
  2014-08-26 15:34 ` [U-Boot] [PATCH v2 21/40] ARM: tegra: Enable XUSB pad controller on Jetson TK1 Thierry Reding
@ 2014-08-26 15:34 ` Thierry Reding
  2014-08-26 15:34 ` [U-Boot] [PATCH v2 23/40] ARM: tegra: Add Tegra20 PCIe device tree node Thierry Reding
                   ` (20 subsequent siblings)
  42 siblings, 0 replies; 104+ messages in thread
From: Thierry Reding @ 2014-08-26 15:34 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.

This is based on the Linux kernel driver, originally submitted upstream
by Mike Rapoport.

Signed-off-by: Mike Rapoport <mike@compulab.co.il>
Signed-off-by: Thierry Reding <treding@nvidia.com>
---
Changes in v2:
- update copyright statement
- add Mike's Signed-off-by

 drivers/pci/Makefile    |    1 +
 drivers/pci/pci_tegra.c | 1143 +++++++++++++++++++++++++++++++++++++++++++++++
 include/fdtdec.h        |    3 +
 lib/fdtdec.c            |    3 +
 4 files changed, 1150 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..a03ad5ff1fb6
--- /dev/null
+++ b/drivers/pci/pci_tegra.c
@@ -0,0 +1,1143 @@
+/*
+ * Copyright (c) 2010, CompuLab, Ltd.
+ * Author: Mike Rapoport <mike@compulab.co.il>
+ *
+ * Based on NVIDIA PCIe driver
+ * Copyright (c) 2008-2009, NVIDIA Corporation.
+ *
+ * Copyright (c) 2013-2014, 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-tegra/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);
+
+	err = tegra_powergate_power_off(TEGRA_POWERGATE_PCIE);
+	if (err < 0) {
+		error("failed to power off PCIe partition: %d", err);
+		return err;
+	}
+
+	tegra_pcie_board_init();
+
+	err = tegra_powergate_sequence_power_up(TEGRA_POWERGATE_PCIE,
+						PERIPH_ID_PCIE);
+	if (err < 0) {
+		error("failed to power up PCIe partition: %d", err);
+		return err;
+	}
+
+	/* 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 364da6c67cd2..925133fa48d0 100644
--- a/include/fdtdec.h
+++ b/include/fdtdec.h
@@ -86,6 +86,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 f4851592687f..9ec826205855 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] 104+ messages in thread

* [U-Boot] [PATCH v2 23/40] ARM: tegra: Add Tegra20 PCIe device tree node
  2014-08-26 15:33 [U-Boot] [PATCH v2 00/40] ARM: tegra: Add PCIe support Thierry Reding
                   ` (21 preceding siblings ...)
  2014-08-26 15:34 ` [U-Boot] [PATCH v2 22/40] pci: tegra: Add Tegra PCIe driver Thierry Reding
@ 2014-08-26 15:34 ` Thierry Reding
  2014-08-26 15:34 ` [U-Boot] [PATCH v2 24/40] ARM: tegra: Enable PCIe on TrimSlice Thierry Reding
                   ` (19 subsequent siblings)
  42 siblings, 0 replies; 104+ messages in thread
From: Thierry Reding @ 2014-08-26 15:34 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.

Acked-by: Stephen Warren <swarren@nvidia.com>
Signed-off-by: Thierry Reding <treding@nvidia.com>
---
Changes in v2:
- add missing interrupt-map-mask and interrupt-map properties
- include unit address in device tree node name

 arch/arm/dts/tegra20.dtsi               |  60 ++++++++++++
 include/dt-bindings/clock/tegra20-car.h | 158 ++++++++++++++++++++++++++++++++
 2 files changed, 218 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..39976864fa48 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,65 @@
 		reg = <0x7000f400 0x200>;
 	};
 
+	pcie-controller at 80003000 {
+		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";
+
+		#interrupt-cells = <1>;
+		interrupt-map-mask = <0 0 0 0>;
+		interrupt-map = <0 0 0 0 &intc GIC_SPI 98 IRQ_TYPE_LEVEL_HIGH>;
+
+		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] 104+ messages in thread

* [U-Boot] [PATCH v2 24/40] ARM: tegra: Enable PCIe on TrimSlice
  2014-08-26 15:33 [U-Boot] [PATCH v2 00/40] ARM: tegra: Add PCIe support Thierry Reding
                   ` (22 preceding siblings ...)
  2014-08-26 15:34 ` [U-Boot] [PATCH v2 23/40] ARM: tegra: Add Tegra20 PCIe device tree node Thierry Reding
@ 2014-08-26 15:34 ` Thierry Reding
  2014-08-26 15:34 ` [U-Boot] [PATCH v2 25/40] ARM: tegra: Add GIC for Tegra30 Thierry Reding
                   ` (18 subsequent siblings)
  42 siblings, 0 replies; 104+ messages in thread
From: Thierry Reding @ 2014-08-26 15:34 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>
---
Changes in v2:
- add all regulators from Linux kernel DTS
- use proper set of PCIe power supplies
- use unit-address in node name

 arch/arm/dts/tegra20-trimslice.dts   | 69 ++++++++++++++++++++++++++++++++++++
 board/compulab/trimslice/trimslice.c |  8 +++++
 include/configs/trimslice.h          | 10 ++++++
 3 files changed, 87 insertions(+)

diff --git a/arch/arm/dts/tegra20-trimslice.dts b/arch/arm/dts/tegra20-trimslice.dts
index ee31476c1eb8..9d6ec12e6d00 100644
--- a/arch/arm/dts/tegra20-trimslice.dts
+++ b/arch/arm/dts/tegra20-trimslice.dts
@@ -42,6 +42,20 @@
 		status = "disabled";
 	};
 
+	pcie-controller at 80003000 {
+		status = "okay";
+
+		avdd-pex-supply = <&pci_vdd_reg>;
+		vdd-pex-supply = <&pci_vdd_reg>;
+		avdd-pex-pll-supply = <&pci_vdd_reg>;
+		avdd-plle-supply = <&pci_vdd_reg>;
+		vddio-pex-clk-supply = <&pci_clk_reg>;
+
+		pci at 1,0 {
+			status = "okay";
+		};
+	};
+
 	usb at c5000000 {
 		nvidia,vbus-gpio = <&gpio 170 0>; /* PV2 */
 	};
@@ -61,4 +75,59 @@
 		wp-gpios = <&gpio 122 0>; /* gpio PP2 */
 		bus-width = <4>;
 	};
+
+	regulators {
+		compatible = "simple-bus";
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		hdmi_vdd_reg: regulator at 0 {
+			compatible = "regulator-fixed";
+			reg = <0>;
+			regulator-name = "avdd_hdmi";
+			regulator-min-microvolt = <3300000>;
+			regulator-max-microvolt = <3300000>;
+			regulator-always-on;
+		};
+
+		hdmi_pll_reg: regulator at 1 {
+			compatible = "regulator-fixed";
+			reg = <1>;
+			regulator-name = "avdd_hdmi_pll";
+			regulator-min-microvolt = <1800000>;
+			regulator-max-microvolt = <1800000>;
+			regulator-always-on;
+		};
+
+		vbus_reg: regulator at 2 {
+			compatible = "regulator-fixed";
+			reg = <2>;
+			regulator-name = "usb1_vbus";
+			regulator-min-microvolt = <5000000>;
+			regulator-max-microvolt = <5000000>;
+			enable-active-high;
+			gpio = <&gpio TEGRA_GPIO(V, 2) 0>;
+			regulator-always-on;
+			regulator-boot-on;
+		};
+
+		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] 104+ messages in thread

* [U-Boot] [PATCH v2 25/40] ARM: tegra: Add GIC for Tegra30
  2014-08-26 15:33 [U-Boot] [PATCH v2 00/40] ARM: tegra: Add PCIe support Thierry Reding
                   ` (23 preceding siblings ...)
  2014-08-26 15:34 ` [U-Boot] [PATCH v2 24/40] ARM: tegra: Enable PCIe on TrimSlice Thierry Reding
@ 2014-08-26 15:34 ` Thierry Reding
  2014-08-26 15:34 ` [U-Boot] [PATCH v2 26/40] ARM: tegra: Add Tegra30 PCIe device tree node Thierry Reding
                   ` (17 subsequent siblings)
  42 siblings, 0 replies; 104+ messages in thread
From: Thierry Reding @ 2014-08-26 15:34 UTC (permalink / raw)
  To: u-boot

From: Thierry Reding <treding@nvidia.com>

Add a device tree node for the GIC found on Tegra30. U-Boot doesn't use
it directly but subsequent patches will add device tree nodes that
reference it by phandle.

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

diff --git a/arch/arm/dts/tegra30.dtsi b/arch/arm/dts/tegra30.dtsi
index 7be3791fc9a6..8b8940df796a 100644
--- a/arch/arm/dts/tegra30.dtsi
+++ b/arch/arm/dts/tegra30.dtsi
@@ -5,6 +5,15 @@
 
 / {
 	compatible = "nvidia,tegra30";
+	interrupt-parent = <&intc>;
+
+	intc: interrupt-controller at 50041000 {
+		compatible = "arm,cortex-a9-gic";
+		reg = <0x50041000 0x1000
+		       0x50040100 0x0100>;
+		interrupt-controller;
+		#interrupt-cells = <3>;
+	};
 
 	tegra_car: clock {
 		compatible = "nvidia,tegra30-car";
-- 
2.0.4

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

* [U-Boot] [PATCH v2 26/40] ARM: tegra: Add Tegra30 PCIe device tree node
  2014-08-26 15:33 [U-Boot] [PATCH v2 00/40] ARM: tegra: Add PCIe support Thierry Reding
                   ` (24 preceding siblings ...)
  2014-08-26 15:34 ` [U-Boot] [PATCH v2 25/40] ARM: tegra: Add GIC for Tegra30 Thierry Reding
@ 2014-08-26 15:34 ` Thierry Reding
  2014-08-26 15:34 ` [U-Boot] [PATCH v2 27/40] ARM: tegra: Enable PCIe on Cardhu Thierry Reding
                   ` (16 subsequent siblings)
  42 siblings, 0 replies; 104+ messages in thread
From: Thierry Reding @ 2014-08-26 15:34 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>
---
Changes in v2:
- include unit address in device tree node name
- add missing interrupt-map-mask and interrupt-map properties

 arch/arm/dts/tegra30.dtsi               |  75 +++++++++
 include/dt-bindings/clock/tegra30-car.h | 265 ++++++++++++++++++++++++++++++++
 2 files changed, 340 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 8b8940df796a..521fdc9600e7 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>
 
@@ -15,6 +16,80 @@
 		#interrupt-cells = <3>;
 	};
 
+	pcie-controller at 00003000 {
+		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";
+
+		#interrupt-cells = <1>;
+		interrupt-map-mask = <0 0 0 0>;
+		interrupt-map = <0 0 0 0 &intc GIC_SPI 98 IRQ_TYPE_LEVEL_HIGH>;
+
+		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] 104+ messages in thread

* [U-Boot] [PATCH v2 27/40] ARM: tegra: Enable PCIe on Cardhu
  2014-08-26 15:33 [U-Boot] [PATCH v2 00/40] ARM: tegra: Add PCIe support Thierry Reding
                   ` (25 preceding siblings ...)
  2014-08-26 15:34 ` [U-Boot] [PATCH v2 26/40] ARM: tegra: Add Tegra30 PCIe device tree node Thierry Reding
@ 2014-08-26 15:34 ` Thierry Reding
  2014-08-26 15:34 ` [U-Boot] [PATCH v2 28/40] ARM: tegra: Enable PCIe on Beaver Thierry Reding
                   ` (15 subsequent siblings)
  42 siblings, 0 replies; 104+ messages in thread
From: Thierry Reding @ 2014-08-26 15:34 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>
---
Changes in v2:
- write to instead of read from the LDO2_REG register to enable LDO2
- use proper set of PCIe power supplies
- use unit address in node name

 arch/arm/dts/tegra30-cardhu.dts | 362 ++++++++++++++++++++++++++++++++++++++++
 board/nvidia/cardhu/cardhu.c    |  56 +++++++
 include/configs/cardhu.h        |  10 ++
 3 files changed, 428 insertions(+)

diff --git a/arch/arm/dts/tegra30-cardhu.dts b/arch/arm/dts/tegra30-cardhu.dts
index ea2cf76ff3a8..54e08f59da12 100644
--- a/arch/arm/dts/tegra30-cardhu.dts
+++ b/arch/arm/dts/tegra30-cardhu.dts
@@ -22,6 +22,31 @@
 		reg = <0x80000000 0x40000000>;
 	};
 
+	pcie-controller at 00003000 {
+		status = "okay";
+
+		/* AVDD_PEXA and VDD_PEXA inputs are grounded on Cardhu. */
+		avdd-pexb-supply = <&ldo1_reg>;
+		vdd-pexb-supply = <&ldo1_reg>;
+		avdd-pex-pll-supply = <&ldo1_reg>;
+		hvdd-pex-supply = <&pex_hvdd_3v3_reg>;
+		vddio-pex-ctl-supply = <&sys_3v3_reg>;
+		avdd-plle-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 +70,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 +195,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/board/nvidia/cardhu/cardhu.c b/board/nvidia/cardhu/cardhu.c
index cc0e5e130fda..7893bc3db81c 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_write(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/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] 104+ messages in thread

* [U-Boot] [PATCH v2 28/40] ARM: tegra: Enable PCIe on Beaver
  2014-08-26 15:33 [U-Boot] [PATCH v2 00/40] ARM: tegra: Add PCIe support Thierry Reding
                   ` (26 preceding siblings ...)
  2014-08-26 15:34 ` [U-Boot] [PATCH v2 27/40] ARM: tegra: Enable PCIe on Cardhu Thierry Reding
@ 2014-08-26 15:34 ` Thierry Reding
  2014-08-26 15:34 ` [U-Boot] [PATCH v2 29/40] ARM: tegra: Add GIC for Tegra124 Thierry Reding
                   ` (14 subsequent siblings)
  42 siblings, 0 replies; 104+ messages in thread
From: Thierry Reding @ 2014-08-26 15:34 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>
---
Changes in v2:
- move after Cardhu PCIe patch and move most code into that patch
- use proper set of PCIe power supplies
- use unit address in node name

 arch/arm/dts/tegra30-beaver.dts | 245 ++++++++++++++++++++++++++++++++++++++++
 include/configs/beaver.h        |  10 ++
 2 files changed, 255 insertions(+)

diff --git a/arch/arm/dts/tegra30-beaver.dts b/arch/arm/dts/tegra30-beaver.dts
index 85e62e9db32e..4a4c07851202 100644
--- a/arch/arm/dts/tegra30-beaver.dts
+++ b/arch/arm/dts/tegra30-beaver.dts
@@ -23,6 +23,33 @@
 		reg = <0x80000000 0x7ff00000>;
 	};
 
+	pcie-controller at 00003000 {
+		status = "okay";
+
+		avdd-pexa-supply = <&ldo1_reg>;
+		vdd-pexa-supply = <&ldo1_reg>;
+		avdd-pexb-supply = <&ldo1_reg>;
+		vdd-pexb-supply = <&ldo1_reg>;
+		avdd-pex-pll-supply = <&ldo1_reg>;
+		avdd-plle-supply = <&ldo1_reg>;
+		vddio-pex-ctl-supply = <&sys_3v3_reg>;
+		hvdd-pex-supply = <&sys_3v3_pexs_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 +73,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 +212,118 @@
 		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;
+		};
+
+		chargepump_5v_reg: regulator at 1 {
+			compatible = "regulator-fixed";
+			reg = <1>;
+			regulator-name = "chargepump_5v";
+			regulator-min-microvolt = <5000000>;
+			regulator-max-microvolt = <5000000>;
+			regulator-boot-on;
+			regulator-always-on;
+			enable-active-high;
+			gpio = <&pmic 0 GPIO_ACTIVE_HIGH>;
+		};
+
+		ddr_reg: regulator at 2 {
+			compatible = "regulator-fixed";
+			reg = <2>;
+			regulator-name = "vdd_ddr";
+			regulator-min-microvolt = <1500000>;
+			regulator-max-microvolt = <1500000>;
+			regulator-always-on;
+			regulator-boot-on;
+			enable-active-high;
+			gpio = <&pmic 7 GPIO_ACTIVE_HIGH>;
+			vin-supply = <&vdd_5v_in_reg>;
+		};
+
+		vdd_5v_sata_reg: regulator at 3 {
+			compatible = "regulator-fixed";
+			reg = <3>;
+			regulator-name = "vdd_5v_sata";
+			regulator-min-microvolt = <5000000>;
+			regulator-max-microvolt = <5000000>;
+			regulator-always-on;
+			regulator-boot-on;
+			enable-active-high;
+			gpio = <&gpio TEGRA_GPIO(D, 6) GPIO_ACTIVE_HIGH>;
+			vin-supply = <&vdd_5v_in_reg>;
+		};
+
+		usb1_vbus_reg: regulator at 4 {
+			compatible = "regulator-fixed";
+			reg = <4>;
+			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_5v_in_reg>;
+		};
+
+		usb3_vbus_reg: regulator at 5 {
+			compatible = "regulator-fixed";
+			reg = <5>;
+			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_5v_in_reg>;
+		};
+
+		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>;
+		};
+
+		vdd_5v0_hdmi: regulator at 8 {
+			compatible = "regulator-fixed";
+			reg = <8>;
+			regulator-name = "+VDD_5V_HDMI";
+			regulator-min-microvolt = <5000000>;
+			regulator-max-microvolt = <5000000>;
+			regulator-always-on;
+			regulator-boot-on;
+			vin-supply = <&sys_3v3_reg>;
+		};
+	};
 };
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] 104+ messages in thread

* [U-Boot] [PATCH v2 29/40] ARM: tegra: Add GIC for Tegra124
  2014-08-26 15:33 [U-Boot] [PATCH v2 00/40] ARM: tegra: Add PCIe support Thierry Reding
                   ` (27 preceding siblings ...)
  2014-08-26 15:34 ` [U-Boot] [PATCH v2 28/40] ARM: tegra: Enable PCIe on Beaver Thierry Reding
@ 2014-08-26 15:34 ` Thierry Reding
  2014-08-26 15:34 ` [U-Boot] [PATCH v2 30/40] ARM: tegra: Add Tegra124 PCIe device tree node Thierry Reding
                   ` (13 subsequent siblings)
  42 siblings, 0 replies; 104+ messages in thread
From: Thierry Reding @ 2014-08-26 15:34 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.

Acked-by: Stephen Warren <swarren@nvidia.com>
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] 104+ messages in thread

* [U-Boot] [PATCH v2 30/40] ARM: tegra: Add Tegra124 PCIe device tree node
  2014-08-26 15:33 [U-Boot] [PATCH v2 00/40] ARM: tegra: Add PCIe support Thierry Reding
                   ` (28 preceding siblings ...)
  2014-08-26 15:34 ` [U-Boot] [PATCH v2 29/40] ARM: tegra: Add GIC for Tegra124 Thierry Reding
@ 2014-08-26 15:34 ` Thierry Reding
  2014-08-26 15:34 ` [U-Boot] [PATCH v2 31/40] ARM: tegra: Enable PCIe on Jetson TK1 Thierry Reding
                   ` (12 subsequent siblings)
  42 siblings, 0 replies; 104+ messages in thread
From: Thierry Reding @ 2014-08-26 15:34 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.

Acked-by: Stephen Warren <swarren@nvidia.com>
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] 104+ messages in thread

* [U-Boot] [PATCH v2 31/40] ARM: tegra: Enable PCIe on Jetson TK1
  2014-08-26 15:33 [U-Boot] [PATCH v2 00/40] ARM: tegra: Add PCIe support Thierry Reding
                   ` (29 preceding siblings ...)
  2014-08-26 15:34 ` [U-Boot] [PATCH v2 30/40] ARM: tegra: Add Tegra124 PCIe device tree node Thierry Reding
@ 2014-08-26 15:34 ` Thierry Reding
  2014-08-26 15:34 ` [U-Boot] [PATCH v2 32/40] ARM: cache_v7: Various minor cleanups Thierry Reding
                   ` (11 subsequent siblings)
  42 siblings, 0 replies; 104+ messages in thread
From: Thierry Reding @ 2014-08-26 15:34 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>
---
Changes in v2:
- move AS3722 PMIC code into separate driver
- use revised list of supplies in DTS

 arch/arm/dts/tegra124-jetson-tk1.dts | 347 +++++++++++++++++++++++++++++++++++
 board/nvidia/jetson-tk1/jetson-tk1.c |  52 ++++++
 include/configs/jetson-tk1.h         |  13 ++
 3 files changed, 412 insertions(+)

diff --git a/arch/arm/dts/tegra124-jetson-tk1.dts b/arch/arm/dts/tegra124-jetson-tk1.dts
index f61736f0ef0f..80106ec95ea3 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>;
+		dvddio-pex-supply = <&vdd_1v05_run>;
+		avdd-pex-pll-supply = <&vdd_1v05_run>;
+		hvdd-pex-supply = <&vdd_3v3_lp0>;
+		hvdd-pex-pll-e-supply = <&vdd_3v3_lp0>;
+		vddio-pex-ctl-supply = <&vdd_3v3_lp0>;
+		avdd-pll-erefe-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..263aa423dd04 100644
--- a/board/nvidia/jetson-tk1/jetson-tk1.c
+++ b/board/nvidia/jetson-tk1/jetson-tk1.c
@@ -6,10 +6,16 @@
  */
 
 #include <common.h>
+#include <netdev.h>
+#include <power/as3722.h>
+
 #include <asm/arch/gpio.h>
 #include <asm/arch/pinmux.h>
+
 #include "pinmux-config-jetson-tk1.h"
 
+DECLARE_GLOBAL_DATA_PTR;
+
 /*
  * Routine: pinmux_init
  * Description: Do individual peripheral pinmux configs
@@ -27,3 +33,49 @@ void pinmux_init(void)
 	pinmux_config_drvgrp_table(jetson_tk1_drvgrps,
 				   ARRAY_SIZE(jetson_tk1_drvgrps));
 }
+
+#ifdef CONFIG_PCI_TEGRA
+int tegra_pcie_board_init(void)
+{
+	struct as3722 *pmic;
+	int err;
+
+	err = as3722_init(&pmic, gd->fdt_blob);
+	if (err) {
+		error("failed to initialize AS3722 PMIC: %d\n", err);
+		return err;
+	}
+
+	err = as3722_sd_enable(pmic, 4);
+	if (err < 0) {
+		error("failed to enable SD4: %d\n", err);
+		return err;
+	}
+
+	err = as3722_sd_set_voltage(pmic, 4, 0x24);
+	if (err < 0) {
+		error("failed to set SD4 voltage: %d\n", err);
+		return err;
+	}
+
+	err = as3722_gpio_configure(pmic, 1, AS3722_GPIO_OUTPUT_VDDH |
+					     AS3722_GPIO_INVERT);
+	if (err < 0) {
+		error("failed to configure GPIO#1 as output: %d\n", err);
+		return err;
+	}
+
+	err = as3722_gpio_direction_output(pmic, 2, 1);
+	if (err < 0) {
+		error("failed to set GPIO#2 high: %d\n", err);
+		return err;
+	}
+
+	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..255f0f0a823e 100644
--- a/include/configs/jetson-tk1.h
+++ b/include/configs/jetson-tk1.h
@@ -10,6 +10,9 @@
 
 #include <linux/sizes.h>
 
+/* enable PMIC */
+#define CONFIG_AS3722_POWER
+
 #include "tegra124-common.h"
 
 /* Enable fdt support for Jetson TK1. Flash the image in u-boot-dtb.bin */
@@ -71,6 +74,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] 104+ messages in thread

* [U-Boot] [PATCH v2 32/40] ARM: cache_v7: Various minor cleanups
  2014-08-26 15:33 [U-Boot] [PATCH v2 00/40] ARM: tegra: Add PCIe support Thierry Reding
                   ` (30 preceding siblings ...)
  2014-08-26 15:34 ` [U-Boot] [PATCH v2 31/40] ARM: tegra: Enable PCIe on Jetson TK1 Thierry Reding
@ 2014-08-26 15:34 ` Thierry Reding
  2014-08-27 18:56   ` Simon Glass
  2014-11-08  8:30   ` Albert ARIBAUD
  2014-08-26 15:34 ` [U-Boot] [PATCH v2 33/40] ARM: cache-cp15: Use more accurate types Thierry Reding
                   ` (10 subsequent siblings)
  42 siblings, 2 replies; 104+ messages in thread
From: Thierry Reding @ 2014-08-26 15:34 UTC (permalink / raw)
  To: u-boot

From: Thierry Reding <treding@nvidia.com>

Remove two gratuituous blank lines, uses u32 (instead of int) as the
type for values that will be written to a register, moves the beginning
of the variable declaration section to a separate line (rather than the
one with the opening brace) and keeps the function signature on a single
line where possible.

Signed-off-by: Thierry Reding <treding@nvidia.com>
---
 arch/arm/cpu/armv7/cache_v7.c | 14 +++++++-------
 1 file changed, 7 insertions(+), 7 deletions(-)

diff --git a/arch/arm/cpu/armv7/cache_v7.c b/arch/arm/cpu/armv7/cache_v7.c
index a2c4032fed8c..0f9d8377ed5a 100644
--- a/arch/arm/cpu/armv7/cache_v7.c
+++ b/arch/arm/cpu/armv7/cache_v7.c
@@ -21,7 +21,8 @@
  * to get size details from Current Cache Size ID Register(CCSIDR)
  */
 static void set_csselr(u32 level, u32 type)
-{	u32 csselr = level << 1 | type;
+{
+	u32 csselr = level << 1 | type;
 
 	/* Write to Cache Size Selection Register(CSSELR) */
 	asm volatile ("mcr p15, 2, %0, c0, c0, 0" : : "r" (csselr));
@@ -49,7 +50,8 @@ static void v7_inval_dcache_level_setway(u32 level, u32 num_sets,
 					 u32 num_ways, u32 way_shift,
 					 u32 log2_line_len)
 {
-	int way, set, setway;
+	int way, set;
+	u32 setway;
 
 	/*
 	 * For optimal assembly code:
@@ -73,7 +75,8 @@ static void v7_clean_inval_dcache_level_setway(u32 level, u32 num_sets,
 					       u32 num_ways, u32 way_shift,
 					       u32 log2_line_len)
 {
-	int way, set, setway;
+	int way, set;
+	u32 setway;
 
 	/*
 	 * For optimal assembly code:
@@ -134,7 +137,6 @@ static void v7_maint_dcache_level_setway(u32 level, u32 operation)
 static void v7_maint_dcache_all(u32 operation)
 {
 	u32 level, cache_type, level_start_bit = 0;
-
 	u32 clidr = get_clidr();
 
 	for (level = 0; level < 7; level++) {
@@ -147,8 +149,7 @@ static void v7_maint_dcache_all(u32 operation)
 	}
 }
 
-static void v7_dcache_clean_inval_range(u32 start,
-					u32 stop, u32 line_len)
+static void v7_dcache_clean_inval_range(u32 start, u32 stop, u32 line_len)
 {
 	u32 mva;
 
@@ -256,7 +257,6 @@ void flush_dcache_all(void)
  */
 void invalidate_dcache_range(unsigned long start, unsigned long stop)
 {
-
 	v7_dcache_maint_range(start, stop, ARMV7_DCACHE_INVAL_RANGE);
 
 	v7_outer_cache_inval_range(start, stop);
-- 
2.0.4

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

* [U-Boot] [PATCH v2 33/40] ARM: cache-cp15: Use more accurate types
  2014-08-26 15:33 [U-Boot] [PATCH v2 00/40] ARM: tegra: Add PCIe support Thierry Reding
                   ` (31 preceding siblings ...)
  2014-08-26 15:34 ` [U-Boot] [PATCH v2 32/40] ARM: cache_v7: Various minor cleanups Thierry Reding
@ 2014-08-26 15:34 ` Thierry Reding
  2014-08-27 18:57   ` Simon Glass
  2014-11-08  8:31   ` Albert ARIBAUD
  2014-08-26 15:34 ` [U-Boot] [PATCH v2 34/40] malloc: Output region when debugging Thierry Reding
                   ` (9 subsequent siblings)
  42 siblings, 2 replies; 104+ messages in thread
From: Thierry Reding @ 2014-08-26 15:34 UTC (permalink / raw)
  To: u-boot

From: Thierry Reding <treding@nvidia.com>

size_t is the canonical type to represent variables that contain a size.
Use it instead of signed integer. Physical addresses can be larger than
32-bit, so use a more appropriate type for them as well. phys_addr_t is
a type that is 32-bit on systems that use 32-bit addresses and 64-bit if
the system is 64-bit or uses a form of physical address extension to use
a larger address space on 32-bit systems. Using these types the same API
can be implemented on a wider range of systems.

Signed-off-by: Thierry Reding <treding@nvidia.com>
---
 arch/arm/include/asm/system.h | 2 +-
 arch/arm/lib/cache-cp15.c     | 6 +++---
 2 files changed, 4 insertions(+), 4 deletions(-)

diff --git a/arch/arm/include/asm/system.h b/arch/arm/include/asm/system.h
index d51ba668f323..fb31a8faf2b1 100644
--- a/arch/arm/include/asm/system.h
+++ b/arch/arm/include/asm/system.h
@@ -200,7 +200,7 @@ enum {
  * \param size		size of memory region to change
  * \param option	dcache option to select
  */
-void mmu_set_region_dcache_behaviour(u32 start, int size,
+void mmu_set_region_dcache_behaviour(phys_addr_t start, size_t size,
 				     enum dcache_option option);
 
 /**
diff --git a/arch/arm/lib/cache-cp15.c b/arch/arm/lib/cache-cp15.c
index 5fdfdbfca541..e6c1c83e5758 100644
--- a/arch/arm/lib/cache-cp15.c
+++ b/arch/arm/lib/cache-cp15.c
@@ -47,15 +47,15 @@ __weak void mmu_page_table_flush(unsigned long start, unsigned long stop)
 	debug("%s: Warning: not implemented\n", __func__);
 }
 
-void mmu_set_region_dcache_behaviour(u32 start, int size,
+void mmu_set_region_dcache_behaviour(phys_addr_t start, size_t size,
 				     enum dcache_option option)
 {
 	u32 *page_table = (u32 *)gd->arch.tlb_addr;
-	u32 upto, end;
+	unsigned long upto, end;
 
 	end = ALIGN(start + size, MMU_SECTION_SIZE) >> MMU_SECTION_SHIFT;
 	start = start >> MMU_SECTION_SHIFT;
-	debug("%s: start=%x, size=%x, option=%d\n", __func__, start, size,
+	debug("%s: start=%pa, size=%zu, option=%d\n", __func__, &start, size,
 	      option);
 	for (upto = start; upto < end; upto++)
 		set_section_dcache(upto, option);
-- 
2.0.4

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

* [U-Boot] [PATCH v2 34/40] malloc: Output region when debugging
  2014-08-26 15:33 [U-Boot] [PATCH v2 00/40] ARM: tegra: Add PCIe support Thierry Reding
                   ` (32 preceding siblings ...)
  2014-08-26 15:34 ` [U-Boot] [PATCH v2 33/40] ARM: cache-cp15: Use more accurate types Thierry Reding
@ 2014-08-26 15:34 ` Thierry Reding
  2014-08-27 18:58   ` Simon Glass
  2014-11-08  8:31   ` Albert ARIBAUD
  2014-08-26 15:34 ` [U-Boot] [PATCH v2 35/40] ARM: Implement non-cached memory support Thierry Reding
                   ` (8 subsequent siblings)
  42 siblings, 2 replies; 104+ messages in thread
From: Thierry Reding @ 2014-08-26 15:34 UTC (permalink / raw)
  To: u-boot

From: Thierry Reding <treding@nvidia.com>

When DEBUG is set, output memory region used for malloc().

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

diff --git a/common/dlmalloc.c b/common/dlmalloc.c
index f9873393c183..3d6391e60acf 100644
--- a/common/dlmalloc.c
+++ b/common/dlmalloc.c
@@ -1533,6 +1533,9 @@ void mem_malloc_init(ulong start, ulong size)
 	mem_malloc_end = start + size;
 	mem_malloc_brk = start;
 
+	debug("using memory %#lx-%#lx for malloc()\n", mem_malloc_start,
+	      mem_malloc_end);
+
 	memset((void *)mem_malloc_start, 0, size);
 
 	malloc_bin_reloc();
-- 
2.0.4

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

* [U-Boot] [PATCH v2 35/40] ARM: Implement non-cached memory support
  2014-08-26 15:33 [U-Boot] [PATCH v2 00/40] ARM: tegra: Add PCIe support Thierry Reding
                   ` (33 preceding siblings ...)
  2014-08-26 15:34 ` [U-Boot] [PATCH v2 34/40] malloc: Output region when debugging Thierry Reding
@ 2014-08-26 15:34 ` Thierry Reding
  2014-08-27 19:07   ` Simon Glass
  2014-10-24 19:11   ` Stephen Warren
  2014-08-26 15:34 ` [U-Boot] [PATCH v2 36/40] ARM: tegra: Enable non-cached memory Thierry Reding
                   ` (7 subsequent siblings)
  42 siblings, 2 replies; 104+ messages in thread
From: Thierry Reding @ 2014-08-26 15:34 UTC (permalink / raw)
  To: u-boot

From: Thierry Reding <treding@nvidia.com>

Implement an API that can be used by drivers to allocate memory from a
pool that is mapped uncached. This is useful if drivers would otherwise
need to do extensive cache maintenance (or explicitly maintaining the
cache isn't safe).

The API is protected using the new CONFIG_SYS_NONCACHED_MEMORY setting.
Boards can set this to the size to be used for the non-cached area. The
area will typically be right below the malloc() area, but architectures
should take care of aligning the beginning and end of the area to honor
any mapping restrictions. Architectures must also ensure that mappings
established for this area do not overlap with the malloc() area (which
should remain cached for improved performance).

While the API is currently only implemented for ARM v7, it should be
generic enough to allow other architectures to implement it as well.

Signed-off-by: Thierry Reding <treding@nvidia.com>
---
Changes in v2:
- avoid overflow when checking for available space

 README                        | 19 +++++++++++++++++++
 arch/arm/include/asm/system.h |  5 +++++
 arch/arm/lib/cache.c          | 42 ++++++++++++++++++++++++++++++++++++++++++
 common/board_r.c              | 11 +++++++++++
 4 files changed, 77 insertions(+)

diff --git a/README b/README
index 1d713596ec6f..526e06edb52c 100644
--- a/README
+++ b/README
@@ -3759,6 +3759,25 @@ Configuration Settings:
 		Pre-relocation malloc() is only supported on ARM at present
 		but is fairly easy to enable for other archs.
 
+- CONFIG_SYS_NONCACHED_MEMORY:
+		Size of non-cached memory area. This area of memory will be
+		typically located right below the malloc() area and mapped
+		uncached in the MMU. This is useful for drivers that would
+		otherwise require a lot of explicit cache maintenance. For
+		some drivers it's also impossible to properly maintain the
+		cache. For example if the regions that need to be flushed
+		are not a multiple of the cache-line size, *and* padding
+		cannot be allocated between the regions to align them (i.e.
+		if the HW requires a contiguous array of regions, and the
+		size of each region is not cache-aligned), then a flush of
+		one region may result in overwriting data that hardware has
+		written to another region in the same cache-line. This can
+		happen for example in network drivers where descriptors for
+		buffers are typically smaller than the CPU cache-line (e.g.
+		16 bytes vs. 32 or 64 bytes).
+
+		Non-cached memory is only supported on 32-bit ARM at present.
+
 - CONFIG_SYS_BOOTM_LEN:
 		Normally compressed uImages are limited to an
 		uncompressed size of 8 MBytes. If this is not enough,
diff --git a/arch/arm/include/asm/system.h b/arch/arm/include/asm/system.h
index fb31a8faf2b1..fb1bc0699a56 100644
--- a/arch/arm/include/asm/system.h
+++ b/arch/arm/include/asm/system.h
@@ -211,6 +211,11 @@ void mmu_set_region_dcache_behaviour(phys_addr_t start, size_t size,
  */
 void mmu_page_table_flush(unsigned long start, unsigned long stop);
 
+#ifdef CONFIG_SYS_NONCACHED_MEMORY
+void noncached_init(void);
+phys_addr_t noncached_alloc(size_t size, size_t align);
+#endif /* CONFIG_SYS_NONCACHED_MEMORY */
+
 #endif /* __ASSEMBLY__ */
 
 #define arch_align_stack(x) (x)
diff --git a/arch/arm/lib/cache.c b/arch/arm/lib/cache.c
index 4e597a4c1d16..b2aa7740d4f8 100644
--- a/arch/arm/lib/cache.c
+++ b/arch/arm/lib/cache.c
@@ -8,6 +8,7 @@
 /* for now: just dummy functions to satisfy the linker */
 
 #include <common.h>
+#include <malloc.h>
 
 __weak void flush_cache(unsigned long start, unsigned long size)
 {
@@ -49,3 +50,44 @@ __weak void enable_caches(void)
 {
 	puts("WARNING: Caches not enabled\n");
 }
+
+#ifdef CONFIG_SYS_NONCACHED_MEMORY
+/*
+ * Reserve one MMU section worth of address space below the malloc() area that
+ * will be mapped uncached.
+ */
+static unsigned long noncached_start;
+static unsigned long noncached_end;
+static unsigned long noncached_next;
+
+void noncached_init(void)
+{
+	phys_addr_t start, end;
+	size_t size;
+
+	end = ALIGN(mem_malloc_start, MMU_SECTION_SIZE) - MMU_SECTION_SIZE;
+	size = ALIGN(CONFIG_SYS_NONCACHED_MEMORY, MMU_SECTION_SIZE);
+	start = end - size;
+
+	debug("mapping memory %pa-%pa non-cached\n", &start, &end);
+
+	noncached_start = start;
+	noncached_end = end;
+	noncached_next = start;
+
+	mmu_set_region_dcache_behaviour(noncached_start, size, DCACHE_OFF);
+}
+
+phys_addr_t noncached_alloc(size_t size, size_t align)
+{
+	phys_addr_t next = ALIGN(noncached_next, align);
+
+	if (next >= noncached_end || (noncached_end - next) < size)
+		return 0;
+
+	debug("allocated %zu bytes of uncached memory @%pa\n", size, &next);
+	noncached_next = next + size;
+
+	return next;
+}
+#endif /* CONFIG_SYS_NONCACHED_MEMORY */
diff --git a/common/board_r.c b/common/board_r.c
index ba9a68dc6691..6b8e62bf032b 100644
--- a/common/board_r.c
+++ b/common/board_r.c
@@ -270,6 +270,14 @@ static int initr_malloc(void)
 	return 0;
 }
 
+#ifdef CONFIG_SYS_NONCACHED_MEMORY
+static int initr_noncached(void)
+{
+	noncached_init();
+	return 0;
+}
+#endif
+
 #ifdef CONFIG_DM
 static int initr_dm(void)
 {
@@ -765,6 +773,9 @@ init_fnc_t init_sequence_r[] = {
 #endif
 	initr_barrier,
 	initr_malloc,
+#ifdef CONFIG_SYS_NONCACHED_MEMORY
+	initr_noncached,
+#endif
 	bootstage_relocate,
 #ifdef CONFIG_DM
 	initr_dm,
-- 
2.0.4

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

* [U-Boot] [PATCH v2 36/40] ARM: tegra: Enable non-cached memory
  2014-08-26 15:33 [U-Boot] [PATCH v2 00/40] ARM: tegra: Add PCIe support Thierry Reding
                   ` (34 preceding siblings ...)
  2014-08-26 15:34 ` [U-Boot] [PATCH v2 35/40] ARM: Implement non-cached memory support Thierry Reding
@ 2014-08-26 15:34 ` Thierry Reding
  2014-08-26 15:34 ` [U-Boot] [PATCH v2 37/40] net: rtl8169: Honor CONFIG_SYS_RX_ETH_BUFFER Thierry Reding
                   ` (6 subsequent siblings)
  42 siblings, 0 replies; 104+ messages in thread
From: Thierry Reding @ 2014-08-26 15:34 UTC (permalink / raw)
  To: u-boot

From: Thierry Reding <treding@nvidia.com>

Some boards, most notably those with a PCIe ethernet NIC, require this
to avoid cache coherency problems. Since the option adds very little
code and overhead enable it across all Tegra generations. Other drivers
may also start supporting this functionality at some point, so enabling
it now will automatically reap the benefits later on.

Acked-by: Stephen Warren <swarren@nvidia.com>
Signed-off-by: Thierry Reding <treding@nvidia.com>
---
 include/configs/tegra-common.h | 1 +
 1 file changed, 1 insertion(+)

diff --git a/include/configs/tegra-common.h b/include/configs/tegra-common.h
index 717cd61bd69a..16f45f5def9b 100644
--- a/include/configs/tegra-common.h
+++ b/include/configs/tegra-common.h
@@ -41,6 +41,7 @@
  * Size of malloc() pool
  */
 #define CONFIG_SYS_MALLOC_LEN		(4 << 20)	/* 4MB  */
+#define CONFIG_SYS_NONCACHED_MEMORY	(1 << 20)	/* 1 MiB */
 
 /*
  * NS16550 Configuration
-- 
2.0.4

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

* [U-Boot] [PATCH v2 37/40] net: rtl8169: Honor CONFIG_SYS_RX_ETH_BUFFER
  2014-08-26 15:33 [U-Boot] [PATCH v2 00/40] ARM: tegra: Add PCIe support Thierry Reding
                   ` (35 preceding siblings ...)
  2014-08-26 15:34 ` [U-Boot] [PATCH v2 36/40] ARM: tegra: Enable non-cached memory Thierry Reding
@ 2014-08-26 15:34 ` Thierry Reding
  2014-08-26 15:34 ` [U-Boot] [PATCH v2 38/40] net: rtl8169: Properly align buffers Thierry Reding
                   ` (5 subsequent siblings)
  42 siblings, 0 replies; 104+ messages in thread
From: Thierry Reding @ 2014-08-26 15:34 UTC (permalink / raw)
  To: u-boot

From: Thierry Reding <treding@nvidia.com>

According to the top-level README file, this configuration setting can
be used to override the number of receive buffers that an ethernet NIC
uses.

Signed-off-by: Thierry Reding <treding@nvidia.com>
---
 drivers/net/rtl8169.c | 6 +++++-
 1 file changed, 5 insertions(+), 1 deletion(-)

diff --git a/drivers/net/rtl8169.c b/drivers/net/rtl8169.c
index d040ab171bf5..c3eb474f0fba 100644
--- a/drivers/net/rtl8169.c
+++ b/drivers/net/rtl8169.c
@@ -79,7 +79,11 @@ static int media[MAX_UNITS] = { -1, -1, -1, -1, -1, -1, -1, -1 };
 #define InterFrameGap	0x03	/* 3 means InterFrameGap = the shortest one */
 
 #define NUM_TX_DESC	1	/* Number of Tx descriptor registers */
-#define NUM_RX_DESC	4	/* Number of Rx descriptor registers */
+#ifdef CONFIG_SYS_RX_ETH_BUFFER
+  #define NUM_RX_DESC	CONFIG_SYS_RX_ETH_BUFFER
+#else
+  #define NUM_RX_DESC	4	/* Number of Rx descriptor registers */
+#endif
 #define RX_BUF_SIZE	1536	/* Rx Buffer size */
 #define RX_BUF_LEN	8192
 
-- 
2.0.4

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

* [U-Boot] [PATCH v2 38/40] net: rtl8169: Properly align buffers
  2014-08-26 15:33 [U-Boot] [PATCH v2 00/40] ARM: tegra: Add PCIe support Thierry Reding
                   ` (36 preceding siblings ...)
  2014-08-26 15:34 ` [U-Boot] [PATCH v2 37/40] net: rtl8169: Honor CONFIG_SYS_RX_ETH_BUFFER Thierry Reding
@ 2014-08-26 15:34 ` Thierry Reding
  2014-11-12 23:37   ` Nobuhiro Iwamatsu
  2014-08-26 15:34 ` [U-Boot] [PATCH v2 39/40] net: rtl8169: Use non-cached memory if available Thierry Reding
                   ` (4 subsequent siblings)
  42 siblings, 1 reply; 104+ messages in thread
From: Thierry Reding @ 2014-08-26 15:34 UTC (permalink / raw)
  To: u-boot

From: Thierry Reding <treding@nvidia.com>

RX and TX descriptor rings should be aligned to 256 byte boundaries. Use
the DEFINE_ALIGN_BUFFER() macro to define the buffers so that they don't
have to be manually aligned later on. Also make sure that the buffers do
align to cache-line boundaries in case the cache-line is higher than the
256 byte alignment requirements of the NIC.

Also add a warning if the cache-line size is larger than the descriptor
size, because the driver may discard changes to descriptors made by the
hardware when requeuing RX buffers.

Signed-off-by: Thierry Reding <treding@nvidia.com>
---
Changes in v2:
- make cache-line vs. descriptor size a compile-time warning

 drivers/net/rtl8169.c | 63 +++++++++++++++++++++++++++------------------------
 1 file changed, 34 insertions(+), 29 deletions(-)

diff --git a/drivers/net/rtl8169.c b/drivers/net/rtl8169.c
index c3eb474f0fba..d81ee8af1cc1 100644
--- a/drivers/net/rtl8169.c
+++ b/drivers/net/rtl8169.c
@@ -277,23 +277,41 @@ struct RxDesc {
 	u32 buf_Haddr;
 };
 
-/* Define the TX Descriptor */
-static u8 tx_ring[NUM_TX_DESC * sizeof(struct TxDesc) + 256];
-/*	__attribute__ ((aligned(256))); */
+#define RTL8169_DESC_SIZE 16
 
-/* Create a static buffer of size RX_BUF_SZ for each
-TX Descriptor.	All descriptors point to a
-part of this buffer */
-static unsigned char txb[NUM_TX_DESC * RX_BUF_SIZE];
+#if ARCH_DMA_MINALIGN > 256
+#  define RTL8169_ALIGN ARCH_DMA_MINALIGN
+#else
+#  define RTL8169_ALIGN 256
+#endif
+
+/*
+ * Warn if the cache-line size is larger than the descriptor size. In such
+ * cases the driver will likely fail because the CPU needs to flush the cache
+ * when requeuing RX buffers, therefore descriptors written by the hardware
+ * may be discarded.
+ */
+#if RTL8169_DESC_SIZE < ARCH_DMA_MINALIGN
+#warning cache-line size is larger than descriptor size
+#endif
+
+/* Define the TX Descriptor */
+DEFINE_ALIGN_BUFFER(struct TxDesc, tx_ring, NUM_TX_DESC, RTL8169_ALIGN);
 
 /* Define the RX Descriptor */
-static u8 rx_ring[NUM_RX_DESC * sizeof(struct TxDesc) + 256];
-  /*  __attribute__ ((aligned(256))); */
+DEFINE_ALIGN_BUFFER(struct RxDesc, rx_ring, NUM_RX_DESC, RTL8169_ALIGN);
 
-/* Create a static buffer of size RX_BUF_SZ for each
-RX Descriptor	All descriptors point to a
-part of this buffer */
-static unsigned char rxb[NUM_RX_DESC * RX_BUF_SIZE];
+/*
+ * Create a static buffer of size RX_BUF_SZ for each TX Descriptor. All
+ * descriptors point to a part of this buffer.
+ */
+DEFINE_ALIGN_BUFFER(u8, txb, NUM_TX_DESC * RX_BUF_SIZE, RTL8169_ALIGN);
+
+/*
+ * Create a static buffer of size RX_BUF_SZ for each RX Descriptor. All
+ * descriptors point to a part of this buffer.
+ */
+DEFINE_ALIGN_BUFFER(u8, rxb, NUM_RX_DESC * RX_BUF_SIZE, RTL8169_ALIGN);
 
 struct rtl8169_private {
 	void *mmio_addr;	/* memory map physical address */
@@ -301,8 +319,6 @@ struct rtl8169_private {
 	unsigned long cur_rx;	/* Index into the Rx descriptor buffer of next Rx pkt. */
 	unsigned long cur_tx;	/* Index into the Tx descriptor buffer of next Rx pkt. */
 	unsigned long dirty_tx;
-	unsigned char *TxDescArrays;	/* Index of Tx Descriptor buffer */
-	unsigned char *RxDescArrays;	/* Index of Rx Descriptor buffer */
 	struct TxDesc *TxDescArray;	/* Index of 256-alignment Tx Descriptor buffer */
 	struct RxDesc *RxDescArray;	/* Index of 256-alignment Rx Descriptor buffer */
 	unsigned char *RxBufferRings;	/* Index of Rx Buffer  */
@@ -710,16 +726,6 @@ static int rtl_reset(struct eth_device *dev, bd_t *bis)
 	printf ("%s\n", __FUNCTION__);
 #endif
 
-	tpc->TxDescArrays = tx_ring;
-	/* Tx Desscriptor needs 256 bytes alignment; */
-	tpc->TxDescArray = (struct TxDesc *) ((unsigned long)(tpc->TxDescArrays +
-							      255) & ~255);
-
-	tpc->RxDescArrays = rx_ring;
-	/* Rx Desscriptor needs 256 bytes alignment; */
-	tpc->RxDescArray = (struct RxDesc *) ((unsigned long)(tpc->RxDescArrays +
-							      255) & ~255);
-
 	rtl8169_init_ring(dev);
 	rtl8169_hw_start(dev);
 	/* Construct a perfect filter frame with the mac address as first match
@@ -761,10 +767,6 @@ static void rtl_halt(struct eth_device *dev)
 
 	RTL_W32(RxMissed, 0);
 
-	tpc->TxDescArrays = NULL;
-	tpc->RxDescArrays = NULL;
-	tpc->TxDescArray = NULL;
-	tpc->RxDescArray = NULL;
 	for (i = 0; i < NUM_RX_DESC; i++) {
 		tpc->RxBufferRing[i] = NULL;
 	}
@@ -909,6 +911,9 @@ static int rtl_init(struct eth_device *dev, bd_t *bis)
 #endif
 	}
 
+	tpc->TxDescArray = tx_ring;
+	tpc->RxDescArray = rx_ring;
+
 	return 1;
 }
 
-- 
2.0.4

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

* [U-Boot] [PATCH v2 39/40] net: rtl8169: Use non-cached memory if available
  2014-08-26 15:33 [U-Boot] [PATCH v2 00/40] ARM: tegra: Add PCIe support Thierry Reding
                   ` (37 preceding siblings ...)
  2014-08-26 15:34 ` [U-Boot] [PATCH v2 38/40] net: rtl8169: Properly align buffers Thierry Reding
@ 2014-08-26 15:34 ` Thierry Reding
  2014-08-26 15:34 ` [U-Boot] [PATCH v2 40/40] net: rtl8169: Add support for RTL-8168/8111g Thierry Reding
                   ` (3 subsequent siblings)
  42 siblings, 0 replies; 104+ messages in thread
From: Thierry Reding @ 2014-08-26 15:34 UTC (permalink / raw)
  To: u-boot

From: Thierry Reding <treding@nvidia.com>

To work around potential issues with explicit cache maintenance of the
RX and TX descriptor rings, allocate them from a pool of uncached memory
if the architecture supports it.

Signed-off-by: Thierry Reding <treding@nvidia.com>
---
Changes in v2:
- if non-cached memory is not available, use memalign() for more
  consistent descriptor allocations
- allow rtl_init() to fail

 drivers/net/rtl8169.c | 71 +++++++++++++++++++++++++++++++++++++++++++--------
 1 file changed, 60 insertions(+), 11 deletions(-)

diff --git a/drivers/net/rtl8169.c b/drivers/net/rtl8169.c
index d81ee8af1cc1..22ad70719937 100644
--- a/drivers/net/rtl8169.c
+++ b/drivers/net/rtl8169.c
@@ -41,6 +41,7 @@
  * Modified to use le32_to_cpu and cpu_to_le32 properly
  */
 #include <common.h>
+#include <errno.h>
 #include <malloc.h>
 #include <net.h>
 #include <netdev.h>
@@ -290,16 +291,15 @@ struct RxDesc {
  * cases the driver will likely fail because the CPU needs to flush the cache
  * when requeuing RX buffers, therefore descriptors written by the hardware
  * may be discarded.
+ *
+ * This can be fixed by defining CONFIG_SYS_NONCACHED_MEMORY which will cause
+ * the driver allocate descriptors from a pool of non-cached memory.
  */
 #if RTL8169_DESC_SIZE < ARCH_DMA_MINALIGN
+#ifndef CONFIG_SYS_NONCACHED_MEMORY
 #warning cache-line size is larger than descriptor size
 #endif
-
-/* Define the TX Descriptor */
-DEFINE_ALIGN_BUFFER(struct TxDesc, tx_ring, NUM_TX_DESC, RTL8169_ALIGN);
-
-/* Define the RX Descriptor */
-DEFINE_ALIGN_BUFFER(struct RxDesc, rx_ring, NUM_RX_DESC, RTL8169_ALIGN);
+#endif
 
 /*
  * Create a static buffer of size RX_BUF_SZ for each TX Descriptor. All
@@ -418,34 +418,71 @@ match:
 }
 
 /*
+ * TX and RX descriptors are 16 bytes. This causes problems with the cache
+ * maintenance on CPUs where the cache-line size exceeds the size of these
+ * descriptors. What will happen is that when the driver receives a packet
+ * it will be immediately requeued for the hardware to reuse. The CPU will
+ * therefore need to flush the cache-line containing the descriptor, which
+ * will cause all other descriptors in the same cache-line to be flushed
+ * along with it. If one of those descriptors had been written to by the
+ * device those changes (and the associated packet) will be lost.
+ *
+ * To work around this, we make use of non-cached memory if available. If
+ * descriptors are mapped uncached there's no need to manually flush them
+ * or invalidate them.
+ *
+ * Note that this only applies to descriptors. The packet data buffers do
+ * not have the same constraints since they are 1536 bytes large, so they
+ * are unlikely to share cache-lines.
+ */
+static void *rtl_alloc_descs(unsigned int num)
+{
+	size_t size = num * RTL8169_DESC_SIZE;
+
+#ifdef CONFIG_SYS_NONCACHED_MEMORY
+	return (void *)noncached_alloc(size, RTL8169_ALIGN);
+#else
+	return memalign(RTL8169_ALIGN, size);
+#endif
+}
+
+/*
  * Cache maintenance functions. These are simple wrappers around the more
  * general purpose flush_cache() and invalidate_dcache_range() functions.
  */
 
 static void rtl_inval_rx_desc(struct RxDesc *desc)
 {
+#ifndef CONFIG_SYS_NONCACHED_MEMORY
 	unsigned long start = (unsigned long)desc & ~(ARCH_DMA_MINALIGN - 1);
 	unsigned long end = ALIGN(start + sizeof(*desc), ARCH_DMA_MINALIGN);
 
 	invalidate_dcache_range(start, end);
+#endif
 }
 
 static void rtl_flush_rx_desc(struct RxDesc *desc)
 {
+#ifndef CONFIG_SYS_NONCACHED_MEMORY
 	flush_cache((unsigned long)desc, sizeof(*desc));
+#endif
 }
 
 static void rtl_inval_tx_desc(struct TxDesc *desc)
 {
+#ifndef CONFIG_SYS_NONCACHED_MEMORY
 	unsigned long start = (unsigned long)desc & ~(ARCH_DMA_MINALIGN - 1);
 	unsigned long end = ALIGN(start + sizeof(*desc), ARCH_DMA_MINALIGN);
 
 	invalidate_dcache_range(start, end);
+#endif
 }
 
 static void rtl_flush_tx_desc(struct TxDesc *desc)
 {
+#ifndef CONFIG_SYS_NONCACHED_MEMORY
 	flush_cache((unsigned long)desc, sizeof(*desc));
+#endif
 }
 
 static void rtl_inval_buffer(void *buf, size_t size)
@@ -911,10 +948,16 @@ static int rtl_init(struct eth_device *dev, bd_t *bis)
 #endif
 	}
 
-	tpc->TxDescArray = tx_ring;
-	tpc->RxDescArray = rx_ring;
 
-	return 1;
+	tpc->RxDescArray = rtl_alloc_descs(NUM_RX_DESC);
+	if (!tpc->RxDescArray)
+		return -ENOMEM;
+
+	tpc->TxDescArray = rtl_alloc_descs(NUM_TX_DESC);
+	if (!tpc->TxDescArray)
+		return -ENOMEM;
+
+	return 0;
 }
 
 int rtl8169_initialize(bd_t *bis)
@@ -928,6 +971,7 @@ int rtl8169_initialize(bd_t *bis)
 	while(1){
 		unsigned int region;
 		u16 device;
+		int err;
 
 		/* Find RTL8169 */
 		if ((devno = pci_find_devices(supported, idx++)) < 0)
@@ -966,9 +1010,14 @@ int rtl8169_initialize(bd_t *bis)
 		dev->send = rtl_send;
 		dev->recv = rtl_recv;
 
-		eth_register (dev);
+		err = rtl_init(dev, bis);
+		if (err < 0) {
+			printf(pr_fmt("failed to initialize card: %d\n"), err);
+			free(dev);
+			continue;
+		}
 
-		rtl_init(dev, bis);
+		eth_register (dev);
 
 		card_number++;
 	}
-- 
2.0.4

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

* [U-Boot] [PATCH v2 40/40] net: rtl8169: Add support for RTL-8168/8111g
  2014-08-26 15:33 [U-Boot] [PATCH v2 00/40] ARM: tegra: Add PCIe support Thierry Reding
                   ` (38 preceding siblings ...)
  2014-08-26 15:34 ` [U-Boot] [PATCH v2 39/40] net: rtl8169: Use non-cached memory if available Thierry Reding
@ 2014-08-26 15:34 ` Thierry Reding
  2014-09-11 16:00 ` [U-Boot] [PATCH v2 00/40] ARM: tegra: Add PCIe support Albert ARIBAUD
                   ` (2 subsequent siblings)
  42 siblings, 0 replies; 104+ messages in thread
From: Thierry Reding @ 2014-08-26 15:34 UTC (permalink / raw)
  To: u-boot

From: Thierry Reding <treding@nvidia.com>

This network interface card in found on the NVIDIA Jetson TK1.

Signed-off-by: Thierry Reding <treding@nvidia.com>
---
 drivers/net/rtl8169.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/net/rtl8169.c b/drivers/net/rtl8169.c
index 22ad70719937..8183df39e77a 100644
--- a/drivers/net/rtl8169.c
+++ b/drivers/net/rtl8169.c
@@ -253,6 +253,7 @@ static struct {
 	{"RTL-8168b/8111sb",	0x38, 0xff7e1880,},
 	{"RTL-8168d/8111d",	0x28, 0xff7e1880,},
 	{"RTL-8168evl/8111evl",	0x2e, 0xff7e1880,},
+	{"RTL-8168/8111g",	0x4c, 0xff7e1880,},
 	{"RTL-8101e",		0x34, 0xff7e1880,},
 	{"RTL-8100e",		0x32, 0xff7e1880,},
 };
-- 
2.0.4

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

* [U-Boot] [PATCH v2 01/40] vsprintf: Add modifier for phys_addr_t
  2014-08-26 15:33 ` [U-Boot] [PATCH v2 01/40] vsprintf: Add modifier for phys_addr_t Thierry Reding
@ 2014-08-26 17:04   ` Stephen Warren
  2014-08-27  7:01     ` Thierry Reding
  2014-08-26 23:14   ` [U-Boot] [PATCH v2 " Simon Glass
  1 sibling, 1 reply; 104+ messages in thread
From: Stephen Warren @ 2014-08-26 17:04 UTC (permalink / raw)
  To: u-boot

On 08/26/2014 09:33 AM, Thierry Reding wrote:
> From: Thierry Reding <treding@nvidia.com>
>
> Provide a new modifier to vsprintf() to print phys_addr_t variables to
> avoid having to cast or #ifdef when printing them out. The %pa modifier
> is used for this purpose, so phys_addr_t variables need to be passed by
> reference, like so:
>
> 	phys_addr_t start = 0;
>
> 	printf("start: %pa\n", &start);
>
> Depending on the size of phys_addr_t this will print out the address
> with 8 or 16 hexadecimal digits following a 0x prefix.

The series,

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

Note that I did see the following printed a couple of times when I 
executed "run bootcmd_pxe":

pci_hose_bus_to_phys: invalid physical address

... but everything worked perfectly, so I guess we can track that down 
later.

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

* [U-Boot] [PATCH v2 01/40] vsprintf: Add modifier for phys_addr_t
  2014-08-26 15:33 ` [U-Boot] [PATCH v2 01/40] vsprintf: Add modifier for phys_addr_t Thierry Reding
  2014-08-26 17:04   ` Stephen Warren
@ 2014-08-26 23:14   ` Simon Glass
  2014-08-27  7:37     ` Thierry Reding
  1 sibling, 1 reply; 104+ messages in thread
From: Simon Glass @ 2014-08-26 23:14 UTC (permalink / raw)
  To: u-boot

Hi Thierry,

On 26 August 2014 09:33, Thierry Reding <thierry.reding@gmail.com> wrote:
>
> From: Thierry Reding <treding@nvidia.com>
>
> Provide a new modifier to vsprintf() to print phys_addr_t variables to
> avoid having to cast or #ifdef when printing them out. The %pa modifier
> is used for this purpose, so phys_addr_t variables need to be passed by
> reference, like so:
>
>         phys_addr_t start = 0;
>
>         printf("start: %pa\n", &start);
>
> Depending on the size of phys_addr_t this will print out the address
> with 8 or 16 hexadecimal digits following a 0x prefix.

Would it be better to use %#pa to get the 0x prefix so we have the
option? Hex is the default in U-Boot.

>
> Signed-off-by: Thierry Reding <treding@nvidia.com>
> ---
>  lib/vsprintf.c | 16 ++++++++++++++--
>  1 file changed, 14 insertions(+), 2 deletions(-)
>
> diff --git a/lib/vsprintf.c b/lib/vsprintf.c
> index 7ec758e40fc5..044d5551bdd0 100644
> --- a/lib/vsprintf.c
> +++ b/lib/vsprintf.c
> @@ -518,6 +518,8 @@ static char *ip4_addr_string(char *buf, char *end, u8 *addr, int field_width,
>  static char *pointer(const char *fmt, char *buf, char *end, void *ptr,
>                 int field_width, int precision, int flags)
>  {
> +       u64 num = (uintptr_t)ptr;
> +

Will this impact code size much? I suppose it is vsprintf() so it
doesn't matter too much?

>         /*
>          * Being a boot loader, we explicitly allow pointers to
>          * (physical) address null.
> @@ -530,6 +532,17 @@ static char *pointer(const char *fmt, char *buf, char *end, void *ptr,
>
>  #ifdef CONFIG_CMD_NET
>         switch (*fmt) {
> +       case 'a':
> +               flags |= SPECIAL | ZEROPAD;
> +
> +               switch (fmt[1]) {
> +               case 'p':
> +               default:
> +                       field_width = sizeof(phys_addr_t) * 2 + 2;
> +                       num = *(phys_addr_t *)ptr;
> +                       break;
> +               }
> +               break;
>         case 'm':
>                 flags |= SPECIAL;
>                 /* Fallthrough */
> @@ -555,8 +568,7 @@ static char *pointer(const char *fmt, char *buf, char *end, void *ptr,
>                 field_width = 2*sizeof(void *);
>                 flags |= ZEROPAD;
>         }
> -       return number(buf, end, (unsigned long)ptr, 16, field_width,
> -                     precision, flags);
> +       return number(buf, end, num, 16, field_width, precision, flags);
>  }
>
>  static int vsnprintf_internal(char *buf, size_t size, const char *fmt,
> --
> 2.0.4
>

Regards,
Simon

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

* [U-Boot] [PATCH v2 11/40] i2c: Initialize the correct bus
  2014-08-26 15:33 ` [U-Boot] [PATCH v2 11/40] i2c: Initialize the correct bus Thierry Reding
@ 2014-08-27  4:52   ` Heiko Schocher
  2014-08-27  5:12     ` Thierry Reding
  0 siblings, 1 reply; 104+ messages in thread
From: Heiko Schocher @ 2014-08-27  4:52 UTC (permalink / raw)
  To: u-boot

Hello Thierry,

Am 26.08.2014 17:33, schrieb Thierry Reding:
> From: Thierry Reding<treding@nvidia.com>
>
> i2c_bus_init() takes a bus number but relies on the currently selected
> bus to determine which adapter to initialize. Make the function use the
> bus passed in as parameter rather than the currently selected bus. While
> at it, keep a pointer to the specified bus to avoid having to look it up
> repeatedly.
>
> Signed-off-by: Thierry Reding<treding@nvidia.com>
> ---
>   drivers/i2c/i2c_core.c | 15 +++++++++------
>   1 file changed, 9 insertions(+), 6 deletions(-)

Why you could not use the current CONFIG_SYS_I2C API and init a bus with
i2c_set_bus_num()?

i2c_init_bus() is deprecated and should be removed if all i2c drivers are
ported to the CONFIG_SYS_I2C framework ...

bye,
Heiko
> diff --git a/drivers/i2c/i2c_core.c b/drivers/i2c/i2c_core.c
> index 18d6736601c1..cca455bc9c63 100644
> --- a/drivers/i2c/i2c_core.c
> +++ b/drivers/i2c/i2c_core.c
> @@ -214,17 +214,20 @@ static int i2c_mux_disconnet_all(void)
>    * Initializes one bus. Will initialize the parent adapter. No current bus
>    * changes, no mux (if any) setup.
>    */
> -static void i2c_init_bus(unsigned int bus_no, int speed, int slaveaddr)
> +static void i2c_init_bus(unsigned int bus, int speed, int slaveaddr)
>   {
> -	if (bus_no>= CONFIG_SYS_NUM_I2C_BUSES)
> +	struct i2c_adapter *adapter;
> +
> +	if (bus>= CONFIG_SYS_NUM_I2C_BUSES)
>   		return;
>
> -	I2C_ADAP->init(I2C_ADAP, speed, slaveaddr);
> +	adapter = i2c_get_adapter(I2C_ADAPTER(bus));
> +	adapter->init(adapter, speed, slaveaddr);
>
>   	if (gd->flags&  GD_FLG_RELOC) {
> -		I2C_ADAP->init_done = 1;
> -		I2C_ADAP->speed = speed;
> -		I2C_ADAP->slaveaddr = slaveaddr;
> +		adapter->init_done = 1;
> +		adapter->speed = speed;
> +		adapter->slaveaddr = slaveaddr;
>   	}
>   }
>

-- 
DENX Software Engineering GmbH,     MD: Wolfgang Denk & Detlev Zundel
HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany

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

* [U-Boot] [PATCH v2 11/40] i2c: Initialize the correct bus
  2014-08-27  4:52   ` Heiko Schocher
@ 2014-08-27  5:12     ` Thierry Reding
  2014-08-27  5:26       ` Heiko Schocher
  0 siblings, 1 reply; 104+ messages in thread
From: Thierry Reding @ 2014-08-27  5:12 UTC (permalink / raw)
  To: u-boot

On Wed, Aug 27, 2014 at 06:52:16AM +0200, Heiko Schocher wrote:
> Hello Thierry,
> 
> Am 26.08.2014 17:33, schrieb Thierry Reding:
> >From: Thierry Reding<treding@nvidia.com>
> >
> >i2c_bus_init() takes a bus number but relies on the currently selected
> >bus to determine which adapter to initialize. Make the function use the
> >bus passed in as parameter rather than the currently selected bus. While
> >at it, keep a pointer to the specified bus to avoid having to look it up
> >repeatedly.
> >
> >Signed-off-by: Thierry Reding<treding@nvidia.com>
> >---
> >  drivers/i2c/i2c_core.c | 15 +++++++++------
> >  1 file changed, 9 insertions(+), 6 deletions(-)
> 
> Why you could not use the current CONFIG_SYS_I2C API and init a bus with
> i2c_set_bus_num()?

That's orthogonal to this patch. i2c_set_bus_num() will end up calling
the i2c_init_bus() function, too. What this patch does is fix an issue
where i2c_init_bus is completely ignoring the bus_no parameter (except
for sanity checking) but instead relies on the gd->cur_i2c_bus (via
I2C_ADAP) to initialize a bus. That's completely unexpected and making
this consistent allows the function to be reused in a more generic way
as done in subsequent patches.

Thierry

> >diff --git a/drivers/i2c/i2c_core.c b/drivers/i2c/i2c_core.c
> >index 18d6736601c1..cca455bc9c63 100644
> >--- a/drivers/i2c/i2c_core.c
> >+++ b/drivers/i2c/i2c_core.c
> >@@ -214,17 +214,20 @@ static int i2c_mux_disconnet_all(void)
> >   * Initializes one bus. Will initialize the parent adapter. No current bus
> >   * changes, no mux (if any) setup.
> >   */
> >-static void i2c_init_bus(unsigned int bus_no, int speed, int slaveaddr)
> >+static void i2c_init_bus(unsigned int bus, int speed, int slaveaddr)
> >  {
> >-	if (bus_no>= CONFIG_SYS_NUM_I2C_BUSES)
> >+	struct i2c_adapter *adapter;
> >+
> >+	if (bus>= CONFIG_SYS_NUM_I2C_BUSES)
> >  		return;
> >
> >-	I2C_ADAP->init(I2C_ADAP, speed, slaveaddr);
> >+	adapter = i2c_get_adapter(I2C_ADAPTER(bus));
> >+	adapter->init(adapter, speed, slaveaddr);
> >
> >  	if (gd->flags&  GD_FLG_RELOC) {
> >-		I2C_ADAP->init_done = 1;
> >-		I2C_ADAP->speed = speed;
> >-		I2C_ADAP->slaveaddr = slaveaddr;
> >+		adapter->init_done = 1;
> >+		adapter->speed = speed;
> >+		adapter->slaveaddr = slaveaddr;
> >  	}
> >  }
> >
> 
> -- 
> DENX Software Engineering GmbH,     MD: Wolfgang Denk & Detlev Zundel
> HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
-------------- 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/0c102af2/attachment.pgp>

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

* [U-Boot] [PATCH v2 13/40] i2c: Add high-level API
  2014-08-26 15:34 ` [U-Boot] [PATCH v2 13/40] i2c: Add high-level API Thierry Reding
@ 2014-08-27  5:21   ` Heiko Schocher
  2014-08-27  6:21     ` Thierry Reding
  0 siblings, 1 reply; 104+ messages in thread
From: Heiko Schocher @ 2014-08-27  5:21 UTC (permalink / raw)
  To: u-boot

Hello Thierry,

Am 26.08.2014 17:34, schrieb Thierry Reding:
> From: Thierry Reding<treding@nvidia.com>
>
> This API operates on I2C adapters or I2C clients (a new type of object

which is a bad idea ...

> that refers to a particular slave connected to an adapter). This is
> useful to avoid having to call i2c_set_bus_num() whenever a device is
> being accessed.

But thats the supose of i2c_set_bus_num()! ... if you use an i2c bus,
you must check before every access, if you are on it, if not, you must
switch back to it...

This is collected in i2c_set_bus_num() ... before, every "user" did
this on his own ... if you are on the bus you want to access, the
overhead is not so big, see:

http://git.denx.de/?p=u-boot.git;a=blob;f=drivers/i2c/i2c_core.c;h=18d6736601c161f45cb7d81b5eae53bdeaaf6b0b;hb=7bee1c91a94db19bd26f92cc67be35d3592c6429#l278

  278 int i2c_set_bus_num(unsigned int bus)
  279 {
  280         int max;
  281
  282         if ((bus == I2C_BUS) && (I2C_ADAP->init_done > 0))
  283                 return 0;

And you must be aware of i2c muxes! You directly use the read/write
functions from the i2c adapter, but what is if you have i2c muxes?

Maybe there is on one i2c adapter a i2c mux with 4 ports. On one is
an eeprom, on the other is a PMIC ... your code in patch
"power: Add AMS AS3722 PMIC support" does access with your functions
the PMIC ... what is, if between this accesses someone accesses the eeprom?
If he switches the mux, you never switch back!

Your code did not check this!

Why is i2c_set_bus_num() such a problem?

> Drivers for I2C devices are supposed to embed a struct i2c_client within
> a driver-specific data structure and call i2c_client_init() on it,
> passing in a pointer to the parent I2C adapter and the slave address of
> the device.
>
> Signed-off-by: Thierry Reding<treding@nvidia.com>
> ---
>   drivers/i2c/i2c_core.c | 53 ++++++++++++++++++++++++++++
>   include/i2c.h          | 96 ++++++++++++++++++++++++++++++++++++++++++++++++++
>   2 files changed, 149 insertions(+)
>
> diff --git a/drivers/i2c/i2c_core.c b/drivers/i2c/i2c_core.c
> index f6179a16244b..88c7af546b0b 100644
> --- a/drivers/i2c/i2c_core.c
> +++ b/drivers/i2c/i2c_core.c
> @@ -410,3 +410,56 @@ void __i2c_init(int speed, int slaveaddr)
>   }
>   void i2c_init(int speed, int slaveaddr)
>   	__attribute__((weak, alias("__i2c_init")));
> +
> +struct i2c_adapter *i2c_adapter_get(unsigned int index)
> +{
> +	struct i2c_adapter *adapter = ll_entry_start(struct i2c_adapter, i2c);
> +	unsigned int num = ll_entry_count(struct i2c_adapter, i2c);
> +	unsigned int i;
> +
> +	if (index>= num)
> +		return NULL;
> +
> +	for (i = 0; i<  index; i++)
> +		adapter++;
> +
> +	i2c_adapter_init(adapter, adapter->speed, adapter->slaveaddr);
> +	return adapter;
> +}
> +
> +int i2c_adapter_read(struct i2c_adapter *adapter, uint8_t chip,
> +		     unsigned int address, size_t alen, void *buffer,
> +		     size_t size)
> +{
> +	return adapter->read(adapter, chip, address, alen, buffer, size);
> +}
> +
> +int i2c_adapter_write(struct i2c_adapter *adapter, uint8_t chip,
> +		      unsigned int address, size_t alen, void *buffer,
> +		      size_t size)
> +{
> +	return adapter->write(adapter, chip, address, alen, buffer, size);
> +}
> +
> +int i2c_client_init(struct i2c_client *client, struct i2c_adapter *adapter,
> +		    uint8_t address)
> +{
> +	client->adapter = adapter;
> +	client->address = address;
> +
> +	return 0;
> +}
> +
> +int i2c_client_read(struct i2c_client *client, unsigned int address,
> +		    size_t alen, void *buffer, size_t size)
> +{
> +	return i2c_adapter_read(client->adapter, client->address, address,
> +				alen, buffer, size);
> +}
> +
> +int i2c_client_write(struct i2c_client *client, unsigned int address,
> +		     size_t alen, void *buffer, size_t size)
> +{
> +	return i2c_adapter_write(client->adapter, client->address, address,
> +				 alen, buffer, size);
> +}
> diff --git a/include/i2c.h b/include/i2c.h
> index 1b4078ed62fe..8f73ba93c614 100644
> --- a/include/i2c.h
> +++ b/include/i2c.h
> @@ -55,6 +55,20 @@
>   #define CONFIG_SYS_SPD_BUS_NUM		0
>   #endif
>
> +/**
> + * struct i2c_adapter - I2C adapter
> + * @init: initialize I2C adapter
> + * @probe: probe for a device on the I2C bus
> + * @read: read data from a device on the I2C bus
> + * @write: write data to a device on the I2C bus
> + * @set_bus_speed: configure the I2C bus speed
> + * @speed: current I2C bus speed
> + * @waitdelay:
> + * @slaveaddr: own address (when used as a slave)
> + * @init_done: flag to indicate whether or not the adapter has been initialized
> + * @hwadapnr: the hardware number of this adapter
> + * @name: name of this adapter
> + */
>   struct i2c_adapter {
>   	void		(*init)(struct i2c_adapter *adap, int speed,
>   				int slaveaddr);
> @@ -75,6 +89,16 @@ struct i2c_adapter {
>   	char		*name;
>   };
>
> +/**
> + * struct i2c_client - I2C slave
> + * @adapter: I2C adapter providing the slave's parent bus
> + * address: address of the I2C slave on the parent bus
> + */
> +struct i2c_client {
> +	struct i2c_adapter *adapter;
> +	unsigned int address;
> +};
> +
>   #define U_BOOT_I2C_MKENT_COMPLETE(_init, _probe, _read, _write, \
>   		_set_speed, _speed, _slaveaddr, _hwadapnr, _name) \
>   	{ \
> @@ -271,6 +295,78 @@ unsigned int i2c_get_bus_speed(void);
>    * Adjusts I2C pointers after U-Boot is relocated to DRAM
>    */
>   void i2c_reloc_fixup(void);
> +
> +/*
> + * i2c_adapter_get() - get the I2C adapter associated with a given index
> + * @index: index of the I2C adapter
> + */
> +struct i2c_adapter *i2c_adapter_get(unsigned int index);
> +
> +/*
> + * i2c_adapter_read() - read data from an I2C slave at a given address
> + * @adapter: I2C adapter
> + * @chip: address of the I2C slave to read from
> + * @address: address within the I2C slave to read from
> + * @alen: length of address
> + * @buffer: buffer to receive data from I2C slave
> + * @size: number of bytes to read
> + */
> +int i2c_adapter_read(struct i2c_adapter *adapter, uint8_t chip,
> +		     unsigned int address, size_t alen, void *buffer,
> +		     size_t size);
> +
> +/*
> + * i2c_adapter_write() - write data to an I2C slave at a given address
> + * @adapter: I2C adapter
> + * @chip: address of the I2C slave to write to
> + * @address: address within the I2C slave to write to
> + * @alen: length of address
> + * @buffer: buffer containing the data to write
> + * @size: number of bytes to write
> + *
> + * Ideally the function would take a const void * buffer, but the underlying
> + * infrastructure doesn't properly propagate const and adding it here would
> + * cause a lot of build warnings.
> + */
> +int i2c_adapter_write(struct i2c_adapter *adapter, uint8_t chip,
> +		      unsigned int address, size_t alen, void *buffer,
> +		      size_t size);
> +
> +/*
> + * i2c_client_init() - initialize an I2C slave
> + * @client: I2C slave
> + * @adapter: parent I2C adapter
> + * @address: address of I2C slave
> + */
> +int i2c_client_init(struct i2c_client *client, struct i2c_adapter *adapter,
> +		    uint8_t address);
> +
> +/*
> + * i2c_client_read() - read data from an I2C slave
> + * @client: I2C slave
> + * @address: address within the I2C slave to read from
> + * @alen: length of address
> + * @buffer: buffer to receive data from I2C slave
> + * @size: number of bytes to read
> + */
> +int i2c_client_read(struct i2c_client *client, unsigned int address,
> +		    size_t alen, void *buffer, size_t size);
> +
> +/*
> + * i2c_client_write() - write data to an I2C slave
> + * @client: I2C slave
> + * @address: address within the I2C slave to write to
> + * @alen: length of address
> + * @buffer: buffer containing the data to write
> + * @size: number of bytes to write
> + *
> + * Ideally the function would take a const void * buffer, but the underlying
> + * infrastructure doesn't properly propagate const and adding it here would
> + * cause a lot of build warnings.
> + */
> +int i2c_client_write(struct i2c_client *client, unsigned int address,
> +		     size_t alen, void *buffer, size_t size);
> +
>   #if defined(CONFIG_SYS_I2C_SOFT)
>   void i2c_soft_init(void);
>   void i2c_soft_active(void);

-- 
DENX Software Engineering GmbH,     MD: Wolfgang Denk & Detlev Zundel
HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany

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

* [U-Boot] [PATCH v2 15/40] power: Add AMS AS3722 PMIC support
  2014-08-26 15:34 ` [U-Boot] [PATCH v2 15/40] power: Add AMS AS3722 PMIC support Thierry Reding
@ 2014-08-27  5:26   ` Heiko Schocher
  2014-08-27  6:28     ` Thierry Reding
  0 siblings, 1 reply; 104+ messages in thread
From: Heiko Schocher @ 2014-08-27  5:26 UTC (permalink / raw)
  To: u-boot

Hello Thierry,

Am 26.08.2014 17:34, schrieb Thierry Reding:
> From: Thierry Reding<treding@nvidia.com>
>
> The AS3722 provides a number of DC/DC converters and LDOs as well as 8
> GPIOs.
>
> Signed-off-by: Thierry Reding<treding@nvidia.com>
> ---
>   drivers/power/Makefile |   1 +
>   drivers/power/as3722.c | 300 +++++++++++++++++++++++++++++++++++++++++++++++++
>   include/fdtdec.h       |   1 +
>   include/power/as3722.h |  27 +++++
>   lib/fdtdec.c           |   1 +
>   5 files changed, 330 insertions(+)
>   create mode 100644 drivers/power/as3722.c
>   create mode 100644 include/power/as3722.h
>
> diff --git a/drivers/power/Makefile b/drivers/power/Makefile
> index dc64e4d32bff..b3097316e27e 100644
> --- a/drivers/power/Makefile
> +++ b/drivers/power/Makefile
> @@ -5,6 +5,7 @@
>   # SPDX-License-Identifier:	GPL-2.0+
>   #
>
> +obj-$(CONFIG_AS3722_POWER)	+= as3722.o
>   obj-$(CONFIG_AXP152_POWER)	+= axp152.o
>   obj-$(CONFIG_AXP209_POWER)	+= axp209.o
>   obj-$(CONFIG_EXYNOS_TMU)	+= exynos-tmu.o
> diff --git a/drivers/power/as3722.c b/drivers/power/as3722.c
> new file mode 100644
> index 000000000000..59d1bf1b50b0
> --- /dev/null
> +++ b/drivers/power/as3722.c
> @@ -0,0 +1,300 @@
> +/*
> + * Copyright (C) 2014 NVIDIA Corporation
> + *
> + * SPDX-License-Identifier: GPL-2.0+
> + */
> +
> +#define pr_fmt(fmt) "as3722: " fmt
> +
> +#include<common.h>
> +#include<errno.h>
> +#include<fdtdec.h>
> +#include<i2c.h>
> +
> +#include<power/as3722.h>
> +
> +#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_LDO_VOLTAGE(n) (0x10 + (n))
> +#define AS3722_GPIO_SIGNAL_OUT 0x20
> +#define AS3722_SD_CONTROL 0x4d
> +#define AS3722_LDO_CONTROL 0x4e
> +#define AS3722_ASIC_ID1 0x90
> +#define  AS3722_DEVICE_ID 0x0c
> +#define AS3722_ASIC_ID2 0x91
> +
> +struct as3722 {
> +	struct i2c_client client;
> +	u8 address;
> +};
> +
> +static struct as3722 as3722_pmic;
> +
> +static int as3722_read(struct as3722 *pmic, u8 reg, u8 *value)
> +{
> +	int err;
> +
> +	err = i2c_client_read(&pmic->client, reg, 1, value, 1);
> +	if (err<  0)
> +		return err;
> +
> +	return 0;
> +}
> +
> +static int as3722_write(struct as3722 *pmic, u8 reg, u8 value)
> +{
> +	int err;
> +
> +	err = i2c_client_write(&pmic->client, reg, 1,&value, 1);
> +	if (err<  0)
> +		return err;
> +
> +	return 0;
> +}
> +
> +static int as3722_read_id(struct as3722 *pmic, u8 *id, u8 *revision)
> +{
> +	int err;
> +
> +	err = as3722_read(pmic, AS3722_ASIC_ID1, id);
> +	if (err) {
> +		error("failed to read ID1 register: %d", err);
> +		return err;
> +	}
> +
> +	err = as3722_read(pmic, AS3722_ASIC_ID2, revision);
> +	if (err) {
> +		error("failed to read ID2 register: %d", err);
> +		return err;
> +	}
> +
> +	return 0;
> +}
> +
> +int as3722_sd_enable(struct as3722 *pmic, unsigned int sd)
> +{
> +	u8 value;
> +	int err;
> +
> +	if (sd>  6)
> +		return -EINVAL;
> +
> +	err = as3722_read(pmic, AS3722_SD_CONTROL,&value);
> +	if (err) {
> +		error("failed to read SD control register: %d", err);
> +		return err;
> +	}
> +
> +	value |= 1<<  sd;
> +
> +	err = as3722_write(pmic, AS3722_SD_CONTROL, value);
> +	if (err<  0) {
> +		error("failed to write SD control register: %d", err);
> +		return err;
> +	}
> +
> +	return 0;
> +}
> +
> +int as3722_sd_set_voltage(struct as3722 *pmic, unsigned int sd, u8 value)
> +{
> +	int err;
> +
> +	if (sd>  6)
> +		return -EINVAL;
> +
> +	err = as3722_write(pmic, AS3722_SD_VOLTAGE(sd), value);
> +	if (err<  0) {
> +		error("failed to write SD%u voltage register: %d", sd, err);
> +		return err;
> +	}
> +
> +	return 0;
> +}
> +
> +int as3722_ldo_enable(struct as3722 *pmic, unsigned int ldo)
> +{
> +	u8 value;
> +	int err;
> +
> +	if (ldo>  11)
> +		return -EINVAL;
> +
> +	err = as3722_read(pmic, AS3722_LDO_CONTROL,&value);
> +	if (err) {
> +		error("failed to read LDO control register: %d", err);
> +		return err;
> +	}
> +
> +	value |= 1<<  ldo;
> +
> +	err = as3722_write(pmic, AS3722_LDO_CONTROL, value);
> +	if (err<  0) {
> +		error("failed to write LDO control register: %d", err);
> +		return err;
> +	}
> +
> +	return 0;
> +}
> +
> +int as3722_ldo_set_voltage(struct as3722 *pmic, unsigned int ldo, u8 value)
> +{
> +	int err;
> +
> +	if (ldo>  11)
> +		return -EINVAL;
> +
> +	err = as3722_write(pmic, AS3722_LDO_VOLTAGE(ldo), value);
> +	if (err<  0) {
> +		error("failed to write LDO%u voltage register: %d", ldo,
> +		      err);
> +		return err;
> +	}
> +
> +	return 0;
> +}
> +
> +int as3722_gpio_configure(struct as3722 *pmic, unsigned int gpio,
> +			  unsigned long flags)
> +{
> +	u8 value = 0;
> +	int err;
> +
> +	if (flags&  AS3722_GPIO_OUTPUT_VDDH)
> +		value |= AS3722_GPIO_CONTROL_MODE_OUTPUT_VDDH;
> +
> +	if (flags&  AS3722_GPIO_INVERT)
> +		value |= AS3722_GPIO_CONTROL_INVERT;
> +
> +	err = as3722_write(pmic, AS3722_GPIO_CONTROL(gpio), value);
> +	if (err) {
> +		error("failed to configure GPIO#%u: %d", gpio, err);
> +		return err;
> +	}
> +
> +	return 0;
> +}
> +
> +static int as3722_gpio_set(struct as3722 *pmic, unsigned int gpio,
> +			   unsigned int level)
> +{
> +	const char *l;
> +	u8 value;
> +	int err;
> +
> +	if (gpio>  7)
> +		return -EINVAL;
> +
> +	err = as3722_read(pmic, AS3722_GPIO_SIGNAL_OUT,&value);
> +	if (err<  0) {
> +		error("failed to read GPIO signal out register: %d", err);
> +		return err;
> +	}
> +
> +	if (level == 0) {
> +		value&= ~(1<<  gpio);
> +		l = "low";
> +	} else {
> +		value |= 1<<  gpio;
> +		l = "high";
> +	}
> +
> +	err = as3722_write(pmic, AS3722_GPIO_SIGNAL_OUT, value);
> +	if (err) {
> +		error("failed to set GPIO#%u %s: %d", gpio, l, err);
> +		return err;
> +	}
> +
> +	return 0;
> +}
> +
> +int as3722_gpio_direction_output(struct as3722 *pmic, unsigned int gpio,
> +				 unsigned int 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(pmic, AS3722_GPIO_CONTROL(gpio), value);
> +	if (err) {
> +		error("failed to configure GPIO#%u as output: %d", gpio, err);
> +		return err;
> +	}
> +
> +	err = as3722_gpio_set(pmic, gpio, level);
> +	if (err<  0) {
> +		error("failed to set GPIO#%u high: %d", gpio, err);
> +		return err;
> +	}
> +
> +	return 0;
> +}
> +
> +int as3722_init(struct as3722 **pmicp, const void *fdt)
> +{
> +	struct as3722 *pmic =&as3722_pmic;
> +	int count, nodes[1], i;
> +	int err;
> +
> +	count = fdtdec_find_aliases_for_id(fdt, NULL, COMPAT_AMS_AS3722,
> +					   nodes, ARRAY_SIZE(nodes));
> +	for (i = 0; i<  count; i++) {
> +		int parent = fdt_parent_offset(fdt, nodes[i]), bus;
> +		struct i2c_adapter *adapter;
> +		fdt_addr_t address;
> +		u8 id, revision;
> +
> +		bus = i2c_get_bus_num_fdt(parent);
> +		if (bus<  0) {
> +			error("invalid bus %d", bus);
> +			continue;
> +		}
> +
> +		address = fdtdec_get_addr(fdt, nodes[i], "reg");
> +		if (address == FDT_ADDR_T_NONE) {
> +			error("slave address not found");
> +			continue;
> +		}
> +
> +		adapter = i2c_adapter_get(bus);
> +		if (!adapter) {
> +			error("I2C adapter for bus %d not found", bus);
> +			continue;
> +		}

Why is i2c_set_bus_num() not enough for you? Why introducing a new
API? If another uses this PMIC behind a i2c mux, this driver maybe
not work correctly.

bye,
Heiko
> +
> +		err = i2c_client_init(&pmic->client, adapter, address);
> +		if (err<  0) {
> +			error("failed to initialize I2C slave: %d", err);
> +			continue;
> +		}
> +
> +		err = as3722_read_id(pmic,&id,&revision);
> +		if (err<  0) {
> +			error("failed to read ID: %d", err);
> +			continue;
> +		}
> +
> +		if (id != AS3722_DEVICE_ID) {
> +			error("unknown device");
> +			continue;
> +		}
> +
> +		debug("AS3722 revision %#x found on I2C bus %u, address %#x\n",
> +		      revision, bus, address);
> +
> +		*pmicp = pmic;
> +		return 0;
> +	}
> +
> +	return -ENODEV;
> +}
> diff --git a/include/fdtdec.h b/include/fdtdec.h
> index 5c669a5c8e03..3c38375397df 100644
> --- a/include/fdtdec.h
> +++ b/include/fdtdec.h
> @@ -115,6 +115,7 @@ enum fdt_compat_id {
>   	COMPAT_SANDBOX_LCD_SDL,		/* Sandbox LCD emulation with SDL */
>   	COMPAT_TI_TPS65090,		/* Texas Instrument TPS65090 */
>   	COMPAT_NXP_PTN3460,		/* NXP PTN3460 DP/LVDS bridge */
> +	COMPAT_AMS_AS3722,		/* AMS AS3722 PMIC */
>
>   	COMPAT_COUNT,
>   };
> diff --git a/include/power/as3722.h b/include/power/as3722.h
> new file mode 100644
> index 000000000000..2c2e45a44bab
> --- /dev/null
> +++ b/include/power/as3722.h
> @@ -0,0 +1,27 @@
> +/*
> + * Copyright (C) 2014 NVIDIA Corporation
> + *
> + * SPDX-License-Identifier: GPL-2.0+
> + */
> +
> +#ifndef __POWER_AS3722_H__
> +#define __POWER_AS3722_H__
> +
> +#include<asm/types.h>
> +
> +#define AS3722_GPIO_OUTPUT_VDDH (1<<  0)
> +#define AS3722_GPIO_INVERT (1<<  1)
> +
> +struct as3722;
> +
> +int as3722_init(struct as3722 **pmic, const void *fdt);
> +int as3722_sd_enable(struct as3722 *pmic, unsigned int sd);
> +int as3722_sd_set_voltage(struct as3722 *pmic, unsigned int sd, u8 value);
> +int as3722_ldo_enable(struct as3722 *pmic, unsigned int ldo);
> +int as3722_ldo_set_voltage(struct as3722 *pmic, unsigned int ldo, u8 value);
> +int as3722_gpio_configure(struct as3722 *pmic, unsigned int gpio,
> +			  unsigned long flags);
> +int as3722_gpio_direction_output(struct as3722 *pmic, unsigned int gpio,
> +				 unsigned int level);
> +
> +#endif /* __POWER_AS3722_H__ */
> diff --git a/lib/fdtdec.c b/lib/fdtdec.c
> index fa5da0c0147d..cddd86c3186f 100644
> --- a/lib/fdtdec.c
> +++ b/lib/fdtdec.c
> @@ -70,6 +70,7 @@ static const char * const compat_names[COMPAT_COUNT] = {
>   	COMPAT(SANDBOX_LCD_SDL, "sandbox,lcd-sdl"),
>   	COMPAT(TI_TPS65090, "ti,tps65090"),
>   	COMPAT(COMPAT_NXP_PTN3460, "nxp,ptn3460"),
> +	COMPAT(AMS_AS3722, "ams,as3722"),
>   };
>
>   const char *fdtdec_get_compatible(enum fdt_compat_id id)

-- 
DENX Software Engineering GmbH,     MD: Wolfgang Denk & Detlev Zundel
HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany

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

* [U-Boot] [PATCH v2 11/40] i2c: Initialize the correct bus
  2014-08-27  5:12     ` Thierry Reding
@ 2014-08-27  5:26       ` Heiko Schocher
  0 siblings, 0 replies; 104+ messages in thread
From: Heiko Schocher @ 2014-08-27  5:26 UTC (permalink / raw)
  To: u-boot

Hello Thierry,

Am 27.08.2014 07:12, schrieb Thierry Reding:
> On Wed, Aug 27, 2014 at 06:52:16AM +0200, Heiko Schocher wrote:
>> Hello Thierry,
>>
>> Am 26.08.2014 17:33, schrieb Thierry Reding:
>>> From: Thierry Reding<treding@nvidia.com>
>>>
>>> i2c_bus_init() takes a bus number but relies on the currently selected
>>> bus to determine which adapter to initialize. Make the function use the
>>> bus passed in as parameter rather than the currently selected bus. While
>>> at it, keep a pointer to the specified bus to avoid having to look it up
>>> repeatedly.
>>>
>>> Signed-off-by: Thierry Reding<treding@nvidia.com>
>>> ---
>>>   drivers/i2c/i2c_core.c | 15 +++++++++------
>>>   1 file changed, 9 insertions(+), 6 deletions(-)
>>
>> Why you could not use the current CONFIG_SYS_I2C API and init a bus with
>> i2c_set_bus_num()?
>
> That's orthogonal to this patch. i2c_set_bus_num() will end up calling
> the i2c_init_bus() function, too. What this patch does is fix an issue
> where i2c_init_bus is completely ignoring the bus_no parameter (except
> for sanity checking) but instead relies on the gd->cur_i2c_bus (via
> I2C_ADAP) to initialize a bus. That's completely unexpected and making
> this consistent allows the function to be reused in a more generic way
> as done in subsequent patches.

Yes, I think we could drop the bus_no parameter.

bye,
Heiko
>
> Thierry
>
>>> diff --git a/drivers/i2c/i2c_core.c b/drivers/i2c/i2c_core.c
>>> index 18d6736601c1..cca455bc9c63 100644
>>> --- a/drivers/i2c/i2c_core.c
>>> +++ b/drivers/i2c/i2c_core.c
>>> @@ -214,17 +214,20 @@ static int i2c_mux_disconnet_all(void)
>>>    * Initializes one bus. Will initialize the parent adapter. No current bus
>>>    * changes, no mux (if any) setup.
>>>    */
>>> -static void i2c_init_bus(unsigned int bus_no, int speed, int slaveaddr)
>>> +static void i2c_init_bus(unsigned int bus, int speed, int slaveaddr)
>>>   {
>>> -	if (bus_no>= CONFIG_SYS_NUM_I2C_BUSES)
>>> +	struct i2c_adapter *adapter;
>>> +
>>> +	if (bus>= CONFIG_SYS_NUM_I2C_BUSES)
>>>   		return;
>>>
>>> -	I2C_ADAP->init(I2C_ADAP, speed, slaveaddr);
>>> +	adapter = i2c_get_adapter(I2C_ADAPTER(bus));
>>> +	adapter->init(adapter, speed, slaveaddr);
>>>
>>>   	if (gd->flags&   GD_FLG_RELOC) {
>>> -		I2C_ADAP->init_done = 1;
>>> -		I2C_ADAP->speed = speed;
>>> -		I2C_ADAP->slaveaddr = slaveaddr;
>>> +		adapter->init_done = 1;
>>> +		adapter->speed = speed;
>>> +		adapter->slaveaddr = slaveaddr;
>>>   	}
>>>   }
>>>
>>
>> --
>> DENX Software Engineering GmbH,     MD: Wolfgang Denk&  Detlev Zundel
>> HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany

-- 
DENX Software Engineering GmbH,     MD: Wolfgang Denk & Detlev Zundel
HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany

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

* [U-Boot] [PATCH v2 13/40] i2c: Add high-level API
  2014-08-27  5:21   ` Heiko Schocher
@ 2014-08-27  6:21     ` Thierry Reding
  2014-08-27  7:07       ` Heiko Schocher
  0 siblings, 1 reply; 104+ messages in thread
From: Thierry Reding @ 2014-08-27  6:21 UTC (permalink / raw)
  To: u-boot

On Wed, Aug 27, 2014 at 07:21:51AM +0200, Heiko Schocher wrote:
> Hello Thierry,
> 
> Am 26.08.2014 17:34, schrieb Thierry Reding:
> >From: Thierry Reding<treding@nvidia.com>
> >
> >This API operates on I2C adapters or I2C clients (a new type of object
> 
> which is a bad idea ...
> 
> >that refers to a particular slave connected to an adapter). This is
> >useful to avoid having to call i2c_set_bus_num() whenever a device is
> >being accessed.
> 
> But thats the supose of i2c_set_bus_num()! ... if you use an i2c bus,
> you must check before every access, if you are on it, if not, you must
> switch back to it...

That's not what code does today. Everybody calls i2c_set_bus_num() once
and then does a bunch of transactions on that bus. Given that U-Boot
doesn't run multithreaded this works. If you're really concerned about
this being a problem, then it should be solved at a different level. It
could be part of i2c_client for example, so that i2c_client_read() and
i2c_client_write() would always perform this step. Burdening users with
this isn't going to work (in a multithreaded environment the switch to a
different mux could happen between the call to i2c_set_bus_num() and the
bus access).

In fact I think this would even have to be solved at the controller
level if you want to make sure that client transactions are atomic.

> This is collected in i2c_set_bus_num() ... before, every "user" did
> this on his own ... if you are on the bus you want to access, the
> overhead is not so big, see:
> 
> http://git.denx.de/?p=u-boot.git;a=blob;f=drivers/i2c/i2c_core.c;h=18d6736601c161f45cb7d81b5eae53bdeaaf6b0b;hb=7bee1c91a94db19bd26f92cc67be35d3592c6429#l278
> 
>  278 int i2c_set_bus_num(unsigned int bus)
>  279 {
>  280         int max;
>  281
>  282         if ((bus == I2C_BUS) && (I2C_ADAP->init_done > 0))
>  283                 return 0;
> 
> And you must be aware of i2c muxes! You directly use the read/write
> functions from the i2c adapter, but what is if you have i2c muxes?

That's complexity that users shouldn't have to worry about. They should
simply access an adapter and the adapter (or rather the core) should
take care of setting up any muxes correctly.

> Maybe there is on one i2c adapter a i2c mux with 4 ports. On one is
> an eeprom, on the other is a PMIC ... your code in patch
> "power: Add AMS AS3722 PMIC support" does access with your functions
> the PMIC ... what is, if between this accesses someone accesses the eeprom?
> If he switches the mux, you never switch back!
> 
> Your code did not check this!

Like I said, a lot of code in U-Boot doesn't check this. And quite
frankly as long as this isn't handled in the core I don't think people
will get it right.

> Why is i2c_set_bus_num() such a problem?

Because it's completely confusing. And it's exposing an implementation
detail to users instead of handling it transparently in the core.

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/9e77418e/attachment.pgp>

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

* [U-Boot] [PATCH v2 15/40] power: Add AMS AS3722 PMIC support
  2014-08-27  5:26   ` Heiko Schocher
@ 2014-08-27  6:28     ` Thierry Reding
  2014-08-27  7:18       ` Heiko Schocher
  0 siblings, 1 reply; 104+ messages in thread
From: Thierry Reding @ 2014-08-27  6:28 UTC (permalink / raw)
  To: u-boot

On Wed, Aug 27, 2014 at 07:26:12AM +0200, Heiko Schocher wrote:
> Hello Thierry,
> 
> Am 26.08.2014 17:34, schrieb Thierry Reding:
[...]
> >+int as3722_init(struct as3722 **pmicp, const void *fdt)
> >+{
> >+	struct as3722 *pmic =&as3722_pmic;
> >+	int count, nodes[1], i;
> >+	int err;
> >+
> >+	count = fdtdec_find_aliases_for_id(fdt, NULL, COMPAT_AMS_AS3722,
> >+					   nodes, ARRAY_SIZE(nodes));
> >+	for (i = 0; i<  count; i++) {
> >+		int parent = fdt_parent_offset(fdt, nodes[i]), bus;
> >+		struct i2c_adapter *adapter;
> >+		fdt_addr_t address;
> >+		u8 id, revision;
> >+
> >+		bus = i2c_get_bus_num_fdt(parent);
> >+		if (bus<  0) {
> >+			error("invalid bus %d", bus);
> >+			continue;
> >+		}
> >+
> >+		address = fdtdec_get_addr(fdt, nodes[i], "reg");
> >+		if (address == FDT_ADDR_T_NONE) {
> >+			error("slave address not found");
> >+			continue;
> >+		}
> >+
> >+		adapter = i2c_adapter_get(bus);
> >+		if (!adapter) {
> >+			error("I2C adapter for bus %d not found", bus);
> >+			continue;
> >+		}
> 
> Why is i2c_set_bus_num() not enough for you? Why introducing a new
> API? If another uses this PMIC behind a i2c mux, this driver maybe
> not work correctly.

As I explained earlier, I think requiring users to manually micro-manage
the I2C busses is a bad idea. It's very tedious and error prone. It does
also mean that every patch needs to be carefully checked that the I2C
API is used correctly. The intent of the i2c_client API was to introduce
a higher-level object that people can use and that does the bulk of the
work behind the scenes rather than duplicating it all over the place. It
is true that perhaps it currently doesn't work well with I2C muxes. But
the advantage is that when it does, it does so for everybody that uses
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/20140827/284dcb7b/attachment.pgp>

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

* [U-Boot] [PATCH v2 01/40] vsprintf: Add modifier for phys_addr_t
  2014-08-26 17:04   ` Stephen Warren
@ 2014-08-27  7:01     ` Thierry Reding
  2014-08-27 17:41       ` Stephen Warren
  0 siblings, 1 reply; 104+ messages in thread
From: Thierry Reding @ 2014-08-27  7:01 UTC (permalink / raw)
  To: u-boot

On Tue, Aug 26, 2014 at 11:04:56AM -0600, Stephen Warren wrote:
> On 08/26/2014 09:33 AM, Thierry Reding wrote:
> >From: Thierry Reding <treding@nvidia.com>
> >
> >Provide a new modifier to vsprintf() to print phys_addr_t variables to
> >avoid having to cast or #ifdef when printing them out. The %pa modifier
> >is used for this purpose, so phys_addr_t variables need to be passed by
> >reference, like so:
> >
> >	phys_addr_t start = 0;
> >
> >	printf("start: %pa\n", &start);
> >
> >Depending on the size of phys_addr_t this will print out the address
> >with 8 or 16 hexadecimal digits following a 0x prefix.
> 
> The series,
> 
> Tested-by: Stephen Warren <swarren@nvidia.com>
> 
> Note that I did see the following printed a couple of times when I executed
> "run bootcmd_pxe":
> 
> pci_hose_bus_to_phys: invalid physical address
> 
> ... but everything worked perfectly, so I guess we can track that down
> later.

Yes, it should definitely be tracked down. I don't see that message on
my setup. I've seen it for example when noncached_alloc() fails and
returns 0, but in that case everything shouldn't be working perfectly.

It would be helpful if that message showed what physical address was
considered invalid.

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/70108926/attachment.pgp>

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

* [U-Boot] [PATCH v2 13/40] i2c: Add high-level API
  2014-08-27  6:21     ` Thierry Reding
@ 2014-08-27  7:07       ` Heiko Schocher
  2014-08-27  8:51         ` Thierry Reding
  0 siblings, 1 reply; 104+ messages in thread
From: Heiko Schocher @ 2014-08-27  7:07 UTC (permalink / raw)
  To: u-boot

Hello Thierry,

Am 27.08.2014 08:21, schrieb Thierry Reding:
> On Wed, Aug 27, 2014 at 07:21:51AM +0200, Heiko Schocher wrote:
>> Hello Thierry,
>>
>> Am 26.08.2014 17:34, schrieb Thierry Reding:
>>> From: Thierry Reding<treding@nvidia.com>
>>>
>>> This API operates on I2C adapters or I2C clients (a new type of object
>>
>> which is a bad idea ...
>>
>>> that refers to a particular slave connected to an adapter). This is
>>> useful to avoid having to call i2c_set_bus_num() whenever a device is
>>> being accessed.
>>
>> But thats the supose of i2c_set_bus_num()! ... if you use an i2c bus,
>> you must check before every access, if you are on it, if not, you must
>> switch back to it...
>
> That's not what code does today. Everybody calls i2c_set_bus_num() once
> and then does a bunch of transactions on that bus. Given that U-Boot

Yes, sadly. This has historical reasons ...

> doesn't run multithreaded this works. If you're really concerned about

Yes, U-Boot is singlethread only.

> this being a problem, then it should be solved at a different level. It
> could be part of i2c_client for example, so that i2c_client_read() and
> i2c_client_write() would always perform this step. Burdening users with

Exactly, thats right, and this is a goal from the CONFIG_SYS_I2C API!

But why do you introduce i2c_client_read/write and do not add this step
to i2c_read/write?

- convert all i2c drivers, which are not yet converted to CONFIG_SYS_I2C
   (get also rid od CONFIG_HARD_I2C)
- add busnumber to i2c_read/write API and make i2c_set_bus_num() static ...
   and fix all i2c_read/write() calls in U-Boot code ...

I know, this is a big change and a lot of work ... thats the reason
why we are not at this point ... nobody volunteered to go forward, and
I did not found time to do it ...

> this isn't going to work (in a multithreaded environment the switch to a
> different mux could happen between the call to i2c_set_bus_num() and the
> bus access).
>
> In fact I think this would even have to be solved at the controller
> level if you want to make sure that client transactions are atomic.

As U-Boot is single threaded all i2c_read/writes are atomic.

>> This is collected in i2c_set_bus_num() ... before, every "user" did
>> this on his own ... if you are on the bus you want to access, the
>> overhead is not so big, see:
>>
>> http://git.denx.de/?p=u-boot.git;a=blob;f=drivers/i2c/i2c_core.c;h=18d6736601c161f45cb7d81b5eae53bdeaaf6b0b;hb=7bee1c91a94db19bd26f92cc67be35d3592c6429#l278
>>
>>   278 int i2c_set_bus_num(unsigned int bus)
>>   279 {
>>   280         int max;
>>   281
>>   282         if ((bus == I2C_BUS)&&  (I2C_ADAP->init_done>  0))
>>   283                 return 0;
>>
>> And you must be aware of i2c muxes! You directly use the read/write
>> functions from the i2c adapter, but what is if you have i2c muxes?
>
> That's complexity that users shouldn't have to worry about. They should

Exactly!

> simply access an adapter and the adapter (or rather the core) should
> take care of setting up any muxes correctly.

Yes!

I think you mix here i2c adapter with bus. An "U-Boot i2c adapter" is a
hw adapter (or special case soft i2c adapter). An "i2c bus" is a hw adapter
maybe with m muxes, and each bus has exactly one way through the
i2c muxes, see for an example the README:

http://git.denx.de/?p=u-boot.git;a=blob;f=README;h=14d6b227d689825025f9dfc98fb305021882446d;hb=7bee1c91a94db19bd26f92cc67be35d3592c6429#l2349

So the only thing a User must know when he wants to use an i2c bus is
his number. The switching to this i2c adapter, initializing it and maybe
set i2c muxes does the i2c subsystem ...

>> Maybe there is on one i2c adapter a i2c mux with 4 ports. On one is
>> an eeprom, on the other is a PMIC ... your code in patch
>> "power: Add AMS AS3722 PMIC support" does access with your functions
>> the PMIC ... what is, if between this accesses someone accesses the eeprom?
>> If he switches the mux, you never switch back!
>>
>> Your code did not check this!
>
> Like I said, a lot of code in U-Boot doesn't check this. And quite

With using i2c_set_bus_num() you have not to check this! You only have
to call i2c_set_bus_num() before calling i2c_read/write ... and yes,
that would be nice, if we just pass the bus number to i2c_read/write()
and drop the i2c_set_bus_num() call all over the code ...

Patches welcome!

> frankly as long as this isn't handled in the core I don't think people
> will get it right.

Yes, full ack, which is the goal from CONFIG_SYS_I2C. If all i2c
driver are converted to it, we can make i2c_set_bus_num() static, and
add to the i2c API the bus number as a function parameter!

>> Why is i2c_set_bus_num() such a problem?
>
> Because it's completely confusing. And it's exposing an implementation
> detail to users instead of handling it transparently in the core.

Yes! Full Ack ... but I do not accept a new API for that! Please
fix the i2c_read/write() functions!

bye,
Heiko
-- 
DENX Software Engineering GmbH,     MD: Wolfgang Denk & Detlev Zundel
HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany

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

* [U-Boot] [PATCH v2 15/40] power: Add AMS AS3722 PMIC support
  2014-08-27  6:28     ` Thierry Reding
@ 2014-08-27  7:18       ` Heiko Schocher
  0 siblings, 0 replies; 104+ messages in thread
From: Heiko Schocher @ 2014-08-27  7:18 UTC (permalink / raw)
  To: u-boot

Hello Thierry,

Am 27.08.2014 08:28, schrieb Thierry Reding:
> On Wed, Aug 27, 2014 at 07:26:12AM +0200, Heiko Schocher wrote:
>> Hello Thierry,
>>
>> Am 26.08.2014 17:34, schrieb Thierry Reding:
> [...]
>>> +int as3722_init(struct as3722 **pmicp, const void *fdt)
>>> +{
>>> +	struct as3722 *pmic =&as3722_pmic;
>>> +	int count, nodes[1], i;
>>> +	int err;
>>> +
>>> +	count = fdtdec_find_aliases_for_id(fdt, NULL, COMPAT_AMS_AS3722,
>>> +					   nodes, ARRAY_SIZE(nodes));
>>> +	for (i = 0; i<   count; i++) {
>>> +		int parent = fdt_parent_offset(fdt, nodes[i]), bus;
>>> +		struct i2c_adapter *adapter;
>>> +		fdt_addr_t address;
>>> +		u8 id, revision;
>>> +
>>> +		bus = i2c_get_bus_num_fdt(parent);
>>> +		if (bus<   0) {
>>> +			error("invalid bus %d", bus);
>>> +			continue;
>>> +		}
>>> +
>>> +		address = fdtdec_get_addr(fdt, nodes[i], "reg");
>>> +		if (address == FDT_ADDR_T_NONE) {
>>> +			error("slave address not found");
>>> +			continue;
>>> +		}
>>> +
>>> +		adapter = i2c_adapter_get(bus);
>>> +		if (!adapter) {
>>> +			error("I2C adapter for bus %d not found", bus);
>>> +			continue;
>>> +		}
>>
>> Why is i2c_set_bus_num() not enough for you? Why introducing a new
>> API? If another uses this PMIC behind a i2c mux, this driver maybe
>> not work correctly.
>
> As I explained earlier, I think requiring users to manually micro-manage
> the I2C busses is a bad idea. It's very tedious and error prone. It does

I fully aggree with you.

> also mean that every patch needs to be carefully checked that the I2C
> API is used correctly. The intent of the i2c_client API was to introduce
> a higher-level object that people can use and that does the bulk of the
> work behind the scenes rather than duplicating it all over the place. It

I understand you, but why not fixing the current API, so all can
provide from your work?

> is true that perhaps it currently doesn't work well with I2C muxes. But
> the advantage is that when it does, it does so for everybody that uses
> it.

Please fix the i2c_read/write functions, and it works for free with
i2c muxes!

On my ToDo list:

- Fix all old style i2c driver
- make i2c_set_bus_num() static, and add to i2c_read/write()
   the new function parameter "bus" ...
- get rid of HARD_I2C
- remove all i2c_init() calls, as they no longer needed
- remove all oldstyle defines, functions, structs ...
- introduce a deinit() functions for i2c adapters, so if we switch
   to another i2c bus, we deactivate the current i2c hw adapter. So
   if we boot an OS, we have all i2c hw adapters deactivated.

bye,
Heiko
-- 
DENX Software Engineering GmbH,     MD: Wolfgang Denk & Detlev Zundel
HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany

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

* [U-Boot] [PATCH v2 01/40] vsprintf: Add modifier for phys_addr_t
  2014-08-26 23:14   ` [U-Boot] [PATCH v2 " Simon Glass
@ 2014-08-27  7:37     ` Thierry Reding
  2014-08-27 15:24       ` Simon Glass
  0 siblings, 1 reply; 104+ messages in thread
From: Thierry Reding @ 2014-08-27  7:37 UTC (permalink / raw)
  To: u-boot

On Tue, Aug 26, 2014 at 05:14:17PM -0600, Simon Glass wrote:
> Hi Thierry,
> 
> On 26 August 2014 09:33, Thierry Reding <thierry.reding@gmail.com> wrote:
> >
> > From: Thierry Reding <treding@nvidia.com>
> >
> > Provide a new modifier to vsprintf() to print phys_addr_t variables to
> > avoid having to cast or #ifdef when printing them out. The %pa modifier
> > is used for this purpose, so phys_addr_t variables need to be passed by
> > reference, like so:
> >
> >         phys_addr_t start = 0;
> >
> >         printf("start: %pa\n", &start);
> >
> > Depending on the size of phys_addr_t this will print out the address
> > with 8 or 16 hexadecimal digits following a 0x prefix.
> 
> Would it be better to use %#pa to get the 0x prefix so we have the
> option? Hex is the default in U-Boot.

Yeah, that's very confusing since there's no way to tell apart a
hexadecimal number from a decimal one since there's no decimal
equivalent of the 0x prefix.

If you insist I can change that (it should be a simple matter of
dropping the SPECIAL flag in the 'a' case).

> > Signed-off-by: Thierry Reding <treding@nvidia.com>
> > ---
> >  lib/vsprintf.c | 16 ++++++++++++++--
> >  1 file changed, 14 insertions(+), 2 deletions(-)
> >
> > diff --git a/lib/vsprintf.c b/lib/vsprintf.c
> > index 7ec758e40fc5..044d5551bdd0 100644
> > --- a/lib/vsprintf.c
> > +++ b/lib/vsprintf.c
> > @@ -518,6 +518,8 @@ static char *ip4_addr_string(char *buf, char *end, u8 *addr, int field_width,
> >  static char *pointer(const char *fmt, char *buf, char *end, void *ptr,
> >                 int field_width, int precision, int flags)
> >  {
> > +       u64 num = (uintptr_t)ptr;
> > +
> 
> Will this impact code size much? I suppose it is vsprintf() so it
> doesn't matter too much?

Doing only this change and the corresponding change in the call to
number() results in the exact sizes:

	$ size build/jetson-tk1.{before,after}/u-boot
	   text    data     bss     dec     hex filename
	 310434   10872  309184  630490   99eda build/jetson-tk1.before/u-boot
	 310434   10872  309184  630490   99eda build/jetson-tk1.after/u-boot

Given that the num parameter of the number() function is already a u64
the compiler will presumably automatically handle the ptr argument as a
64-bit value.

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/f6de2d2d/attachment.pgp>

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

* [U-Boot] [PATCH v2 13/40] i2c: Add high-level API
  2014-08-27  7:07       ` Heiko Schocher
@ 2014-08-27  8:51         ` Thierry Reding
  2014-08-27  9:56           ` Heiko Schocher
  0 siblings, 1 reply; 104+ messages in thread
From: Thierry Reding @ 2014-08-27  8:51 UTC (permalink / raw)
  To: u-boot

On Wed, Aug 27, 2014 at 09:07:58AM +0200, Heiko Schocher wrote:
> Hello Thierry,
> 
> Am 27.08.2014 08:21, schrieb Thierry Reding:
> >On Wed, Aug 27, 2014 at 07:21:51AM +0200, Heiko Schocher wrote:
> >>Hello Thierry,
> >>
> >>Am 26.08.2014 17:34, schrieb Thierry Reding:
> >>>From: Thierry Reding<treding@nvidia.com>
> >>>
> >>>This API operates on I2C adapters or I2C clients (a new type of object
> >>
> >>which is a bad idea ...
> >>
> >>>that refers to a particular slave connected to an adapter). This is
> >>>useful to avoid having to call i2c_set_bus_num() whenever a device is
> >>>being accessed.
> >>
> >>But thats the supose of i2c_set_bus_num()! ... if you use an i2c bus,
> >>you must check before every access, if you are on it, if not, you must
> >>switch back to it...
> >
> >That's not what code does today. Everybody calls i2c_set_bus_num() once
> >and then does a bunch of transactions on that bus. Given that U-Boot
> 
> Yes, sadly. This has historical reasons ...
> 
> >doesn't run multithreaded this works. If you're really concerned about
> 
> Yes, U-Boot is singlethread only.
> 
> >this being a problem, then it should be solved at a different level. It
> >could be part of i2c_client for example, so that i2c_client_read() and
> >i2c_client_write() would always perform this step. Burdening users with
> 
> Exactly, thats right, and this is a goal from the CONFIG_SYS_I2C API!
> 
> But why do you introduce i2c_client_read/write and do not add this step
> to i2c_read/write?
> 
> - convert all i2c drivers, which are not yet converted to CONFIG_SYS_I2C
>   (get also rid od CONFIG_HARD_I2C)
> - add busnumber to i2c_read/write API and make i2c_set_bus_num() static ...
>   and fix all i2c_read/write() calls in U-Boot code ...

I don't think adding a bus number as parameter is useful. Why not just
use the I2C adapter directly? That way we don't have to keep looking it
up in an array every time.

> I know, this is a big change and a lot of work ... thats the reason
> why we are not at this point ... nobody volunteered to go forward, and
> I did not found time to do it ...

I suppose that would be one possibility to do it. But I consider
i2c_client more of a convenience around the lower-level i2c_read() and
i2c_write(). The idea is that users set up an I2C client once and then
refer to the client, which will automatically use the correct adapter
and slave address rather than having that duplicated in every driver.

> >this isn't going to work (in a multithreaded environment the switch to a
> >different mux could happen between the call to i2c_set_bus_num() and the
> >bus access).
> >
> >In fact I think this would even have to be solved at the controller
> >level if you want to make sure that client transactions are atomic.
> 
> As U-Boot is single threaded all i2c_read/writes are atomic.

In which case you don't have to call i2c_set_bus_num() for every access,
only whenever you don't know exactly where you're coming from. Functions
that perform a sequence of accesses only need to set it once.

Also, if we directly talk to an adapter instead, then the bulk of what
i2c_set_bus_num() does isn't even required. It would require that
adapters are made aware of a hierarchy if there are muxes, but I think
that's worthwhile to do in any case. Also if ever I2C muxing needs to
gain device tree support having the muxes set up dynamically will be
pretty much a prerequisite.

> >>This is collected in i2c_set_bus_num() ... before, every "user" did
> >>this on his own ... if you are on the bus you want to access, the
> >>overhead is not so big, see:
> >>
> >>http://git.denx.de/?p=u-boot.git;a=blob;f=drivers/i2c/i2c_core.c;h=18d6736601c161f45cb7d81b5eae53bdeaaf6b0b;hb=7bee1c91a94db19bd26f92cc67be35d3592c6429#l278
> >>
> >>  278 int i2c_set_bus_num(unsigned int bus)
> >>  279 {
> >>  280         int max;
> >>  281
> >>  282         if ((bus == I2C_BUS)&&  (I2C_ADAP->init_done>  0))
> >>  283                 return 0;
> >>
> >>And you must be aware of i2c muxes! You directly use the read/write
> >>functions from the i2c adapter, but what is if you have i2c muxes?
> >
> >That's complexity that users shouldn't have to worry about. They should
> 
> Exactly!
> 
> >simply access an adapter and the adapter (or rather the core) should
> >take care of setting up any muxes correctly.
> 
> Yes!
> 
> I think you mix here i2c adapter with bus. An "U-Boot i2c adapter" is a
> hw adapter (or special case soft i2c adapter). An "i2c bus" is a hw adapter
> maybe with m muxes, and each bus has exactly one way through the
> i2c muxes, see for an example the README:
> 
> http://git.denx.de/?p=u-boot.git;a=blob;f=README;h=14d6b227d689825025f9dfc98fb305021882446d;hb=7bee1c91a94db19bd26f92cc67be35d3592c6429#l2349
> 
> So the only thing a User must know when he wants to use an i2c bus is
> his number. The switching to this i2c adapter, initializing it and maybe
> set i2c muxes does the i2c subsystem ...

The above doesn't preclude an I2C adapter representing one of the ports
of a mux. That way you can still talk to an adapter rather than having
to refer to the bus by number. Adapter would become a little more
abstract than it is now, since it would be simply an output that I2C
slaves are connected to (either a HW controller directly or a mux
connected to a HW controller).

> >>Maybe there is on one i2c adapter a i2c mux with 4 ports. On one is
> >>an eeprom, on the other is a PMIC ... your code in patch
> >>"power: Add AMS AS3722 PMIC support" does access with your functions
> >>the PMIC ... what is, if between this accesses someone accesses the eeprom?
> >>If he switches the mux, you never switch back!
> >>
> >>Your code did not check this!
> >
> >Like I said, a lot of code in U-Boot doesn't check this. And quite
> 
> With using i2c_set_bus_num() you have not to check this! You only have
> to call i2c_set_bus_num() before calling i2c_read/write ... and yes,
> that would be nice, if we just pass the bus number to i2c_read/write()
> and drop the i2c_set_bus_num() call all over the code ...
> 
> Patches welcome!

How about a slightly different proposal: introduce a new level of
abstraction (like i2c_client) and start using it in new I2C slave
drivers. At the same time existing drivers could be converted one at a
time without having the big flag date when i2c_read() and i2c_write()
are switched over all at once.

When that new level of abstraction is used, we can hide all the
details behind that and the implementation no longer influences any of
the drivers. Then we could transparently rework adapters and muxes to
our heart's content without needing to update users of the high-level
API.

> >frankly as long as this isn't handled in the core I don't think people
> >will get it right.
> 
> Yes, full ack, which is the goal from CONFIG_SYS_I2C. If all i2c
> driver are converted to it, we can make i2c_set_bus_num() static, and
> add to the i2c API the bus number as a function parameter!
> 
> >>Why is i2c_set_bus_num() such a problem?
> >
> >Because it's completely confusing. And it's exposing an implementation
> >detail to users instead of handling it transparently in the core.
> 
> Yes! Full Ack ... but I do not accept a new API for that! Please
> fix the i2c_read/write() functions!

Doing this kind of conversion is a nightmare. We'd be changing an API
that has around 600 occurrences in U-Boot, all of which need to be
changed *at once* to avoid build breakage. At the same time we need to
make sure any patches in development use the same API, which means that
they can't even be build-tested until the the API has been changed.

Transitioning step by step is a lot less complicated.

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/ff1ac85e/attachment.pgp>

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

* [U-Boot] [PATCH v2 13/40] i2c: Add high-level API
  2014-08-27  8:51         ` Thierry Reding
@ 2014-08-27  9:56           ` Heiko Schocher
  2014-08-27 11:41             ` Thierry Reding
  0 siblings, 1 reply; 104+ messages in thread
From: Heiko Schocher @ 2014-08-27  9:56 UTC (permalink / raw)
  To: u-boot

Hello Thierry,

Am 27.08.2014 10:51, schrieb Thierry Reding:
> On Wed, Aug 27, 2014 at 09:07:58AM +0200, Heiko Schocher wrote:
>> Hello Thierry,
>>
>> Am 27.08.2014 08:21, schrieb Thierry Reding:
>>> On Wed, Aug 27, 2014 at 07:21:51AM +0200, Heiko Schocher wrote:
>>>> Hello Thierry,
>>>>
>>>> Am 26.08.2014 17:34, schrieb Thierry Reding:
>>>>> From: Thierry Reding<treding@nvidia.com>
>>>>>
>>>>> This API operates on I2C adapters or I2C clients (a new type of object
>>>>
>>>> which is a bad idea ...
>>>>
>>>>> that refers to a particular slave connected to an adapter). This is
>>>>> useful to avoid having to call i2c_set_bus_num() whenever a device is
>>>>> being accessed.
>>>>
>>>> But thats the supose of i2c_set_bus_num()! ... if you use an i2c bus,
>>>> you must check before every access, if you are on it, if not, you must
>>>> switch back to it...
>>>
>>> That's not what code does today. Everybody calls i2c_set_bus_num() once
>>> and then does a bunch of transactions on that bus. Given that U-Boot
>>
>> Yes, sadly. This has historical reasons ...
>>
>>> doesn't run multithreaded this works. If you're really concerned about
>>
>> Yes, U-Boot is singlethread only.
>>
>>> this being a problem, then it should be solved at a different level. It
>>> could be part of i2c_client for example, so that i2c_client_read() and
>>> i2c_client_write() would always perform this step. Burdening users with
>>
>> Exactly, thats right, and this is a goal from the CONFIG_SYS_I2C API!
>>
>> But why do you introduce i2c_client_read/write and do not add this step
>> to i2c_read/write?
>>
>> - convert all i2c drivers, which are not yet converted to CONFIG_SYS_I2C
>>    (get also rid od CONFIG_HARD_I2C)
>> - add busnumber to i2c_read/write API and make i2c_set_bus_num() static ...
>>    and fix all i2c_read/write() calls in U-Boot code ...
>
> I don't think adding a bus number as parameter is useful. Why not just
> use the I2C adapter directly? That way we don't have to keep looking it
> up in an array every time.

You again just talk from i2c_adapter ... why you ignore i2c muxes?
A bus is not only an i2c adapter ...

Currently we have two "versions" of i2c_adapter:

In a system without muxes, you can say: i2c bus == i2c adapter
but in a system with muxes we have:     i2c bus == i2c_bus_hose

i2c commands use also a "bus number" starting from 0 ... the bus number
has historical reasons... we could change this ...

But if we introduce a new API, please with mux functionallity ...
Hmm.. thinking about it ... if you want to introduce a new API, please
start with using the DM for I2C!

>> I know, this is a big change and a lot of work ... thats the reason
>> why we are not at this point ... nobody volunteered to go forward, and
>> I did not found time to do it ...
>
> I suppose that would be one possibility to do it. But I consider
> i2c_client more of a convenience around the lower-level i2c_read() and
> i2c_write(). The idea is that users set up an I2C client once and then
> refer to the client, which will automatically use the correct adapter
> and slave address rather than having that duplicated in every driver.

Hmm... Ok, if we want to have a i2c_client struct instead an int ...
What do others think?

But, if we(you ;-) touch this, please start with using the DM for I2C!
This is also a step which should be done, and I do not want to have another
API, if somedays we find time to switch to DM!

>>> this isn't going to work (in a multithreaded environment the switch to a
>>> different mux could happen between the call to i2c_set_bus_num() and the
>>> bus access).
>>>
>>> In fact I think this would even have to be solved at the controller
>>> level if you want to make sure that client transactions are atomic.
>>
>> As U-Boot is single threaded all i2c_read/writes are atomic.
>
> In which case you don't have to call i2c_set_bus_num() for every access,
> only whenever you don't know exactly where you're coming from. Functions
> that perform a sequence of accesses only need to set it once.

Yes ... which really is a pro for having i2c_set_bus_num() not static ...

> Also, if we directly talk to an adapter instead, then the bulk of what

You ignore again muxes ...

> i2c_set_bus_num() does isn't even required. It would require that

What does i2c_set_bus_num() ?

- first check, if current bus = new bus, and if it is initialized
   if so -> all is good, return!

Thats the main case ... is this so expensive? This checks should
be always done (except we do a bulk of i2c accesses, yes). I think,
this has also to be done somewhere with your approach ... or?

What is done in the case, we switch to another bus:

- If we have no muxes, save new bus for further use
- look if new bus is initialized, if not initialize it

All this is hidden from the user ... and actions, which must be done,
whatever API you define ...

If I understand you correct, your big change is not using "int bus"
instead introducing i2c_client ... and define some functions, which
use this struct as parameter ...

Why not defining:

[1]:
int i2c_bus_read(int bus, uint8_t chip,
              unsigned int address, size_t alen, void *buffer,
              size_t size)
{
     i2c_set_bus_num(bus);
     return i2c_read(chip, address, alen, buffer, size);
}

int i2c_bus_write(int bus, uint8_t chip,
               unsigned int address, size_t alen, void *buffer,
               size_t size)
{
     i2c_set_bus_num(bus);
     return i2c_write(chip, address, alen, buffer, size);
}

and you never have to call something like i2c_init(), as
i2c_set_bus_num() does this all for you! You only have to use in your
driver i2c_bus_read/write ... without taking any attention ...

looking deeper in your approach:

+int i2c_client_init(struct i2c_client *client, struct i2c_adapter *adapter,
+            uint8_t address)
+{
+    client->adapter = adapter;
+    client->address = address;
+
+    return 0;
+}

Where is here called adapter->init() ? Nor you check, if the i2c
adapter is intialized ... if more than one driver uses this function,
each intializes the hw? Or currently none :-(

> adapters are made aware of a hierarchy if there are muxes, but I think
> that's worthwhile to do in any case. Also if ever I2C muxing needs to
> gain device tree support having the muxes set up dynamically will be
> pretty much a prerequisite.
>
>>>> This is collected in i2c_set_bus_num() ... before, every "user" did
>>>> this on his own ... if you are on the bus you want to access, the
>>>> overhead is not so big, see:
>>>>
>>>> http://git.denx.de/?p=u-boot.git;a=blob;f=drivers/i2c/i2c_core.c;h=18d6736601c161f45cb7d81b5eae53bdeaaf6b0b;hb=7bee1c91a94db19bd26f92cc67be35d3592c6429#l278
>>>>
>>>>   278 int i2c_set_bus_num(unsigned int bus)
>>>>   279 {
>>>>   280         int max;
>>>>   281
>>>>   282         if ((bus == I2C_BUS)&&   (I2C_ADAP->init_done>   0))
>>>>   283                 return 0;
>>>>
>>>> And you must be aware of i2c muxes! You directly use the read/write
>>>> functions from the i2c adapter, but what is if you have i2c muxes?
>>>
>>> That's complexity that users shouldn't have to worry about. They should
>>
>> Exactly!
>>
>>> simply access an adapter and the adapter (or rather the core) should
>>> take care of setting up any muxes correctly.
>>
>> Yes!
>>
>> I think you mix here i2c adapter with bus. An "U-Boot i2c adapter" is a
>> hw adapter (or special case soft i2c adapter). An "i2c bus" is a hw adapter
>> maybe with m muxes, and each bus has exactly one way through the
>> i2c muxes, see for an example the README:
>>
>> http://git.denx.de/?p=u-boot.git;a=blob;f=README;h=14d6b227d689825025f9dfc98fb305021882446d;hb=7bee1c91a94db19bd26f92cc67be35d3592c6429#l2349
>>
>> So the only thing a User must know when he wants to use an i2c bus is
>> his number. The switching to this i2c adapter, initializing it and maybe
>> set i2c muxes does the i2c subsystem ...
>
> The above doesn't preclude an I2C adapter representing one of the ports
> of a mux. That way you can still talk to an adapter rather than having
> to refer to the bus by number. Adapter would become a little more
> abstract than it is now, since it would be simply an output that I2C

Oh!

> slaves are connected to (either a HW controller directly or a mux
> connected to a HW controller).

Thats sounds for me, that you should use DM ... I do not know, what
your plans are!

>>>> Maybe there is on one i2c adapter a i2c mux with 4 ports. On one is
>>>> an eeprom, on the other is a PMIC ... your code in patch
>>>> "power: Add AMS AS3722 PMIC support" does access with your functions
>>>> the PMIC ... what is, if between this accesses someone accesses the eeprom?
>>>> If he switches the mux, you never switch back!
>>>>
>>>> Your code did not check this!
>>>
>>> Like I said, a lot of code in U-Boot doesn't check this. And quite
>>
>> With using i2c_set_bus_num() you have not to check this! You only have
>> to call i2c_set_bus_num() before calling i2c_read/write ... and yes,
>> that would be nice, if we just pass the bus number to i2c_read/write()
>> and drop the i2c_set_bus_num() call all over the code ...
>>
>> Patches welcome!
>
> How about a slightly different proposal: introduce a new level of
> abstraction (like i2c_client) and start using it in new I2C slave
> drivers. At the same time existing drivers could be converted one at a
> time without having the big flag date when i2c_read() and i2c_write()
> are switched over all at once.

Sound like use/introduce DM for I2C!

> When that new level of abstraction is used, we can hide all the
> details behind that and the implementation no longer influences any of
> the drivers. Then we could transparently rework adapters and muxes to
> our heart's content without needing to update users of the high-level
> API.

Ok, with some functions like in [1], maybe you introduce i2c_client,
and use this instead "int bus" ...

>>> frankly as long as this isn't handled in the core I don't think people
>>> will get it right.
>>
>> Yes, full ack, which is the goal from CONFIG_SYS_I2C. If all i2c
>> driver are converted to it, we can make i2c_set_bus_num() static, and
>> add to the i2c API the bus number as a function parameter!
>>
>>>> Why is i2c_set_bus_num() such a problem?
>>>
>>> Because it's completely confusing. And it's exposing an implementation
>>> detail to users instead of handling it transparently in the core.
>>
>> Yes! Full Ack ... but I do not accept a new API for that! Please
>> fix the i2c_read/write() functions!
>
> Doing this kind of conversion is a nightmare. We'd be changing an API

Full Ack.

> that has around 600 occurrences in U-Boot, all of which need to be
> changed *at once* to avoid build breakage. At the same time we need to
> make sure any patches in development use the same API, which means that
> they can't even be build-tested until the the API has been changed.
>
> Transitioning step by step is a lot less complicated.

Ok, it was worth a try ;-)

So what do you think about defining functions like in [1] ?

bye,
Heiko
-- 
DENX Software Engineering GmbH,     MD: Wolfgang Denk & Detlev Zundel
HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany

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

* [U-Boot] [PATCH v2 13/40] i2c: Add high-level API
  2014-08-27  9:56           ` Heiko Schocher
@ 2014-08-27 11:41             ` Thierry Reding
  2014-08-27 19:10               ` Simon Glass
  0 siblings, 1 reply; 104+ messages in thread
From: Thierry Reding @ 2014-08-27 11:41 UTC (permalink / raw)
  To: u-boot

On Wed, Aug 27, 2014 at 11:56:41AM +0200, Heiko Schocher wrote:
> Hello Thierry,
> 
> Am 27.08.2014 10:51, schrieb Thierry Reding:
> >On Wed, Aug 27, 2014 at 09:07:58AM +0200, Heiko Schocher wrote:
> >>Hello Thierry,
> >>
> >>Am 27.08.2014 08:21, schrieb Thierry Reding:
> >>>On Wed, Aug 27, 2014 at 07:21:51AM +0200, Heiko Schocher wrote:
> >>>>Hello Thierry,
> >>>>
> >>>>Am 26.08.2014 17:34, schrieb Thierry Reding:
> >>>>>From: Thierry Reding<treding@nvidia.com>
> >>>>>
> >>>>>This API operates on I2C adapters or I2C clients (a new type of object
> >>>>
> >>>>which is a bad idea ...
> >>>>
> >>>>>that refers to a particular slave connected to an adapter). This is
> >>>>>useful to avoid having to call i2c_set_bus_num() whenever a device is
> >>>>>being accessed.
> >>>>
> >>>>But thats the supose of i2c_set_bus_num()! ... if you use an i2c bus,
> >>>>you must check before every access, if you are on it, if not, you must
> >>>>switch back to it...
> >>>
> >>>That's not what code does today. Everybody calls i2c_set_bus_num() once
> >>>and then does a bunch of transactions on that bus. Given that U-Boot
> >>
> >>Yes, sadly. This has historical reasons ...
> >>
> >>>doesn't run multithreaded this works. If you're really concerned about
> >>
> >>Yes, U-Boot is singlethread only.
> >>
> >>>this being a problem, then it should be solved at a different level. It
> >>>could be part of i2c_client for example, so that i2c_client_read() and
> >>>i2c_client_write() would always perform this step. Burdening users with
> >>
> >>Exactly, thats right, and this is a goal from the CONFIG_SYS_I2C API!
> >>
> >>But why do you introduce i2c_client_read/write and do not add this step
> >>to i2c_read/write?
> >>
> >>- convert all i2c drivers, which are not yet converted to CONFIG_SYS_I2C
> >>   (get also rid od CONFIG_HARD_I2C)
> >>- add busnumber to i2c_read/write API and make i2c_set_bus_num() static ...
> >>   and fix all i2c_read/write() calls in U-Boot code ...
> >
> >I don't think adding a bus number as parameter is useful. Why not just
> >use the I2C adapter directly? That way we don't have to keep looking it
> >up in an array every time.
> 
> You again just talk from i2c_adapter ... why you ignore i2c muxes?
> A bus is not only an i2c adapter ...

I know. I keep saying i2c_adapter because in the rough sketch that I
have in mind for how this could work eventually, an mux is just another
special kind of i2c_adapter.

> Currently we have two "versions" of i2c_adapter:
> 
> In a system without muxes, you can say: i2c bus == i2c adapter
> but in a system with muxes we have:     i2c bus == i2c_bus_hose
> 
> i2c commands use also a "bus number" starting from 0 ... the bus number
> has historical reasons... we could change this ...
> 
> But if we introduce a new API, please with mux functionallity ...
> Hmm.. thinking about it ... if you want to introduce a new API, please
> start with using the DM for I2C!

I can look into it, but it sounds like a task way beyond what I have
time for right now.

> >>>this isn't going to work (in a multithreaded environment the switch to a
> >>>different mux could happen between the call to i2c_set_bus_num() and the
> >>>bus access).
> >>>
> >>>In fact I think this would even have to be solved at the controller
> >>>level if you want to make sure that client transactions are atomic.
> >>
> >>As U-Boot is single threaded all i2c_read/writes are atomic.
> >
> >In which case you don't have to call i2c_set_bus_num() for every access,
> >only whenever you don't know exactly where you're coming from. Functions
> >that perform a sequence of accesses only need to set it once.
> 
> Yes ... which really is a pro for having i2c_set_bus_num() not static ...

Or if said functionality is encapsulated within adapters then they can
be done as necessary with the same effect.

> >Also, if we directly talk to an adapter instead, then the bulk of what
> 
> You ignore again muxes ...
> 
> >i2c_set_bus_num() does isn't even required. It would require that
> 
> What does i2c_set_bus_num() ?
> 
> - first check, if current bus = new bus, and if it is initialized
>   if so -> all is good, return!
> 
> Thats the main case ... is this so expensive? This checks should
> be always done (except we do a bulk of i2c accesses, yes). I think,
> this has also to be done somewhere with your approach ... or?

It's currently done as part of i2c_adapter_get() which as you already
point out only work when muxes aren't used. But the main issue about the
current approach is that we have these global indices and pass them
around in global state and need to be careful to always set the current
bus where appropriate.

If we simply pass adapters around (provided they handle muxes correctly)
we can simply address each slave as an (adapter, slave address) pair,
rather than repeating the same arguments over and over and calling very
low-level bus management functions.

But we already agree that this isn't optimal. The disagreement seems to
be mostly about the implementation details.

> What is done in the case, we switch to another bus:
> 
> - If we have no muxes, save new bus for further use
> - look if new bus is initialized, if not initialize it
> 
> All this is hidden from the user ... and actions, which must be done,
> whatever API you define ...
> 
> If I understand you correct, your big change is not using "int bus"
> instead introducing i2c_client ... and define some functions, which
> use this struct as parameter ...

Correct.

> Why not defining:
> 
> [1]:
> int i2c_bus_read(int bus, uint8_t chip,
>              unsigned int address, size_t alen, void *buffer,
>              size_t size)
> {
>     i2c_set_bus_num(bus);
>     return i2c_read(chip, address, alen, buffer, size);
> }
> 
> int i2c_bus_write(int bus, uint8_t chip,
>               unsigned int address, size_t alen, void *buffer,
>               size_t size)
> {
>     i2c_set_bus_num(bus);
>     return i2c_write(chip, address, alen, buffer, size);
> }
> 
> and you never have to call something like i2c_init(), as
> i2c_set_bus_num() does this all for you! You only have to use in your
> driver i2c_bus_read/write ... without taking any attention ...

Yes, that sounds like a useful change in itself. But it still requires
users to explicitly manage the bus and chip numbers. The goal of the
i2c_client API is to standardize on how to talk to clients. Essentially
the goal would be for a driver to get a hold of a struct i2c_client via
some standard interface (perhaps with DM this could be done completely
outside of the driver itself) and then talks to the device via this
standard object. Currently drivers either need to hardcode the bus
number and slave addresses, or they need to store them in some custom
structure. i2c_client gives uniformity to that.

There are really two parts of a puzzle here. One is the client-side API
that drivers for slave devices use and the other is the I2C controller
drivers that provide the struct i2c_adapter.

> looking deeper in your approach:
> 
> +int i2c_client_init(struct i2c_client *client, struct i2c_adapter *adapter,
> +            uint8_t address)
> +{
> +    client->adapter = adapter;
> +    client->address = address;
> +
> +    return 0;
> +}
> 
> Where is here called adapter->init() ? Nor you check, if the i2c
> adapter is intialized ... if more than one driver uses this function,
> each intializes the hw? Or currently none :-(

It's done as part of the i2c_adapter_get(). It takes an index (which is
roughly the bus number) initializes the corresponding adapter (if found)
and returns a pointer to it.

To handle muxes I think this could work by adding hooks that could be
called before doing transactions to make sure that the correct muxing is
set up.

> >adapters are made aware of a hierarchy if there are muxes, but I think
> >that's worthwhile to do in any case. Also if ever I2C muxing needs to
> >gain device tree support having the muxes set up dynamically will be
> >pretty much a prerequisite.
> >
> >>>>This is collected in i2c_set_bus_num() ... before, every "user" did
> >>>>this on his own ... if you are on the bus you want to access, the
> >>>>overhead is not so big, see:
> >>>>
> >>>>http://git.denx.de/?p=u-boot.git;a=blob;f=drivers/i2c/i2c_core.c;h=18d6736601c161f45cb7d81b5eae53bdeaaf6b0b;hb=7bee1c91a94db19bd26f92cc67be35d3592c6429#l278
> >>>>
> >>>>  278 int i2c_set_bus_num(unsigned int bus)
> >>>>  279 {
> >>>>  280         int max;
> >>>>  281
> >>>>  282         if ((bus == I2C_BUS)&&   (I2C_ADAP->init_done>   0))
> >>>>  283                 return 0;
> >>>>
> >>>>And you must be aware of i2c muxes! You directly use the read/write
> >>>>functions from the i2c adapter, but what is if you have i2c muxes?
> >>>
> >>>That's complexity that users shouldn't have to worry about. They should
> >>
> >>Exactly!
> >>
> >>>simply access an adapter and the adapter (or rather the core) should
> >>>take care of setting up any muxes correctly.
> >>
> >>Yes!
> >>
> >>I think you mix here i2c adapter with bus. An "U-Boot i2c adapter" is a
> >>hw adapter (or special case soft i2c adapter). An "i2c bus" is a hw adapter
> >>maybe with m muxes, and each bus has exactly one way through the
> >>i2c muxes, see for an example the README:
> >>
> >>http://git.denx.de/?p=u-boot.git;a=blob;f=README;h=14d6b227d689825025f9dfc98fb305021882446d;hb=7bee1c91a94db19bd26f92cc67be35d3592c6429#l2349
> >>
> >>So the only thing a User must know when he wants to use an i2c bus is
> >>his number. The switching to this i2c adapter, initializing it and maybe
> >>set i2c muxes does the i2c subsystem ...
> >
> >The above doesn't preclude an I2C adapter representing one of the ports
> >of a mux. That way you can still talk to an adapter rather than having
> >to refer to the bus by number. Adapter would become a little more
> >abstract than it is now, since it would be simply an output that I2C
> 
> Oh!
> 
> >slaves are connected to (either a HW controller directly or a mux
> >connected to a HW controller).
> 
> Thats sounds for me, that you should use DM ... I do not know, what
> your plans are!

Yes, perhaps DM is part of the solution. But I don't have any concrete
plans. I'd rather tackle this step by step rather than as one monolithic
patch series.

> >When that new level of abstraction is used, we can hide all the
> >details behind that and the implementation no longer influences any of
> >the drivers. Then we could transparently rework adapters and muxes to
> >our heart's content without needing to update users of the high-level
> >API.
> 
> Ok, with some functions like in [1], maybe you introduce i2c_client,
> and use this instead "int bus" ...

This would probably work fine to approach the problem from two sides. An
API like the i2c_client could be used to abstract away all the
implementation details on the controller/mux side and then more work
could be done to convert the adapter side of things to whatever works
best.

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/9dcc975f/attachment.pgp>

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

* [U-Boot] [PATCH v2 01/40] vsprintf: Add modifier for phys_addr_t
  2014-08-27  7:37     ` Thierry Reding
@ 2014-08-27 15:24       ` Simon Glass
  0 siblings, 0 replies; 104+ messages in thread
From: Simon Glass @ 2014-08-27 15:24 UTC (permalink / raw)
  To: u-boot

Hi Thierry,

On 27 August 2014 01:37, Thierry Reding <thierry.reding@gmail.com> wrote:
> On Tue, Aug 26, 2014 at 05:14:17PM -0600, Simon Glass wrote:
>> Hi Thierry,
>>
>> On 26 August 2014 09:33, Thierry Reding <thierry.reding@gmail.com> wrote:
>> >
>> > From: Thierry Reding <treding@nvidia.com>
>> >
>> > Provide a new modifier to vsprintf() to print phys_addr_t variables to
>> > avoid having to cast or #ifdef when printing them out. The %pa modifier
>> > is used for this purpose, so phys_addr_t variables need to be passed by
>> > reference, like so:
>> >
>> >         phys_addr_t start = 0;
>> >
>> >         printf("start: %pa\n", &start);
>> >
>> > Depending on the size of phys_addr_t this will print out the address
>> > with 8 or 16 hexadecimal digits following a 0x prefix.
>>
>> Would it be better to use %#pa to get the 0x prefix so we have the
>> option? Hex is the default in U-Boot.
>
> Yeah, that's very confusing since there's no way to tell apart a
> hexadecimal number from a decimal one since there's no decimal
> equivalent of the 0x prefix.
>
> If you insist I can change that (it should be a simple matter of
> dropping the SPECIAL flag in the 'a' case).

%p doesn't imply %#p, this seems like a unilateral change of
behaviour. So I think you should drop the SPECIAL flag.

It might be confusing in some cases but I feel it is quite expected
that an 8- or 16-digit value will be hex in U-Boot.

If you wish to change the default input/output base for U-Boot I feel
that would require a larger patch.

>
>> > Signed-off-by: Thierry Reding <treding@nvidia.com>
>> > ---
>> >  lib/vsprintf.c | 16 ++++++++++++++--
>> >  1 file changed, 14 insertions(+), 2 deletions(-)
>> >
>> > diff --git a/lib/vsprintf.c b/lib/vsprintf.c
>> > index 7ec758e40fc5..044d5551bdd0 100644
>> > --- a/lib/vsprintf.c
>> > +++ b/lib/vsprintf.c
>> > @@ -518,6 +518,8 @@ static char *ip4_addr_string(char *buf, char *end, u8 *addr, int field_width,
>> >  static char *pointer(const char *fmt, char *buf, char *end, void *ptr,
>> >                 int field_width, int precision, int flags)
>> >  {
>> > +       u64 num = (uintptr_t)ptr;
>> > +
>>
>> Will this impact code size much? I suppose it is vsprintf() so it
>> doesn't matter too much?
>
> Doing only this change and the corresponding change in the call to
> number() results in the exact sizes:
>
>         $ size build/jetson-tk1.{before,after}/u-boot
>            text    data     bss     dec     hex filename
>          310434   10872  309184  630490   99eda build/jetson-tk1.before/u-boot
>          310434   10872  309184  630490   99eda build/jetson-tk1.after/u-boot
>
> Given that the num parameter of the number() function is already a u64
> the compiler will presumably automatically handle the ptr argument as a
> 64-bit value.

I hadn't picked that up - I though ulong was 32-bit. Still this code
affects most boards.

Regards,
Simon


>
> Thierry

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

* [U-Boot] [PATCH v2 01/40] vsprintf: Add modifier for phys_addr_t
  2014-08-27  7:01     ` Thierry Reding
@ 2014-08-27 17:41       ` Stephen Warren
  2014-08-28 10:38         ` Thierry Reding
  0 siblings, 1 reply; 104+ messages in thread
From: Stephen Warren @ 2014-08-27 17:41 UTC (permalink / raw)
  To: u-boot

On 08/27/2014 01:01 AM, Thierry Reding wrote:
> On Tue, Aug 26, 2014 at 11:04:56AM -0600, Stephen Warren wrote:
>> On 08/26/2014 09:33 AM, Thierry Reding wrote:
>>> From: Thierry Reding <treding@nvidia.com>
>>>
>>> Provide a new modifier to vsprintf() to print phys_addr_t variables to
>>> avoid having to cast or #ifdef when printing them out. The %pa modifier
>>> is used for this purpose, so phys_addr_t variables need to be passed by
>>> reference, like so:
>>>
>>> 	phys_addr_t start = 0;
>>>
>>> 	printf("start: %pa\n", &start);
>>>
>>> Depending on the size of phys_addr_t this will print out the address
>>> with 8 or 16 hexadecimal digits following a 0x prefix.
>>
>> The series,
>>
>> Tested-by: Stephen Warren <swarren@nvidia.com>
>>
>> Note that I did see the following printed a couple of times when I executed
>> "run bootcmd_pxe":
>>
>> pci_hose_bus_to_phys: invalid physical address
>>
>> ... but everything worked perfectly, so I guess we can track that down
>> later.
>
> Yes, it should definitely be tracked down. I don't see that message on
> my setup. I've seen it for example when noncached_alloc() fails and
> returns 0, but in that case everything shouldn't be working perfectly.

It looks like it happens when "dhcp" or "pxe get" attempt to download a 
file that doesn't exist on the server.

> It would be helpful if that message showed what physical address was
> considered invalid.

The address is 0. I think this is because rtl_recv() is being called 
after rtl_halt(). rtl_halt() NULLs out all tpc->RxBufferRing[] entries, 
so calling rtl_recv() after that tries to convert address 0 to a PCI 
address. I haven't fully tracked this down, but it seems like a bug in 
the U-Boot networking or TFTP core, rather than anything to do with 
drivers for R8169 or the Tegra PCIe controller.

I'm not planning on tracking this down any further at the moment.

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

* [U-Boot] [PATCH v2 02/40] fdt: Add a function to count strings
  2014-08-26 15:33 ` [U-Boot] [PATCH v2 02/40] fdt: Add a function to count strings Thierry Reding
@ 2014-08-27 18:51   ` Simon Glass
  2014-09-08 15:01     ` Simon Glass
  0 siblings, 1 reply; 104+ messages in thread
From: Simon Glass @ 2014-08-27 18:51 UTC (permalink / raw)
  To: u-boot

Hi Thierry,

On 26 August 2014 09:33, Thierry Reding <thierry.reding@gmail.com> wrote:
> From: Thierry Reding <treding@nvidia.com>
>
> Given a device tree node and a property name, the fdt_count_strings()
> function counts the number of strings found in the property value.
>
> Signed-off-by: Thierry Reding <treding@nvidia.com>

A better name might be fdt_stringlist_count() given that we have
fdt_stringlist_contains(). But let's take this and see what happens
when you send it upstream.

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

Regards,
Simon

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

* [U-Boot] [PATCH v2 03/40] fdt: Add a function to get the index of a string
  2014-08-26 15:33 ` [U-Boot] [PATCH v2 03/40] fdt: Add a function to get the index of a string Thierry Reding
@ 2014-08-27 18:51   ` Simon Glass
  2014-09-08 15:02     ` Simon Glass
  0 siblings, 1 reply; 104+ messages in thread
From: Simon Glass @ 2014-08-27 18:51 UTC (permalink / raw)
  To: u-boot

Hi Thierry,

On 26 August 2014 09:33, Thierry Reding <thierry.reding@gmail.com> wrote:
> From: Thierry Reding <treding@nvidia.com>
>
> Given a device tree node and a property name, the new fdt_find_string()
> 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>

fdt_stringlist_find() maybe? Will see what happens when you upstream.

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

Regards,
Simon

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

* [U-Boot] [PATCH v2 04/40] fdt: Add functions to retrieve strings
  2014-08-26 15:33 ` [U-Boot] [PATCH v2 04/40] fdt: Add functions to retrieve strings Thierry Reding
@ 2014-08-27 18:53   ` Simon Glass
  2014-09-08 15:02     ` Simon Glass
  0 siblings, 1 reply; 104+ messages in thread
From: Simon Glass @ 2014-08-27 18:53 UTC (permalink / raw)
  To: u-boot

Hi Thierry,

On 26 August 2014 09:33, Thierry Reding <thierry.reding@gmail.com> wrote:
> From: Thierry Reding <treding@nvidia.com>
>
> Given a device tree node, a property name and an index, the new function
> fdt_get_string_index() will return in an output argument a pointer to
> the index'th string in the property's value.
>
> The fdt_get_string() is a shortcut for the above with the index being 0.
>
> Signed-off-by: Thierry Reding <treding@nvidia.com>

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

Could be fdt_stringlist_lookup() maybe. But there's no point guessing
until you send this upstream.

Regards,
Simon

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

* [U-Boot] [PATCH v2 05/40] fdt: Add resource parsing functions
  2014-08-26 15:33 ` [U-Boot] [PATCH v2 05/40] fdt: Add resource parsing functions Thierry Reding
@ 2014-08-27 18:53   ` Simon Glass
  2014-09-08 15:02   ` Simon Glass
  1 sibling, 0 replies; 104+ messages in thread
From: Simon Glass @ 2014-08-27 18:53 UTC (permalink / raw)
  To: u-boot

On 26 August 2014 09:33, 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>

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

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

* [U-Boot] [PATCH v2 32/40] ARM: cache_v7: Various minor cleanups
  2014-08-26 15:34 ` [U-Boot] [PATCH v2 32/40] ARM: cache_v7: Various minor cleanups Thierry Reding
@ 2014-08-27 18:56   ` Simon Glass
  2014-11-08  8:30   ` Albert ARIBAUD
  1 sibling, 0 replies; 104+ messages in thread
From: Simon Glass @ 2014-08-27 18:56 UTC (permalink / raw)
  To: u-boot

On 26 August 2014 09:34, Thierry Reding <thierry.reding@gmail.com> wrote:
> From: Thierry Reding <treding@nvidia.com>
>
> Remove two gratuituous blank lines, uses u32 (instead of int) as the
> type for values that will be written to a register, moves the beginning
> of the variable declaration section to a separate line (rather than the
> one with the opening brace) and keeps the function signature on a single
> line where possible.
>
> Signed-off-by: Thierry Reding <treding@nvidia.com>

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

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

* [U-Boot] [PATCH v2 33/40] ARM: cache-cp15: Use more accurate types
  2014-08-26 15:34 ` [U-Boot] [PATCH v2 33/40] ARM: cache-cp15: Use more accurate types Thierry Reding
@ 2014-08-27 18:57   ` Simon Glass
  2014-11-08  8:31   ` Albert ARIBAUD
  1 sibling, 0 replies; 104+ messages in thread
From: Simon Glass @ 2014-08-27 18:57 UTC (permalink / raw)
  To: u-boot

Hi Thierry,

On 26 August 2014 09:34, Thierry Reding <thierry.reding@gmail.com> wrote:
> From: Thierry Reding <treding@nvidia.com>
>
> size_t is the canonical type to represent variables that contain a size.
> Use it instead of signed integer. Physical addresses can be larger than
> 32-bit, so use a more appropriate type for them as well. phys_addr_t is
> a type that is 32-bit on systems that use 32-bit addresses and 64-bit if
> the system is 64-bit or uses a form of physical address extension to use
> a larger address space on 32-bit systems. Using these types the same API
> can be implemented on a wider range of systems.
>
> Signed-off-by: Thierry Reding <treding@nvidia.com>
> ---
>  arch/arm/include/asm/system.h | 2 +-
>  arch/arm/lib/cache-cp15.c     | 6 +++---
>  2 files changed, 4 insertions(+), 4 deletions(-)
>
> diff --git a/arch/arm/include/asm/system.h b/arch/arm/include/asm/system.h
> index d51ba668f323..fb31a8faf2b1 100644
> --- a/arch/arm/include/asm/system.h
> +++ b/arch/arm/include/asm/system.h
> @@ -200,7 +200,7 @@ enum {
>   * \param size         size of memory region to change
>   * \param option       dcache option to select
>   */
> -void mmu_set_region_dcache_behaviour(u32 start, int size,
> +void mmu_set_region_dcache_behaviour(phys_addr_t start, size_t size,
>                                      enum dcache_option option);
>
>  /**
> diff --git a/arch/arm/lib/cache-cp15.c b/arch/arm/lib/cache-cp15.c
> index 5fdfdbfca541..e6c1c83e5758 100644
> --- a/arch/arm/lib/cache-cp15.c
> +++ b/arch/arm/lib/cache-cp15.c
> @@ -47,15 +47,15 @@ __weak void mmu_page_table_flush(unsigned long start, unsigned long stop)
>         debug("%s: Warning: not implemented\n", __func__);
>  }
>
> -void mmu_set_region_dcache_behaviour(u32 start, int size,
> +void mmu_set_region_dcache_behaviour(phys_addr_t start, size_t size,
>                                      enum dcache_option option)
>  {
>         u32 *page_table = (u32 *)gd->arch.tlb_addr;
> -       u32 upto, end;
> +       unsigned long upto, end;
>
>         end = ALIGN(start + size, MMU_SECTION_SIZE) >> MMU_SECTION_SHIFT;
>         start = start >> MMU_SECTION_SHIFT;
> -       debug("%s: start=%x, size=%x, option=%d\n", __func__, start, size,
> +       debug("%s: start=%pa, size=%zu, option=%d\n", __func__, &start, size,

The &start seems counter-intuitive. Can it not just be 'start'?

>               option);
>         for (upto = start; upto < end; upto++)
>                 set_section_dcache(upto, option);
> --
> 2.0.4
>

Regards,
Simon

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

* [U-Boot] [PATCH v2 34/40] malloc: Output region when debugging
  2014-08-26 15:34 ` [U-Boot] [PATCH v2 34/40] malloc: Output region when debugging Thierry Reding
@ 2014-08-27 18:58   ` Simon Glass
  2014-11-08  8:31   ` Albert ARIBAUD
  1 sibling, 0 replies; 104+ messages in thread
From: Simon Glass @ 2014-08-27 18:58 UTC (permalink / raw)
  To: u-boot

On 26 August 2014 09:34, Thierry Reding <thierry.reding@gmail.com> wrote:
> From: Thierry Reding <treding@nvidia.com>
>
> When DEBUG is set, output memory region used for malloc().
>
> Signed-off-by: Thierry Reding <treding@nvidia.com>
> ---
>  common/dlmalloc.c | 3 +++
>  1 file changed, 3 insertions(+)
>
> diff --git a/common/dlmalloc.c b/common/dlmalloc.c
> index f9873393c183..3d6391e60acf 100644
> --- a/common/dlmalloc.c
> +++ b/common/dlmalloc.c
> @@ -1533,6 +1533,9 @@ void mem_malloc_init(ulong start, ulong size)
>         mem_malloc_end = start + size;
>         mem_malloc_brk = start;
>
> +       debug("using memory %#lx-%#lx for malloc()\n", mem_malloc_start,
> +             mem_malloc_end);

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

> +
>         memset((void *)mem_malloc_start, 0, size);
>
>         malloc_bin_reloc();
> --
> 2.0.4
>

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

* [U-Boot] [PATCH v2 35/40] ARM: Implement non-cached memory support
  2014-08-26 15:34 ` [U-Boot] [PATCH v2 35/40] ARM: Implement non-cached memory support Thierry Reding
@ 2014-08-27 19:07   ` Simon Glass
  2014-10-24 19:11   ` Stephen Warren
  1 sibling, 0 replies; 104+ messages in thread
From: Simon Glass @ 2014-08-27 19:07 UTC (permalink / raw)
  To: u-boot

Hi Thierry,

On 26 August 2014 09:34, Thierry Reding <thierry.reding@gmail.com> wrote:
> From: Thierry Reding <treding@nvidia.com>
>
> Implement an API that can be used by drivers to allocate memory from a
> pool that is mapped uncached. This is useful if drivers would otherwise
> need to do extensive cache maintenance (or explicitly maintaining the
> cache isn't safe).
>
> The API is protected using the new CONFIG_SYS_NONCACHED_MEMORY setting.
> Boards can set this to the size to be used for the non-cached area. The
> area will typically be right below the malloc() area, but architectures
> should take care of aligning the beginning and end of the area to honor
> any mapping restrictions. Architectures must also ensure that mappings
> established for this area do not overlap with the malloc() area (which
> should remain cached for improved performance).
>
> While the API is currently only implemented for ARM v7, it should be
> generic enough to allow other architectures to implement it as well.
>
> Signed-off-by: Thierry Reding <treding@nvidia.com>
> ---
> Changes in v2:
> - avoid overflow when checking for available space
>
>  README                        | 19 +++++++++++++++++++
>  arch/arm/include/asm/system.h |  5 +++++
>  arch/arm/lib/cache.c          | 42 ++++++++++++++++++++++++++++++++++++++++++
>  common/board_r.c              | 11 +++++++++++
>  4 files changed, 77 insertions(+)
>
> diff --git a/README b/README
> index 1d713596ec6f..526e06edb52c 100644
> --- a/README
> +++ b/README
> @@ -3759,6 +3759,25 @@ Configuration Settings:
>                 Pre-relocation malloc() is only supported on ARM at present
>                 but is fairly easy to enable for other archs.
>
> +- CONFIG_SYS_NONCACHED_MEMORY:
> +               Size of non-cached memory area. This area of memory will be
> +               typically located right below the malloc() area and mapped
> +               uncached in the MMU. This is useful for drivers that would
> +               otherwise require a lot of explicit cache maintenance. For
> +               some drivers it's also impossible to properly maintain the
> +               cache. For example if the regions that need to be flushed
> +               are not a multiple of the cache-line size, *and* padding
> +               cannot be allocated between the regions to align them (i.e.
> +               if the HW requires a contiguous array of regions, and the
> +               size of each region is not cache-aligned), then a flush of
> +               one region may result in overwriting data that hardware has
> +               written to another region in the same cache-line. This can
> +               happen for example in network drivers where descriptors for
> +               buffers are typically smaller than the CPU cache-line (e.g.
> +               16 bytes vs. 32 or 64 bytes).
> +
> +               Non-cached memory is only supported on 32-bit ARM at present.

Is this better than allocating 1MB with memalign() and then changing
the MMU settings with something like set_section_dcache()?

> +
>  - CONFIG_SYS_BOOTM_LEN:
>                 Normally compressed uImages are limited to an
>                 uncompressed size of 8 MBytes. If this is not enough,
> diff --git a/arch/arm/include/asm/system.h b/arch/arm/include/asm/system.h
> index fb31a8faf2b1..fb1bc0699a56 100644
> --- a/arch/arm/include/asm/system.h
> +++ b/arch/arm/include/asm/system.h
> @@ -211,6 +211,11 @@ void mmu_set_region_dcache_behaviour(phys_addr_t start, size_t size,
>   */
>  void mmu_page_table_flush(unsigned long start, unsigned long stop);
>
> +#ifdef CONFIG_SYS_NONCACHED_MEMORY
> +void noncached_init(void);
> +phys_addr_t noncached_alloc(size_t size, size_t align);
> +#endif /* CONFIG_SYS_NONCACHED_MEMORY */
> +
>  #endif /* __ASSEMBLY__ */
>
>  #define arch_align_stack(x) (x)
> diff --git a/arch/arm/lib/cache.c b/arch/arm/lib/cache.c
> index 4e597a4c1d16..b2aa7740d4f8 100644
> --- a/arch/arm/lib/cache.c
> +++ b/arch/arm/lib/cache.c
> @@ -8,6 +8,7 @@
>  /* for now: just dummy functions to satisfy the linker */
>
>  #include <common.h>
> +#include <malloc.h>
>
>  __weak void flush_cache(unsigned long start, unsigned long size)
>  {
> @@ -49,3 +50,44 @@ __weak void enable_caches(void)
>  {
>         puts("WARNING: Caches not enabled\n");
>  }
> +
> +#ifdef CONFIG_SYS_NONCACHED_MEMORY
> +/*
> + * Reserve one MMU section worth of address space below the malloc() area that
> + * will be mapped uncached.

It looks like it can be >1 section.

> + */
> +static unsigned long noncached_start;
> +static unsigned long noncached_end;
> +static unsigned long noncached_next;

You can use ulong if you like.

> +
> +void noncached_init(void)
> +{
> +       phys_addr_t start, end;
> +       size_t size;
> +
> +       end = ALIGN(mem_malloc_start, MMU_SECTION_SIZE) - MMU_SECTION_SIZE;
> +       size = ALIGN(CONFIG_SYS_NONCACHED_MEMORY, MMU_SECTION_SIZE);
> +       start = end - size;
> +
> +       debug("mapping memory %pa-%pa non-cached\n", &start, &end);
> +
> +       noncached_start = start;
> +       noncached_end = end;
> +       noncached_next = start;
> +
> +       mmu_set_region_dcache_behaviour(noncached_start, size, DCACHE_OFF);
> +}
> +
> +phys_addr_t noncached_alloc(size_t size, size_t align)
> +{
> +       phys_addr_t next = ALIGN(noncached_next, align);
> +
> +       if (next >= noncached_end || (noncached_end - next) < size)
> +               return 0;
> +
> +       debug("allocated %zu bytes of uncached memory @%pa\n", size, &next);
> +       noncached_next = next + size;

Should this be aligned? I suspect it doesn't matter, and you do it
anyway on the next call.

> +
> +       return next;
> +}
> +#endif /* CONFIG_SYS_NONCACHED_MEMORY */
> diff --git a/common/board_r.c b/common/board_r.c
> index ba9a68dc6691..6b8e62bf032b 100644
> --- a/common/board_r.c
> +++ b/common/board_r.c
> @@ -270,6 +270,14 @@ static int initr_malloc(void)
>         return 0;
>  }
>
> +#ifdef CONFIG_SYS_NONCACHED_MEMORY
> +static int initr_noncached(void)
> +{
> +       noncached_init();

Could you make this function return 0 to avoid needing this helper?

> +       return 0;
> +}
> +#endif
> +
>  #ifdef CONFIG_DM
>  static int initr_dm(void)
>  {
> @@ -765,6 +773,9 @@ init_fnc_t init_sequence_r[] = {
>  #endif
>         initr_barrier,
>         initr_malloc,
> +#ifdef CONFIG_SYS_NONCACHED_MEMORY
> +       initr_noncached,
> +#endif
>         bootstage_relocate,
>  #ifdef CONFIG_DM
>         initr_dm,
> --
> 2.0.4
>

Regards,
Simon

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

* [U-Boot] [PATCH v2 13/40] i2c: Add high-level API
  2014-08-27 11:41             ` Thierry Reding
@ 2014-08-27 19:10               ` Simon Glass
  2014-08-28  9:53                 ` Heiko Schocher
  0 siblings, 1 reply; 104+ messages in thread
From: Simon Glass @ 2014-08-27 19:10 UTC (permalink / raw)
  To: u-boot

Hi Thierry,

On 27 August 2014 05:41, Thierry Reding <thierry.reding@gmail.com> wrote:
> On Wed, Aug 27, 2014 at 11:56:41AM +0200, Heiko Schocher wrote:
>> Hello Thierry,
>>
>> Am 27.08.2014 10:51, schrieb Thierry Reding:
>> >On Wed, Aug 27, 2014 at 09:07:58AM +0200, Heiko Schocher wrote:
>> >>Hello Thierry,
>> >>
>> >>Am 27.08.2014 08:21, schrieb Thierry Reding:
>> >>>On Wed, Aug 27, 2014 at 07:21:51AM +0200, Heiko Schocher wrote:
>> >>>>Hello Thierry,
>> >>>>
>> >>>>Am 26.08.2014 17:34, schrieb Thierry Reding:
>> >>>>>From: Thierry Reding<treding@nvidia.com>
>> >>>>>
>> >>>>>This API operates on I2C adapters or I2C clients (a new type of object
>> >>>>
>> >>>>which is a bad idea ...
>> >>>>
>> >>>>>that refers to a particular slave connected to an adapter). This is
>> >>>>>useful to avoid having to call i2c_set_bus_num() whenever a device is
>> >>>>>being accessed.
>> >>>>
>> >>>>But thats the supose of i2c_set_bus_num()! ... if you use an i2c bus,
>> >>>>you must check before every access, if you are on it, if not, you must
>> >>>>switch back to it...
>> >>>
>> >>>That's not what code does today. Everybody calls i2c_set_bus_num() once
>> >>>and then does a bunch of transactions on that bus. Given that U-Boot
>> >>
>> >>Yes, sadly. This has historical reasons ...
>> >>
>> >>>doesn't run multithreaded this works. If you're really concerned about
>> >>
>> >>Yes, U-Boot is singlethread only.
>> >>
>> >>>this being a problem, then it should be solved at a different level. It
>> >>>could be part of i2c_client for example, so that i2c_client_read() and
>> >>>i2c_client_write() would always perform this step. Burdening users with
>> >>
>> >>Exactly, thats right, and this is a goal from the CONFIG_SYS_I2C API!
>> >>
>> >>But why do you introduce i2c_client_read/write and do not add this step
>> >>to i2c_read/write?
>> >>
>> >>- convert all i2c drivers, which are not yet converted to CONFIG_SYS_I2C
>> >>   (get also rid od CONFIG_HARD_I2C)
>> >>- add busnumber to i2c_read/write API and make i2c_set_bus_num() static ...
>> >>   and fix all i2c_read/write() calls in U-Boot code ...
>> >
>> >I don't think adding a bus number as parameter is useful. Why not just
>> >use the I2C adapter directly? That way we don't have to keep looking it
>> >up in an array every time.
>>
>> You again just talk from i2c_adapter ... why you ignore i2c muxes?
>> A bus is not only an i2c adapter ...
>
> I know. I keep saying i2c_adapter because in the rough sketch that I
> have in mind for how this could work eventually, an mux is just another
> special kind of i2c_adapter.
>
>> Currently we have two "versions" of i2c_adapter:
>>
>> In a system without muxes, you can say: i2c bus == i2c adapter
>> but in a system with muxes we have:     i2c bus == i2c_bus_hose
>>
>> i2c commands use also a "bus number" starting from 0 ... the bus number
>> has historical reasons... we could change this ...
>>
>> But if we introduce a new API, please with mux functionallity ...
>> Hmm.. thinking about it ... if you want to introduce a new API, please
>> start with using the DM for I2C!
>
> I can look into it, but it sounds like a task way beyond what I have
> time for right now.
>

I can help if you are interested. I have patches for SPI at
u-boot-dm.git (branch working) and would like to have I2C. They are
sort-of similar so it might not be to hard to convert Tegra I2C over.

The concept of a 'current' bus is broken IMO. Maybe the command line
should have this concept, and maintain a 'current hose' or whatever.
But drives and other code should specific what they need with each
transaction. With DM that will likely be automatic.

Regards,
Simon

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

* [U-Boot] [PATCH v2 13/40] i2c: Add high-level API
  2014-08-27 19:10               ` Simon Glass
@ 2014-08-28  9:53                 ` Heiko Schocher
  0 siblings, 0 replies; 104+ messages in thread
From: Heiko Schocher @ 2014-08-28  9:53 UTC (permalink / raw)
  To: u-boot

Hello Simon,

Am 27.08.2014 21:10, schrieb Simon Glass:
> Hi Thierry,
>
> On 27 August 2014 05:41, Thierry Reding<thierry.reding@gmail.com>  wrote:
>> On Wed, Aug 27, 2014 at 11:56:41AM +0200, Heiko Schocher wrote:
>>> Hello Thierry,
>>>
>>> Am 27.08.2014 10:51, schrieb Thierry Reding:
>>>> On Wed, Aug 27, 2014 at 09:07:58AM +0200, Heiko Schocher wrote:
>>>>> Hello Thierry,
>>>>>
>>>>> Am 27.08.2014 08:21, schrieb Thierry Reding:
>>>>>> On Wed, Aug 27, 2014 at 07:21:51AM +0200, Heiko Schocher wrote:
>>>>>>> Hello Thierry,
>>>>>>>
>>>>>>> Am 26.08.2014 17:34, schrieb Thierry Reding:
>>>>>>>> From: Thierry Reding<treding@nvidia.com>
>>>>>>>>
>>>>>>>> This API operates on I2C adapters or I2C clients (a new type of object
>>>>>>>
>>>>>>> which is a bad idea ...
>>>>>>>
>>>>>>>> that refers to a particular slave connected to an adapter). This is
>>>>>>>> useful to avoid having to call i2c_set_bus_num() whenever a device is
>>>>>>>> being accessed.
>>>>>>>
>>>>>>> But thats the supose of i2c_set_bus_num()! ... if you use an i2c bus,
>>>>>>> you must check before every access, if you are on it, if not, you must
>>>>>>> switch back to it...
>>>>>>
>>>>>> That's not what code does today. Everybody calls i2c_set_bus_num() once
>>>>>> and then does a bunch of transactions on that bus. Given that U-Boot
>>>>>
>>>>> Yes, sadly. This has historical reasons ...
>>>>>
>>>>>> doesn't run multithreaded this works. If you're really concerned about
>>>>>
>>>>> Yes, U-Boot is singlethread only.
>>>>>
>>>>>> this being a problem, then it should be solved at a different level. It
>>>>>> could be part of i2c_client for example, so that i2c_client_read() and
>>>>>> i2c_client_write() would always perform this step. Burdening users with
>>>>>
>>>>> Exactly, thats right, and this is a goal from the CONFIG_SYS_I2C API!
>>>>>
>>>>> But why do you introduce i2c_client_read/write and do not add this step
>>>>> to i2c_read/write?
>>>>>
>>>>> - convert all i2c drivers, which are not yet converted to CONFIG_SYS_I2C
>>>>>    (get also rid od CONFIG_HARD_I2C)
>>>>> - add busnumber to i2c_read/write API and make i2c_set_bus_num() static ...
>>>>>    and fix all i2c_read/write() calls in U-Boot code ...
>>>>
>>>> I don't think adding a bus number as parameter is useful. Why not just
>>>> use the I2C adapter directly? That way we don't have to keep looking it
>>>> up in an array every time.
>>>
>>> You again just talk from i2c_adapter ... why you ignore i2c muxes?
>>> A bus is not only an i2c adapter ...
>>
>> I know. I keep saying i2c_adapter because in the rough sketch that I
>> have in mind for how this could work eventually, an mux is just another
>> special kind of i2c_adapter.
>>
>>> Currently we have two "versions" of i2c_adapter:
>>>
>>> In a system without muxes, you can say: i2c bus == i2c adapter
>>> but in a system with muxes we have:     i2c bus == i2c_bus_hose
>>>
>>> i2c commands use also a "bus number" starting from 0 ... the bus number
>>> has historical reasons... we could change this ...
>>>
>>> But if we introduce a new API, please with mux functionallity ...
>>> Hmm.. thinking about it ... if you want to introduce a new API, please
>>> start with using the DM for I2C!
>>
>> I can look into it, but it sounds like a task way beyond what I have
>> time for right now.
>>
>
> I can help if you are interested. I have patches for SPI at
> u-boot-dm.git (branch working) and would like to have I2C. They are
> sort-of similar so it might not be to hard to convert Tegra I2C over.
>
> The concept of a 'current' bus is broken IMO. Maybe the command line
> should have this concept, and maintain a 'current hose' or whatever.
> But drives and other code should specific what they need with each
> transaction. With DM that will likely be automatic.

That sounds great! I vote for using DM.

bye,
Heiko
-- 
DENX Software Engineering GmbH,     MD: Wolfgang Denk & Detlev Zundel
HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany

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

* [U-Boot] [PATCH v2 01/40] vsprintf: Add modifier for phys_addr_t
  2014-08-27 17:41       ` Stephen Warren
@ 2014-08-28 10:38         ` Thierry Reding
  2014-09-17  0:44           ` [U-Boot] [U-Boot, v2, " Tom Rini
  0 siblings, 1 reply; 104+ messages in thread
From: Thierry Reding @ 2014-08-28 10:38 UTC (permalink / raw)
  To: u-boot

On Wed, Aug 27, 2014 at 11:41:55AM -0600, Stephen Warren wrote:
> On 08/27/2014 01:01 AM, Thierry Reding wrote:
> >On Tue, Aug 26, 2014 at 11:04:56AM -0600, Stephen Warren wrote:
> >>On 08/26/2014 09:33 AM, Thierry Reding wrote:
> >>>From: Thierry Reding <treding@nvidia.com>
> >>>
> >>>Provide a new modifier to vsprintf() to print phys_addr_t variables to
> >>>avoid having to cast or #ifdef when printing them out. The %pa modifier
> >>>is used for this purpose, so phys_addr_t variables need to be passed by
> >>>reference, like so:
> >>>
> >>>	phys_addr_t start = 0;
> >>>
> >>>	printf("start: %pa\n", &start);
> >>>
> >>>Depending on the size of phys_addr_t this will print out the address
> >>>with 8 or 16 hexadecimal digits following a 0x prefix.
> >>
> >>The series,
> >>
> >>Tested-by: Stephen Warren <swarren@nvidia.com>
> >>
> >>Note that I did see the following printed a couple of times when I executed
> >>"run bootcmd_pxe":
> >>
> >>pci_hose_bus_to_phys: invalid physical address
> >>
> >>... but everything worked perfectly, so I guess we can track that down
> >>later.
> >
> >Yes, it should definitely be tracked down. I don't see that message on
> >my setup. I've seen it for example when noncached_alloc() fails and
> >returns 0, but in that case everything shouldn't be working perfectly.
> 
> It looks like it happens when "dhcp" or "pxe get" attempt to download a file
> that doesn't exist on the server.
> 
> >It would be helpful if that message showed what physical address was
> >considered invalid.
> 
> The address is 0. I think this is because rtl_recv() is being called after
> rtl_halt(). rtl_halt() NULLs out all tpc->RxBufferRing[] entries, so calling
> rtl_recv() after that tries to convert address 0 to a PCI address. I haven't
> fully tracked this down, but it seems like a bug in the U-Boot networking or
> TFTP core, rather than anything to do with drivers for R8169 or the Tegra
> PCIe controller.
> 
> I'm not planning on tracking this down any further at the moment.

The attached patch fixes this issue for me. Cc'ing Joe to help figure
out if that's the right approach.

Thierry
-------------- next part --------------
A non-text attachment was scrubbed...
Name: 0001-rtl8169-Defer-network-packet-processing.patch
Type: text/x-diff
Size: 1764 bytes
Desc: not available
URL: <http://lists.denx.de/pipermail/u-boot/attachments/20140828/bedb2512/attachment.patch>
-------------- 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/20140828/bedb2512/attachment.pgp>

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

* [U-Boot] [PATCH v2 14/40] i2c: tegra: Implement i2c_get_bus_num_fdt()
  2014-08-26 15:34 ` [U-Boot] [PATCH v2 14/40] i2c: tegra: Implement i2c_get_bus_num_fdt() Thierry Reding
@ 2014-09-02 19:24   ` Simon Glass
  0 siblings, 0 replies; 104+ messages in thread
From: Simon Glass @ 2014-09-02 19:24 UTC (permalink / raw)
  To: u-boot

On 26 August 2014 09:34, Thierry Reding <thierry.reding@gmail.com> wrote:
> From: Thierry Reding <treding@nvidia.com>
>
> This is useful to retrieve the U-Boot bus number of an I2C controller
> given a device tree node.
>
> Signed-off-by: Thierry Reding <treding@nvidia.com>

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

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

* [U-Boot] [PATCH v2 02/40] fdt: Add a function to count strings
  2014-08-27 18:51   ` Simon Glass
@ 2014-09-08 15:01     ` Simon Glass
  0 siblings, 0 replies; 104+ messages in thread
From: Simon Glass @ 2014-09-08 15:01 UTC (permalink / raw)
  To: u-boot

Applied to u-boot-fdt/next, thanks!

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

* [U-Boot] [PATCH v2 03/40] fdt: Add a function to get the index of a string
  2014-08-27 18:51   ` Simon Glass
@ 2014-09-08 15:02     ` Simon Glass
  0 siblings, 0 replies; 104+ messages in thread
From: Simon Glass @ 2014-09-08 15:02 UTC (permalink / raw)
  To: u-boot

Applied to u-boot-fdt/next, thanks!

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

* [U-Boot] [PATCH v2 04/40] fdt: Add functions to retrieve strings
  2014-08-27 18:53   ` Simon Glass
@ 2014-09-08 15:02     ` Simon Glass
  2015-03-25 23:23       ` Simon Glass
  0 siblings, 1 reply; 104+ messages in thread
From: Simon Glass @ 2014-09-08 15:02 UTC (permalink / raw)
  To: u-boot

Applied to u-boot-fdt/next, thanks!

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

* [U-Boot] [PATCH v2 05/40] fdt: Add resource parsing functions
  2014-08-26 15:33 ` [U-Boot] [PATCH v2 05/40] fdt: Add resource parsing functions Thierry Reding
  2014-08-27 18:53   ` Simon Glass
@ 2014-09-08 15:02   ` Simon Glass
  1 sibling, 0 replies; 104+ messages in thread
From: Simon Glass @ 2014-09-08 15:02 UTC (permalink / raw)
  To: u-boot

Applied to u-boot-fdt/next, thanks!

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

* [U-Boot] [PATCH v2 06/40] fdt: Add a function to return PCI BDF triplet
  2014-08-26 15:33 ` [U-Boot] [PATCH v2 06/40] fdt: Add a function to return PCI BDF triplet Thierry Reding
@ 2014-09-08 15:03   ` Simon Glass
  0 siblings, 0 replies; 104+ messages in thread
From: Simon Glass @ 2014-09-08 15:03 UTC (permalink / raw)
  To: u-boot

Applied to u-boot-fdt/next, thanks!

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

* [U-Boot] [PATCH v2 07/40] fdt: Add a subnodes iterator macro
  2014-08-26 15:33 ` [U-Boot] [PATCH v2 07/40] fdt: Add a subnodes iterator macro Thierry Reding
@ 2014-09-08 15:03   ` Simon Glass
  0 siblings, 0 replies; 104+ messages in thread
From: Simon Glass @ 2014-09-08 15:03 UTC (permalink / raw)
  To: u-boot

Applied to u-boot-fdt/next, thanks!

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

* [U-Boot] [PATCH v2 00/40] ARM: tegra: Add PCIe support
  2014-08-26 15:33 [U-Boot] [PATCH v2 00/40] ARM: tegra: Add PCIe support Thierry Reding
                   ` (39 preceding siblings ...)
  2014-08-26 15:34 ` [U-Boot] [PATCH v2 40/40] net: rtl8169: Add support for RTL-8168/8111g Thierry Reding
@ 2014-09-11 16:00 ` Albert ARIBAUD
  2014-09-11 16:17   ` Stephen Warren
  2014-10-23  3:07   ` Simon Glass
  2014-09-28 22:48 ` Simon Glass
  2014-10-26 19:07 ` Albert ARIBAUD
  42 siblings, 2 replies; 104+ messages in thread
From: Albert ARIBAUD @ 2014-09-11 16:00 UTC (permalink / raw)
  To: u-boot

Hi Thierry,

On Tue, 26 Aug 2014 17:33:48 +0200, Thierry Reding
<thierry.reding@gmail.com> wrote:

> From: Thierry Reding <treding@nvidia.com>

Note: this series was split over several custodians (including myself).
It might thus get applied piecewise... Shouldn't it rather be assigned
a single custodian -with others giving their Ack) and be applied as a
whole? And yes, I'm ok with getting all the pieces.

Amicalement,
-- 
Albert.

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

* [U-Boot] [PATCH v2 00/40] ARM: tegra: Add PCIe support
  2014-09-11 16:00 ` [U-Boot] [PATCH v2 00/40] ARM: tegra: Add PCIe support Albert ARIBAUD
@ 2014-09-11 16:17   ` Stephen Warren
  2014-09-11 19:20     ` Simon Glass
  2014-10-23  3:07   ` Simon Glass
  1 sibling, 1 reply; 104+ messages in thread
From: Stephen Warren @ 2014-09-11 16:17 UTC (permalink / raw)
  To: u-boot

On 09/11/2014 10:00 AM, Albert ARIBAUD wrote:
> Hi Thierry,
>
> On Tue, 26 Aug 2014 17:33:48 +0200, Thierry Reding
> <thierry.reding@gmail.com> wrote:
>
>> From: Thierry Reding <treding@nvidia.com>
>
> Note: this series was split over several custodians (including myself).
> It might thus get applied piecewise... Shouldn't it rather be assigned
> a single custodian -with others giving their Ack) and be applied as a
> whole? And yes, I'm ok with getting all the pieces.

Yes, applying it all in one place would probably make sense.

IIRC, Simon Glass already applied some of the DT patches early in the 
series? I CC'd him to check,

BTW, Thierry is on vacation at the moment, so I don't expect he'll respond.

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

* [U-Boot] [PATCH v2 00/40] ARM: tegra: Add PCIe support
  2014-09-11 16:17   ` Stephen Warren
@ 2014-09-11 19:20     ` Simon Glass
  2014-09-18  8:43       ` Albert ARIBAUD
  0 siblings, 1 reply; 104+ messages in thread
From: Simon Glass @ 2014-09-11 19:20 UTC (permalink / raw)
  To: u-boot

Hi,

On 11 September 2014 10:17, Stephen Warren <swarren@wwwdotorg.org> wrote:
> On 09/11/2014 10:00 AM, Albert ARIBAUD wrote:
>>
>> Hi Thierry,
>>
>> On Tue, 26 Aug 2014 17:33:48 +0200, Thierry Reding
>> <thierry.reding@gmail.com> wrote:
>>
>>> From: Thierry Reding <treding@nvidia.com>
>>
>>
>> Note: this series was split over several custodians (including myself).
>> It might thus get applied piecewise... Shouldn't it rather be assigned
>> a single custodian -with others giving their Ack) and be applied as a
>> whole? And yes, I'm ok with getting all the pieces.
>
>
> Yes, applying it all in one place would probably make sense.
>
> IIRC, Simon Glass already applied some of the DT patches early in the
> series? I CC'd him to check,

Yes I applied the fdt patches to u-boot-fdt/next. I can do a pull
request to ARM if that helps, or you can just grab them.

>
> BTW, Thierry is on vacation at the moment, so I don't expect he'll respond.

Regards,
Simon

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

* [U-Boot] [U-Boot, v2, 01/40] vsprintf: Add modifier for phys_addr_t
  2014-08-28 10:38         ` Thierry Reding
@ 2014-09-17  0:44           ` Tom Rini
  0 siblings, 0 replies; 104+ messages in thread
From: Tom Rini @ 2014-09-17  0:44 UTC (permalink / raw)
  To: u-boot

> From: Thierry Reding <treding@nvidia.com>
> Date: Thu, 28 Aug 2014 12:26:58 +0200
> Subject: [PATCH] rtl8169: Defer network packet processing
> 
> When network protocol errors occur (such as a file not being found on a
> TFTP server), the processing done by the NetReceive() function will end
> up calling the driver's .halt() implementation. However, after that the
> device no longer has access to the memory buffers and will cause errors
> such as this in the rtl_recv() function when trying to hand descriptors
> back to the device:
> 
> 	pci_hose_bus_to_phys: invalid physical address
> 
> This can be fixed by deferring processing of network packets until the
> descriptors have been handed back. That way rtl_halt() tearing down
> network buffers is not going to prevent access to the buffers.
> 
> Reported-by: Stephen Warren <swarren@nvidia.com>
> Signed-off-by: Thierry Reding <treding@nvidia.com>

Applied to u-boot/master, thanks!

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

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

* [U-Boot] [PATCH v2 00/40] ARM: tegra: Add PCIe support
  2014-09-11 19:20     ` Simon Glass
@ 2014-09-18  8:43       ` Albert ARIBAUD
  2014-09-18 18:01         ` Simon Glass
  0 siblings, 1 reply; 104+ messages in thread
From: Albert ARIBAUD @ 2014-09-18  8:43 UTC (permalink / raw)
  To: u-boot

Hi Simon,

On Thu, 11 Sep 2014 13:20:03 -0600, Simon Glass <sjg@chromium.org>
wrote:

> Hi,
> 
> On 11 September 2014 10:17, Stephen Warren <swarren@wwwdotorg.org> wrote:
> > On 09/11/2014 10:00 AM, Albert ARIBAUD wrote:
> >>
> >> Hi Thierry,
> >>
> >> On Tue, 26 Aug 2014 17:33:48 +0200, Thierry Reding
> >> <thierry.reding@gmail.com> wrote:
> >>
> >>> From: Thierry Reding <treding@nvidia.com>
> >>
> >>
> >> Note: this series was split over several custodians (including myself).
> >> It might thus get applied piecewise... Shouldn't it rather be assigned
> >> a single custodian -with others giving their Ack) and be applied as a
> >> whole? And yes, I'm ok with getting all the pieces.
> >
> >
> > Yes, applying it all in one place would probably make sense.
> >
> > IIRC, Simon Glass already applied some of the DT patches early in the
> > series? I CC'd him to check,
> 
> Yes I applied the fdt patches to u-boot-fdt/next. I can do a pull
> request to ARM if that helps, or you can just grab them.

Well, the idea was applying it all in one place :) and I don't like the
idea of pulling the fdt tree into the arm tree, so I'll pick them up,
but please give your Acked-by to them, so that PW sees it and puts it in
when I apply the patches.
  
> > BTW, Thierry is on vacation at the moment, so I don't expect he'll respond.
> 
> Regards,
> Simon

Amicalement,
-- 
Albert.

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

* [U-Boot] [PATCH v2 00/40] ARM: tegra: Add PCIe support
  2014-09-18  8:43       ` Albert ARIBAUD
@ 2014-09-18 18:01         ` Simon Glass
  0 siblings, 0 replies; 104+ messages in thread
From: Simon Glass @ 2014-09-18 18:01 UTC (permalink / raw)
  To: u-boot

HI Albert,

On 18 September 2014 02:43, Albert ARIBAUD <albert.u.boot@aribaud.net>
wrote:

> Hi Simon,
>
> On Thu, 11 Sep 2014 13:20:03 -0600, Simon Glass <sjg@chromium.org>
> wrote:
>
> > Hi,
> >
> > On 11 September 2014 10:17, Stephen Warren <swarren@wwwdotorg.org>
> wrote:
> > > On 09/11/2014 10:00 AM, Albert ARIBAUD wrote:
> > >>
> > >> Hi Thierry,
> > >>
> > >> On Tue, 26 Aug 2014 17:33:48 +0200, Thierry Reding
> > >> <thierry.reding@gmail.com> wrote:
> > >>
> > >>> From: Thierry Reding <treding@nvidia.com>
> > >>
> > >>
> > >> Note: this series was split over several custodians (including
> myself).
> > >> It might thus get applied piecewise... Shouldn't it rather be assigned
> > >> a single custodian -with others giving their Ack) and be applied as a
> > >> whole? And yes, I'm ok with getting all the pieces.
> > >
> > >
> > > Yes, applying it all in one place would probably make sense.
> > >
> > > IIRC, Simon Glass already applied some of the DT patches early in the
> > > series? I CC'd him to check,
> >
> > Yes I applied the fdt patches to u-boot-fdt/next. I can do a pull
> > request to ARM if that helps, or you can just grab them.
>
> Well, the idea was applying it all in one place :) and I don't like the
> idea of pulling the fdt tree into the arm tree, so I'll pick them up,
> but please give your Acked-by to them, so that PW sees it and puts it in
> when I apply the patches.
>

They should all be acked already (I did that before I pulled them in) so
please go ahead.

Regards,
Simon

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

* [U-Boot] [PATCH v2 00/40] ARM: tegra: Add PCIe support
  2014-08-26 15:33 [U-Boot] [PATCH v2 00/40] ARM: tegra: Add PCIe support Thierry Reding
                   ` (40 preceding siblings ...)
  2014-09-11 16:00 ` [U-Boot] [PATCH v2 00/40] ARM: tegra: Add PCIe support Albert ARIBAUD
@ 2014-09-28 22:48 ` Simon Glass
  2014-09-29  8:11   ` Thierry Reding
  2014-10-26 19:07 ` Albert ARIBAUD
  42 siblings, 1 reply; 104+ messages in thread
From: Simon Glass @ 2014-09-28 22:48 UTC (permalink / raw)
  To: u-boot

Hi Thierry,

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

> 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). In this version I've
> included
> all patches that were previously split into three separate series.
> Spreading
> them over multiple series is probably not worth it since there might be
> some
> dependencies between them and only the end result gives a completely
> working
> setup.
>

FYI I have applied this series on top of driver model - it is at
u-boot-dm.git branch 'norrin-working'. There were a quite few conflicts
which I resolved (mostly with mainline I think). I tested it on beaver,
trimslice and jetson-tk1.

Are you going to respin it?

Regards,
Simon

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

* [U-Boot] [PATCH v2 00/40] ARM: tegra: Add PCIe support
  2014-09-28 22:48 ` Simon Glass
@ 2014-09-29  8:11   ` Thierry Reding
  2014-09-29 13:54     ` Simon Glass
  2014-10-06 12:24     ` Heiko Schocher
  0 siblings, 2 replies; 104+ messages in thread
From: Thierry Reding @ 2014-09-29  8:11 UTC (permalink / raw)
  To: u-boot

On Sun, Sep 28, 2014 at 04:48:47PM -0600, Simon Glass wrote:
> Hi Thierry,
> 
> On 26 August 2014 09:33, Thierry Reding <thierry.reding@gmail.com> wrote:
> 
> > 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). In this version I've
> > included
> > all patches that were previously split into three separate series.
> > Spreading
> > them over multiple series is probably not worth it since there might be
> > some
> > dependencies between them and only the end result gives a completely
> > working
> > setup.
> >
> 
> FYI I have applied this series on top of driver model - it is at
> u-boot-dm.git branch 'norrin-working'. There were a quite few conflicts
> which I resolved (mostly with mainline I think). I tested it on beaver,
> trimslice and jetson-tk1.
> 
> Are you going to respin it?

I started looking at DM for I2C as Heiko suggested but it became too
complex and time consuming, so what I'm planning to do is drop the I2C
"enhancements" and use plain i2c_set_bus_num() and friends.

If there's any interest I can push a branch with the work-in-progress
I2C DM patches, perhaps it could serve as the basis if someone else
wanted to continue with that effort.

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/20140929/ae2df0c2/attachment.pgp>

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

* [U-Boot] [PATCH v2 00/40] ARM: tegra: Add PCIe support
  2014-09-29  8:11   ` Thierry Reding
@ 2014-09-29 13:54     ` Simon Glass
  2014-10-06 12:24     ` Heiko Schocher
  1 sibling, 0 replies; 104+ messages in thread
From: Simon Glass @ 2014-09-29 13:54 UTC (permalink / raw)
  To: u-boot

Hi Thierry,

On 29 September 2014 02:11, Thierry Reding <thierry.reding@gmail.com> wrote:

> On Sun, Sep 28, 2014 at 04:48:47PM -0600, Simon Glass wrote:
> > Hi Thierry,
> >
> > On 26 August 2014 09:33, Thierry Reding <thierry.reding@gmail.com>
> wrote:
> >
> > > 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). In this version I've
> > > included
> > > all patches that were previously split into three separate series.
> > > Spreading
> > > them over multiple series is probably not worth it since there might be
> > > some
> > > dependencies between them and only the end result gives a completely
> > > working
> > > setup.
> > >
> >
> > FYI I have applied this series on top of driver model - it is at
> > u-boot-dm.git branch 'norrin-working'. There were a quite few conflicts
> > which I resolved (mostly with mainline I think). I tested it on beaver,
> > trimslice and jetson-tk1.
> >
> > Are you going to respin it?
>
> I started looking at DM for I2C as Heiko suggested but it became too
> complex and time consuming, so what I'm planning to do is drop the I2C
> "enhancements" and use plain i2c_set_bus_num() and friends.
>

OK. I looked at the series and you should really be using the pmic
framework. I've pushed a branch to 'dm/norrin-working' that changes it (see
the as3722 patch near the top). See tps65090 for an example. It should
avoid any messing with I2C. Then, when the new PMIC framework rolls out
your code will ride along for free. Plus you can drop the i2c additions
that way.

Also, there is a clock function that seems to bash various registers -
tegra_plle_enable. I think this should use clock_set_rate() - i.e. build in
support for the new clock rather than creating a parallel function.

The power gate stuff looks good. Are you planning to replace the power gate
code in arch/arm/cpu/arm720t/tegra124/cpu.c and the like? The only minor
issue I see is the availability of get_timer() - but in
tegra_powergate_set() 25ms seems like a very long delay to me anyway.


> If there's any interest I can push a branch with the work-in-progress
> I2C DM patches, perhaps it could serve as the basis if someone else
> wanted to continue with that effort.
>

Yes I think that would be useful.

Regards,
Simon

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

* [U-Boot] [PATCH v2 00/40] ARM: tegra: Add PCIe support
  2014-09-29  8:11   ` Thierry Reding
  2014-09-29 13:54     ` Simon Glass
@ 2014-10-06 12:24     ` Heiko Schocher
  1 sibling, 0 replies; 104+ messages in thread
From: Heiko Schocher @ 2014-10-06 12:24 UTC (permalink / raw)
  To: u-boot

Hello Thierry,

Am 29.09.2014 10:11, schrieb Thierry Reding:
> On Sun, Sep 28, 2014 at 04:48:47PM -0600, Simon Glass wrote:
>> Hi Thierry,
>>
>> On 26 August 2014 09:33, Thierry Reding<thierry.reding@gmail.com>  wrote:
>>
>>> 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). In this version I've
>>> included
>>> all patches that were previously split into three separate series.
>>> Spreading
>>> them over multiple series is probably not worth it since there might be
>>> some
>>> dependencies between them and only the end result gives a completely
>>> working
>>> setup.
>>>
>>
>> FYI I have applied this series on top of driver model - it is at
>> u-boot-dm.git branch 'norrin-working'. There were a quite few conflicts
>> which I resolved (mostly with mainline I think). I tested it on beaver,
>> trimslice and jetson-tk1.
>>
>> Are you going to respin it?
>
> I started looking at DM for I2C as Heiko suggested but it became too
> complex and time consuming, so what I'm planning to do is drop the I2C
> "enhancements" and use plain i2c_set_bus_num() and friends.
>
> If there's any interest I can push a branch with the work-in-progress
> I2C DM patches, perhaps it could serve as the basis if someone else
> wanted to continue with that effort.

Yes please, maybe its worth to use it as a base ...

bye,
Heiko
-- 
DENX Software Engineering GmbH,     MD: Wolfgang Denk & Detlev Zundel
HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany

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

* [U-Boot] [PATCH v2 00/40] ARM: tegra: Add PCIe support
  2014-09-11 16:00 ` [U-Boot] [PATCH v2 00/40] ARM: tegra: Add PCIe support Albert ARIBAUD
  2014-09-11 16:17   ` Stephen Warren
@ 2014-10-23  3:07   ` Simon Glass
  2014-10-23  8:11     ` Thierry Reding
  1 sibling, 1 reply; 104+ messages in thread
From: Simon Glass @ 2014-10-23  3:07 UTC (permalink / raw)
  To: u-boot

Hi,

On 11 September 2014 10:00, Albert ARIBAUD <albert.u.boot@aribaud.net> wrote:
> Hi Thierry,
>
> On Tue, 26 Aug 2014 17:33:48 +0200, Thierry Reding
> <thierry.reding@gmail.com> wrote:
>
>> From: Thierry Reding <treding@nvidia.com>
>
> Note: this series was split over several custodians (including myself).
> It might thus get applied piecewise... Shouldn't it rather be assigned
> a single custodian -with others giving their Ack) and be applied as a
> whole? And yes, I'm ok with getting all the pieces.

As this series still need some minor work, and the DT patches are
separate, I have pushed them to u-boot-fdt/master and issued a pull
request.

Thierry are you going to pick this up again soon? We should try to get
this series applied in the next few weeks.

Regards,
Simon

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

* [U-Boot] [PATCH v2 00/40] ARM: tegra: Add PCIe support
  2014-10-23  3:07   ` Simon Glass
@ 2014-10-23  8:11     ` Thierry Reding
  2014-10-23 18:33       ` Simon Glass
  0 siblings, 1 reply; 104+ messages in thread
From: Thierry Reding @ 2014-10-23  8:11 UTC (permalink / raw)
  To: u-boot

On Wed, Oct 22, 2014 at 09:07:40PM -0600, Simon Glass wrote:
> Hi,
> 
> On 11 September 2014 10:00, Albert ARIBAUD <albert.u.boot@aribaud.net> wrote:
> > Hi Thierry,
> >
> > On Tue, 26 Aug 2014 17:33:48 +0200, Thierry Reding
> > <thierry.reding@gmail.com> wrote:
> >
> >> From: Thierry Reding <treding@nvidia.com>
> >
> > Note: this series was split over several custodians (including myself).
> > It might thus get applied piecewise... Shouldn't it rather be assigned
> > a single custodian -with others giving their Ack) and be applied as a
> > whole? And yes, I'm ok with getting all the pieces.
> 
> As this series still need some minor work, and the DT patches are
> separate, I have pushed them to u-boot-fdt/master and issued a pull
> request.
> 
> Thierry are you going to pick this up again soon? We should try to get
> this series applied in the next few weeks.

I'm completely swamped right now, but I definitely plan on getting back
to this at some point. But I can't really say for sure how soon that'll
be.

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/20141023/a5a23a5d/attachment.pgp>

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

* [U-Boot] [PATCH v2 00/40] ARM: tegra: Add PCIe support
  2014-10-23  8:11     ` Thierry Reding
@ 2014-10-23 18:33       ` Simon Glass
  0 siblings, 0 replies; 104+ messages in thread
From: Simon Glass @ 2014-10-23 18:33 UTC (permalink / raw)
  To: u-boot

Hi Thierry,

On 23 October 2014 02:11, Thierry Reding <thierry.reding@gmail.com> wrote:
> On Wed, Oct 22, 2014 at 09:07:40PM -0600, Simon Glass wrote:
>> Hi,
>>
>> On 11 September 2014 10:00, Albert ARIBAUD <albert.u.boot@aribaud.net> wrote:
>> > Hi Thierry,
>> >
>> > On Tue, 26 Aug 2014 17:33:48 +0200, Thierry Reding
>> > <thierry.reding@gmail.com> wrote:
>> >
>> >> From: Thierry Reding <treding@nvidia.com>
>> >
>> > Note: this series was split over several custodians (including myself).
>> > It might thus get applied piecewise... Shouldn't it rather be assigned
>> > a single custodian -with others giving their Ack) and be applied as a
>> > whole? And yes, I'm ok with getting all the pieces.
>>
>> As this series still need some minor work, and the DT patches are
>> separate, I have pushed them to u-boot-fdt/master and issued a pull
>> request.
>>
>> Thierry are you going to pick this up again soon? We should try to get
>> this series applied in the next few weeks.
>
> I'm completely swamped right now, but I definitely plan on getting back
> to this at some point. But I can't really say for sure how soon that'll
> be.

Since the changes are fairly trivial and I happen to have some of the
platforms, I could respin if you like? Would be great to it into this
merge window, and I have patches that it might affect.

Let me know what you think.

Regards,
Simon

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

* [U-Boot] [PATCH v2 35/40] ARM: Implement non-cached memory support
  2014-08-26 15:34 ` [U-Boot] [PATCH v2 35/40] ARM: Implement non-cached memory support Thierry Reding
  2014-08-27 19:07   ` Simon Glass
@ 2014-10-24 19:11   ` Stephen Warren
  2014-11-12 15:49     ` Simon Glass
  1 sibling, 1 reply; 104+ messages in thread
From: Stephen Warren @ 2014-10-24 19:11 UTC (permalink / raw)
  To: u-boot

On 08/26/2014 09:34 AM, Thierry Reding wrote:
> From: Thierry Reding <treding@nvidia.com>
>
> Implement an API that can be used by drivers to allocate memory from a
> pool that is mapped uncached. This is useful if drivers would otherwise
> need to do extensive cache maintenance (or explicitly maintaining the
> cache isn't safe).
>
> The API is protected using the new CONFIG_SYS_NONCACHED_MEMORY setting.
> Boards can set this to the size to be used for the non-cached area. The
> area will typically be right below the malloc() area, but architectures
> should take care of aligning the beginning and end of the area to honor
> any mapping restrictions. Architectures must also ensure that mappings
> established for this area do not overlap with the malloc() area (which
> should remain cached for improved performance).
>
> While the API is currently only implemented for ARM v7, it should be
> generic enough to allow other architectures to implement it as well.

> diff --git a/arch/arm/lib/cache.c b/arch/arm/lib/cache.c

> +void noncached_init(void)
...
> +	mmu_set_region_dcache_behaviour(noncached_start, size, DCACHE_OFF);
> +}

If I build with:

#define CONFIG_SYS_DCACHE_OFF
#define CONFIG_SYS_ICACHE_OFF

... then mmu_set_region_dcache_behaviour() doesn't exist (or at least 
isn't linked in) on Jetson TK1 at least.

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

* [U-Boot] [PATCH v2 00/40] ARM: tegra: Add PCIe support
  2014-08-26 15:33 [U-Boot] [PATCH v2 00/40] ARM: tegra: Add PCIe support Thierry Reding
                   ` (41 preceding siblings ...)
  2014-09-28 22:48 ` Simon Glass
@ 2014-10-26 19:07 ` Albert ARIBAUD
  2014-10-26 19:29   ` Albert ARIBAUD
  2014-10-27 23:55   ` Simon Glass
  42 siblings, 2 replies; 104+ messages in thread
From: Albert ARIBAUD @ 2014-10-26 19:07 UTC (permalink / raw)
  To: u-boot

Le Tue, 26 Aug 2014 17:33:48 +0200,
Thierry Reding <thierry.reding@gmail.com> a ?crit :

> 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). In this
> version I've included all patches that were previously split into
> three separate series. Spreading them over multiple series is
> probably not worth it since there might be some dependencies between
> them and only the end result gives a completely working setup.
> 
> Patch 1 adds a %pa modifier to printf() to print physical addresses.
> This is required to allow code to output such addresses irrespective
> of whether a 64 bit or 32 bit architecture is built for.
> 
> Patches 2-7 add various FDT helpers to make it easier to parse
> complex device trees.
> 
> Patch 8 is a minor cleanup to the PCI command that prevents a spew of
> error messages if a bus does not exist. Patch 9 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 10 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 11-14 are some cleanup and refactoring of I2C core code, the
> addition of a higher level API that makes it easier for I2C client
> drivers to talk to devices. The Tegra I2C driver now implements
> i2c_get_bus_num_fdt() to obtain bus numbers corresponding to a DT
> node.
> 
> Patch 15 implements a driver for the AS3722 PMIC used on the Venice2
> and Jetson TK1 boards.
> 
> Patches 16-21 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 22 adds the PCIe controller driver for Tegra20, Tegra30 and
> Tegra124.
> 
> Device tree nodes and configurations options to enable PCIe on the
> TrimSlice (Tegra20), Beaver, Cardhu (Tegra30) and Jetson TK1
> (Tegra124) boards are added in patches 23-31.
> 
> Patches 32-35 implement non-cached memory support that will be used
> in the last batch of patches to implement more reliable packet
> transfers in the r8169 driver. Patch 36 enables non-cached memory
> support on Tegra.
> 
> Finally, patches 37-40 implement non-cached memory support and
> various fixes in the r8169 driver and add support for the revision of
> the NIC found on the Jetson TK1.
> 
> The above boards all have an ethernet NIC connected to PCIe, which is
> what I tested with.
> 
> Thierry Reding (40):
>   vsprintf: Add modifier for phys_addr_t
>   fdt: Add a function to count strings
>   fdt: Add a function to get the index of a string
>   fdt: Add functions to retrieve strings
>   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
>   i2c: Initialize the correct bus
>   i2c: Refactor adapter initialization
>   i2c: Add high-level API
>   i2c: tegra: Implement i2c_get_bus_num_fdt()
>   power: Add AMS AS3722 PMIC support
>   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 GIC for Tegra30
>   ARM: tegra: Add Tegra30 PCIe device tree node
>   ARM: tegra: Enable PCIe on Cardhu
>   ARM: tegra: Enable PCIe on Beaver
>   ARM: tegra: Add GIC for Tegra124
>   ARM: tegra: Add Tegra124 PCIe device tree node
>   ARM: tegra: Enable PCIe on Jetson TK1
>   ARM: cache_v7: Various minor cleanups
>   ARM: cache-cp15: Use more accurate types
>   malloc: Output region when debugging
>   ARM: Implement non-cached memory support
>   ARM: tegra: Enable non-cached memory
>   net: rtl8169: Honor CONFIG_SYS_RX_ETH_BUFFER
>   net: rtl8169: Properly align buffers
>   net: rtl8169: Use non-cached memory if available
>   net: rtl8169: Add support for RTL-8168/8111g
> 
>  README                                           |   19 +
>  arch/arm/cpu/armv7/cache_v7.c                    |   14 +-
>  arch/arm/cpu/tegra-common/Makefile               |    2 +
>  arch/arm/cpu/tegra-common/powergate.c            |  102 ++
>  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       |  716
> ++++++++++++++ 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               |   69 ++
>  arch/arm/dts/tegra20.dtsi                        |   60 ++
>  arch/arm/dts/tegra30-beaver.dts                  |  245 +++++
>  arch/arm/dts/tegra30-cardhu.dts                  |  362 +++++++
>  arch/arm/dts/tegra30.dtsi                        |   84 ++
>  arch/arm/include/asm/arch-tegra/powergate.h      |   38 +
>  arch/arm/include/asm/arch-tegra/xusb-padctl.h    |   24 +
>  arch/arm/include/asm/arch-tegra114/powergate.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-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-tegra30/clock.h        |    2 +
>  arch/arm/include/asm/arch-tegra30/powergate.h    |    6 +
>  arch/arm/include/asm/system.h                    |    7 +-
>  arch/arm/lib/cache-cp15.c                        |    6 +-
>  arch/arm/lib/cache.c                             |   42 +
>  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             |   52 +
>  common/board_r.c                                 |   11 +
>  common/cmd_pci.c                                 |    7 +
>  common/dlmalloc.c                                |    3 +
>  drivers/i2c/i2c_core.c                           |   80 +-
>  drivers/i2c/tegra_i2c.c                          |   13 +
>  drivers/net/rtl8169.c                            |  127 ++-
>  drivers/pci/Makefile                             |    1 +
>  drivers/pci/pci.c                                |    3 +
>  drivers/pci/pci_tegra.c                          | 1143
> ++++++++++++++++++++++
> drivers/power/Makefile                           |    1 +
> drivers/power/as3722.c                           |  300 ++++++
> include/common.h                                 |   14 +-
> include/configs/beaver.h                         |   10 +
> include/configs/cardhu.h                         |   10 +
> include/configs/jetson-tk1.h                     |   13 +
> include/configs/tegra-common.h                   |    1 +
> 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                                 |   69 ++
> include/i2c.h                                    |   96 ++
> include/libfdt.h                                 |   72 ++
> include/pci.h                                    |    1 +
> include/power/as3722.h                           |   27 +
> lib/fdtdec.c                                     |   76 ++
> lib/libfdt/fdt_ro.c                              |   76 ++
> lib/vsprintf.c                                   |   16 +- 63 files
> changed, 5736 insertions(+), 64 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-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 create mode 100644
> drivers/pci/pci_tegra.c create mode 100644 drivers/power/as3722.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
>  create mode 100644 include/power/as3722.h

Am I right in thinking there will be a V3 series, at least of the part
not already awaiting upstream ? If so, maybe it should all be delegated
to a single custodian -- right now it is split over five custodians
(although part of it -- so that all of it is applied in one go without
"foreign" patches getting in between.

Amicalement,
-- 
Albert.

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

* [U-Boot] [PATCH v2 00/40] ARM: tegra: Add PCIe support
  2014-10-26 19:07 ` Albert ARIBAUD
@ 2014-10-26 19:29   ` Albert ARIBAUD
  2014-10-27 23:55   ` Simon Glass
  1 sibling, 0 replies; 104+ messages in thread
From: Albert ARIBAUD @ 2014-10-26 19:29 UTC (permalink / raw)
  To: u-boot

On Sun, 26 Oct 2014 20:07:10 +0100,
Albert ARIBAUD <albert.u.boot@aribaud.net> a ?crit :

> delegated to a single custodian -- right now it is split over five
> custodians (although part of it -- so that all of it is applied in

Sorry for the "(although part of it" which I should have edited out.

Amicalement,
-- 
Albert.

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

* [U-Boot] [PATCH v2 00/40] ARM: tegra: Add PCIe support
  2014-10-26 19:07 ` Albert ARIBAUD
  2014-10-26 19:29   ` Albert ARIBAUD
@ 2014-10-27 23:55   ` Simon Glass
  1 sibling, 0 replies; 104+ messages in thread
From: Simon Glass @ 2014-10-27 23:55 UTC (permalink / raw)
  To: u-boot

Hi Albert,

On 26 October 2014 13:07, Albert ARIBAUD <albert.u.boot@aribaud.net> wrote:
> Le Tue, 26 Aug 2014 17:33:48 +0200,
> Thierry Reding <thierry.reding@gmail.com> a ?crit :
>
>> 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). In this
>> version I've included all patches that were previously split into
>> three separate series. Spreading them over multiple series is
>> probably not worth it since there might be some dependencies between
>> them and only the end result gives a completely working setup.
>>
>> Patch 1 adds a %pa modifier to printf() to print physical addresses.
>> This is required to allow code to output such addresses irrespective
>> of whether a 64 bit or 32 bit architecture is built for.
>>
>> Patches 2-7 add various FDT helpers to make it easier to parse
>> complex device trees.
>>
>> Patch 8 is a minor cleanup to the PCI command that prevents a spew of
>> error messages if a bus does not exist. Patch 9 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 10 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 11-14 are some cleanup and refactoring of I2C core code, the
>> addition of a higher level API that makes it easier for I2C client
>> drivers to talk to devices. The Tegra I2C driver now implements
>> i2c_get_bus_num_fdt() to obtain bus numbers corresponding to a DT
>> node.
>>
>> Patch 15 implements a driver for the AS3722 PMIC used on the Venice2
>> and Jetson TK1 boards.
>>
>> Patches 16-21 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 22 adds the PCIe controller driver for Tegra20, Tegra30 and
>> Tegra124.
>>
>> Device tree nodes and configurations options to enable PCIe on the
>> TrimSlice (Tegra20), Beaver, Cardhu (Tegra30) and Jetson TK1
>> (Tegra124) boards are added in patches 23-31.
>>
>> Patches 32-35 implement non-cached memory support that will be used
>> in the last batch of patches to implement more reliable packet
>> transfers in the r8169 driver. Patch 36 enables non-cached memory
>> support on Tegra.
>>
>> Finally, patches 37-40 implement non-cached memory support and
>> various fixes in the r8169 driver and add support for the revision of
>> the NIC found on the Jetson TK1.
>>
>> The above boards all have an ethernet NIC connected to PCIe, which is
>> what I tested with.
>>
>> Thierry Reding (40):
>>   vsprintf: Add modifier for phys_addr_t
>>   fdt: Add a function to count strings
>>   fdt: Add a function to get the index of a string
>>   fdt: Add functions to retrieve strings
>>   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
>>   i2c: Initialize the correct bus
>>   i2c: Refactor adapter initialization
>>   i2c: Add high-level API
>>   i2c: tegra: Implement i2c_get_bus_num_fdt()
>>   power: Add AMS AS3722 PMIC support
>>   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 GIC for Tegra30
>>   ARM: tegra: Add Tegra30 PCIe device tree node
>>   ARM: tegra: Enable PCIe on Cardhu
>>   ARM: tegra: Enable PCIe on Beaver
>>   ARM: tegra: Add GIC for Tegra124
>>   ARM: tegra: Add Tegra124 PCIe device tree node
>>   ARM: tegra: Enable PCIe on Jetson TK1
>>   ARM: cache_v7: Various minor cleanups
>>   ARM: cache-cp15: Use more accurate types
>>   malloc: Output region when debugging
>>   ARM: Implement non-cached memory support
>>   ARM: tegra: Enable non-cached memory
>>   net: rtl8169: Honor CONFIG_SYS_RX_ETH_BUFFER
>>   net: rtl8169: Properly align buffers
>>   net: rtl8169: Use non-cached memory if available
>>   net: rtl8169: Add support for RTL-8168/8111g
>>
>>  README                                           |   19 +
>>  arch/arm/cpu/armv7/cache_v7.c                    |   14 +-
>>  arch/arm/cpu/tegra-common/Makefile               |    2 +
>>  arch/arm/cpu/tegra-common/powergate.c            |  102 ++
>>  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       |  716
>> ++++++++++++++ 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               |   69 ++
>>  arch/arm/dts/tegra20.dtsi                        |   60 ++
>>  arch/arm/dts/tegra30-beaver.dts                  |  245 +++++
>>  arch/arm/dts/tegra30-cardhu.dts                  |  362 +++++++
>>  arch/arm/dts/tegra30.dtsi                        |   84 ++
>>  arch/arm/include/asm/arch-tegra/powergate.h      |   38 +
>>  arch/arm/include/asm/arch-tegra/xusb-padctl.h    |   24 +
>>  arch/arm/include/asm/arch-tegra114/powergate.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-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-tegra30/clock.h        |    2 +
>>  arch/arm/include/asm/arch-tegra30/powergate.h    |    6 +
>>  arch/arm/include/asm/system.h                    |    7 +-
>>  arch/arm/lib/cache-cp15.c                        |    6 +-
>>  arch/arm/lib/cache.c                             |   42 +
>>  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             |   52 +
>>  common/board_r.c                                 |   11 +
>>  common/cmd_pci.c                                 |    7 +
>>  common/dlmalloc.c                                |    3 +
>>  drivers/i2c/i2c_core.c                           |   80 +-
>>  drivers/i2c/tegra_i2c.c                          |   13 +
>>  drivers/net/rtl8169.c                            |  127 ++-
>>  drivers/pci/Makefile                             |    1 +
>>  drivers/pci/pci.c                                |    3 +
>>  drivers/pci/pci_tegra.c                          | 1143
>> ++++++++++++++++++++++
>> drivers/power/Makefile                           |    1 +
>> drivers/power/as3722.c                           |  300 ++++++
>> include/common.h                                 |   14 +-
>> include/configs/beaver.h                         |   10 +
>> include/configs/cardhu.h                         |   10 +
>> include/configs/jetson-tk1.h                     |   13 +
>> include/configs/tegra-common.h                   |    1 +
>> 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                                 |   69 ++
>> include/i2c.h                                    |   96 ++
>> include/libfdt.h                                 |   72 ++
>> include/pci.h                                    |    1 +
>> include/power/as3722.h                           |   27 +
>> lib/fdtdec.c                                     |   76 ++
>> lib/libfdt/fdt_ro.c                              |   76 ++
>> lib/vsprintf.c                                   |   16 +- 63 files
>> changed, 5736 insertions(+), 64 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-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 create mode 100644
>> drivers/pci/pci_tegra.c create mode 100644 drivers/power/as3722.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
>>  create mode 100644 include/power/as3722.h
>
> Am I right in thinking there will be a V3 series, at least of the part
> not already awaiting upstream ? If so, maybe it should all be delegated
> to a single custodian -- right now it is split over five custodians
> (although part of it -- so that all of it is applied in one go without
> "foreign" patches getting in between.

I'm waiting to hear from Thierry if he wants me to respin this series
since he doesn't have time right now. The DT patches are already in
mainline. If it doesn't merge soon it will probably have to move to
driver model for I2C...

Regards,
Simon

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

* [U-Boot] [PATCH v2 32/40] ARM: cache_v7: Various minor cleanups
  2014-08-26 15:34 ` [U-Boot] [PATCH v2 32/40] ARM: cache_v7: Various minor cleanups Thierry Reding
  2014-08-27 18:56   ` Simon Glass
@ 2014-11-08  8:30   ` Albert ARIBAUD
  1 sibling, 0 replies; 104+ messages in thread
From: Albert ARIBAUD @ 2014-11-08  8:30 UTC (permalink / raw)
  To: u-boot

Hello Thierry,

On Tue, 26 Aug 2014 17:34:20 +0200, Thierry Reding <thierry.reding@gmail.com> wrote:
> From: Thierry Reding <treding@nvidia.com>
> 
> Remove two gratuituous blank lines, uses u32 (instead of int) as the
> type for values that will be written to a register, moves the beginning
> of the variable declaration section to a separate line (rather than the
> one with the opening brace) and keeps the function signature on a single
> line where possible.
> 
> Signed-off-by: Thierry Reding <treding@nvidia.com>
> ---
>  arch/arm/cpu/armv7/cache_v7.c | 14 +++++++-------
>  1 file changed, 7 insertions(+), 7 deletions(-)
> 
> diff --git a/arch/arm/cpu/armv7/cache_v7.c b/arch/arm/cpu/armv7/cache_v7.c
> index a2c4032fed8c..0f9d8377ed5a 100644
> --- a/arch/arm/cpu/armv7/cache_v7.c
> +++ b/arch/arm/cpu/armv7/cache_v7.c
> @@ -21,7 +21,8 @@
>   * to get size details from Current Cache Size ID Register(CCSIDR)
>   */
>  static void set_csselr(u32 level, u32 type)
> -{	u32 csselr = level << 1 | type;
> +{
> +	u32 csselr = level << 1 | type;
>  
>  	/* Write to Cache Size Selection Register(CSSELR) */
>  	asm volatile ("mcr p15, 2, %0, c0, c0, 0" : : "r" (csselr));
> @@ -49,7 +50,8 @@ static void v7_inval_dcache_level_setway(u32 level, u32 num_sets,
>  					 u32 num_ways, u32 way_shift,
>  					 u32 log2_line_len)
>  {
> -	int way, set, setway;
> +	int way, set;
> +	u32 setway;
>  
>  	/*
>  	 * For optimal assembly code:
> @@ -73,7 +75,8 @@ static void v7_clean_inval_dcache_level_setway(u32 level, u32 num_sets,
>  					       u32 num_ways, u32 way_shift,
>  					       u32 log2_line_len)
>  {
> -	int way, set, setway;
> +	int way, set;
> +	u32 setway;
>  
>  	/*
>  	 * For optimal assembly code:
> @@ -134,7 +137,6 @@ static void v7_maint_dcache_level_setway(u32 level, u32 operation)
>  static void v7_maint_dcache_all(u32 operation)
>  {
>  	u32 level, cache_type, level_start_bit = 0;
> -
>  	u32 clidr = get_clidr();
>  
>  	for (level = 0; level < 7; level++) {
> @@ -147,8 +149,7 @@ static void v7_maint_dcache_all(u32 operation)
>  	}
>  }
>  
> -static void v7_dcache_clean_inval_range(u32 start,
> -					u32 stop, u32 line_len)
> +static void v7_dcache_clean_inval_range(u32 start, u32 stop, u32 line_len)
>  {
>  	u32 mva;
>  
> @@ -256,7 +257,6 @@ void flush_dcache_all(void)
>   */
>  void invalidate_dcache_range(unsigned long start, unsigned long stop)
>  {
> -
>  	v7_dcache_maint_range(start, stop, ARMV7_DCACHE_INVAL_RANGE);
>  
>  	v7_outer_cache_inval_range(start, stop);
> -- 
> 2.0.4
> 

Applied to u-boot-arm/master, thanks!

Amicalement,
-- 
Albert.

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

* [U-Boot] [PATCH v2 33/40] ARM: cache-cp15: Use more accurate types
  2014-08-26 15:34 ` [U-Boot] [PATCH v2 33/40] ARM: cache-cp15: Use more accurate types Thierry Reding
  2014-08-27 18:57   ` Simon Glass
@ 2014-11-08  8:31   ` Albert ARIBAUD
  1 sibling, 0 replies; 104+ messages in thread
From: Albert ARIBAUD @ 2014-11-08  8:31 UTC (permalink / raw)
  To: u-boot

Hello Thierry,

On Tue, 26 Aug 2014 17:34:21 +0200, Thierry Reding <thierry.reding@gmail.com> wrote:
> From: Thierry Reding <treding@nvidia.com>
> 
> size_t is the canonical type to represent variables that contain a size.
> Use it instead of signed integer. Physical addresses can be larger than
> 32-bit, so use a more appropriate type for them as well. phys_addr_t is
> a type that is 32-bit on systems that use 32-bit addresses and 64-bit if
> the system is 64-bit or uses a form of physical address extension to use
> a larger address space on 32-bit systems. Using these types the same API
> can be implemented on a wider range of systems.
> 
> Signed-off-by: Thierry Reding <treding@nvidia.com>
> ---
>  arch/arm/include/asm/system.h | 2 +-
>  arch/arm/lib/cache-cp15.c     | 6 +++---
>  2 files changed, 4 insertions(+), 4 deletions(-)
> 
> diff --git a/arch/arm/include/asm/system.h b/arch/arm/include/asm/system.h
> index d51ba668f323..fb31a8faf2b1 100644
> --- a/arch/arm/include/asm/system.h
> +++ b/arch/arm/include/asm/system.h
> @@ -200,7 +200,7 @@ enum {
>   * \param size		size of memory region to change
>   * \param option	dcache option to select
>   */
> -void mmu_set_region_dcache_behaviour(u32 start, int size,
> +void mmu_set_region_dcache_behaviour(phys_addr_t start, size_t size,
>  				     enum dcache_option option);
>  
>  /**
> diff --git a/arch/arm/lib/cache-cp15.c b/arch/arm/lib/cache-cp15.c
> index 5fdfdbfca541..e6c1c83e5758 100644
> --- a/arch/arm/lib/cache-cp15.c
> +++ b/arch/arm/lib/cache-cp15.c
> @@ -47,15 +47,15 @@ __weak void mmu_page_table_flush(unsigned long start, unsigned long stop)
>  	debug("%s: Warning: not implemented\n", __func__);
>  }
>  
> -void mmu_set_region_dcache_behaviour(u32 start, int size,
> +void mmu_set_region_dcache_behaviour(phys_addr_t start, size_t size,
>  				     enum dcache_option option)
>  {
>  	u32 *page_table = (u32 *)gd->arch.tlb_addr;
> -	u32 upto, end;
> +	unsigned long upto, end;
>  
>  	end = ALIGN(start + size, MMU_SECTION_SIZE) >> MMU_SECTION_SHIFT;
>  	start = start >> MMU_SECTION_SHIFT;
> -	debug("%s: start=%x, size=%x, option=%d\n", __func__, start, size,
> +	debug("%s: start=%pa, size=%zu, option=%d\n", __func__, &start, size,
>  	      option);
>  	for (upto = start; upto < end; upto++)
>  		set_section_dcache(upto, option);
> -- 
> 2.0.4
> 

Applied to u-boot-arm/master, thanks!

Amicalement,
-- 
Albert.

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

* [U-Boot] [PATCH v2 34/40] malloc: Output region when debugging
  2014-08-26 15:34 ` [U-Boot] [PATCH v2 34/40] malloc: Output region when debugging Thierry Reding
  2014-08-27 18:58   ` Simon Glass
@ 2014-11-08  8:31   ` Albert ARIBAUD
  1 sibling, 0 replies; 104+ messages in thread
From: Albert ARIBAUD @ 2014-11-08  8:31 UTC (permalink / raw)
  To: u-boot

Hello Thierry,

On Tue, 26 Aug 2014 17:34:22 +0200, Thierry Reding <thierry.reding@gmail.com> wrote:
> From: Thierry Reding <treding@nvidia.com>
> 
> When DEBUG is set, output memory region used for malloc().
> 
> Signed-off-by: Thierry Reding <treding@nvidia.com>
> ---
>  common/dlmalloc.c | 3 +++
>  1 file changed, 3 insertions(+)
> 
> diff --git a/common/dlmalloc.c b/common/dlmalloc.c
> index f9873393c183..3d6391e60acf 100644
> --- a/common/dlmalloc.c
> +++ b/common/dlmalloc.c
> @@ -1533,6 +1533,9 @@ void mem_malloc_init(ulong start, ulong size)
>  	mem_malloc_end = start + size;
>  	mem_malloc_brk = start;
>  
> +	debug("using memory %#lx-%#lx for malloc()\n", mem_malloc_start,
> +	      mem_malloc_end);
> +
>  	memset((void *)mem_malloc_start, 0, size);
>  
>  	malloc_bin_reloc();
> -- 
> 2.0.4
> 

Applied to u-boot-arm/master, thanks!

Amicalement,
-- 
Albert.

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

* [U-Boot] [PATCH v2 35/40] ARM: Implement non-cached memory support
  2014-10-24 19:11   ` Stephen Warren
@ 2014-11-12 15:49     ` Simon Glass
  0 siblings, 0 replies; 104+ messages in thread
From: Simon Glass @ 2014-11-12 15:49 UTC (permalink / raw)
  To: u-boot

Hi Stephen,

On 24 October 2014 13:11, Stephen Warren <swarren@wwwdotorg.org> wrote:
> On 08/26/2014 09:34 AM, Thierry Reding wrote:
>>
>> From: Thierry Reding <treding@nvidia.com>
>>
>> Implement an API that can be used by drivers to allocate memory from a
>> pool that is mapped uncached. This is useful if drivers would otherwise
>> need to do extensive cache maintenance (or explicitly maintaining the
>> cache isn't safe).
>>
>> The API is protected using the new CONFIG_SYS_NONCACHED_MEMORY setting.
>> Boards can set this to the size to be used for the non-cached area. The
>> area will typically be right below the malloc() area, but architectures
>> should take care of aligning the beginning and end of the area to honor
>> any mapping restrictions. Architectures must also ensure that mappings
>> established for this area do not overlap with the malloc() area (which
>> should remain cached for improved performance).
>>
>> While the API is currently only implemented for ARM v7, it should be
>> generic enough to allow other architectures to implement it as well.
>
>
>> diff --git a/arch/arm/lib/cache.c b/arch/arm/lib/cache.c
>
>
>> +void noncached_init(void)
>
> ...
>>
>> +       mmu_set_region_dcache_behaviour(noncached_start, size,
>> DCACHE_OFF);
>> +}
>
>
> If I build with:
>
> #define CONFIG_SYS_DCACHE_OFF
> #define CONFIG_SYS_ICACHE_OFF
>
> ... then mmu_set_region_dcache_behaviour() doesn't exist (or at least isn't
> linked in) on Jetson TK1 at least.

I see that too. If you #undef CONFIG_SYS_NONCACHED_MEMORY then the
problem goes away. There is a warning in the network driver in this
case but it is not important.

A better solution is probably an #ifdef around the call you mention.
It minimised code changes when cache is on/off which is probably a
good thing.

Regards
Simon

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

* [U-Boot] [PATCH v2 38/40] net: rtl8169: Properly align buffers
  2014-08-26 15:34 ` [U-Boot] [PATCH v2 38/40] net: rtl8169: Properly align buffers Thierry Reding
@ 2014-11-12 23:37   ` Nobuhiro Iwamatsu
  0 siblings, 0 replies; 104+ messages in thread
From: Nobuhiro Iwamatsu @ 2014-11-12 23:37 UTC (permalink / raw)
  To: u-boot

Hi,

I tested on sh7785lcr board with this patch.
This worked without any problems. Thanks.

2014-08-27 0:34 GMT+09:00 Thierry Reding <thierry.reding@gmail.com>:
> From: Thierry Reding <treding@nvidia.com>
>
> RX and TX descriptor rings should be aligned to 256 byte boundaries. Use
> the DEFINE_ALIGN_BUFFER() macro to define the buffers so that they don't
> have to be manually aligned later on. Also make sure that the buffers do
> align to cache-line boundaries in case the cache-line is higher than the
> 256 byte alignment requirements of the NIC.
>
> Also add a warning if the cache-line size is larger than the descriptor
> size, because the driver may discard changes to descriptors made by the
> hardware when requeuing RX buffers.
>
> Signed-off-by: Thierry Reding <treding@nvidia.com>
> ---
> Changes in v2:
> - make cache-line vs. descriptor size a compile-time warning

Tested-by: Nobuhiro Iwamatsu <nobuhiro.iwamatsu.yj@renesas.com>

>
>  drivers/net/rtl8169.c | 63 +++++++++++++++++++++++++++------------------------
>  1 file changed, 34 insertions(+), 29 deletions(-)
>
> diff --git a/drivers/net/rtl8169.c b/drivers/net/rtl8169.c
> index c3eb474f0fba..d81ee8af1cc1 100644
> --- a/drivers/net/rtl8169.c
> +++ b/drivers/net/rtl8169.c
> @@ -277,23 +277,41 @@ struct RxDesc {
>         u32 buf_Haddr;
>  };
>
> -/* Define the TX Descriptor */
> -static u8 tx_ring[NUM_TX_DESC * sizeof(struct TxDesc) + 256];
> -/*     __attribute__ ((aligned(256))); */
> +#define RTL8169_DESC_SIZE 16
>
> -/* Create a static buffer of size RX_BUF_SZ for each
> -TX Descriptor. All descriptors point to a
> -part of this buffer */
> -static unsigned char txb[NUM_TX_DESC * RX_BUF_SIZE];
> +#if ARCH_DMA_MINALIGN > 256
> +#  define RTL8169_ALIGN ARCH_DMA_MINALIGN
> +#else
> +#  define RTL8169_ALIGN 256
> +#endif
> +
> +/*
> + * Warn if the cache-line size is larger than the descriptor size. In such
> + * cases the driver will likely fail because the CPU needs to flush the cache
> + * when requeuing RX buffers, therefore descriptors written by the hardware
> + * may be discarded.
> + */
> +#if RTL8169_DESC_SIZE < ARCH_DMA_MINALIGN
> +#warning cache-line size is larger than descriptor size
> +#endif
> +
> +/* Define the TX Descriptor */
> +DEFINE_ALIGN_BUFFER(struct TxDesc, tx_ring, NUM_TX_DESC, RTL8169_ALIGN);
>
>  /* Define the RX Descriptor */
> -static u8 rx_ring[NUM_RX_DESC * sizeof(struct TxDesc) + 256];
> -  /*  __attribute__ ((aligned(256))); */
> +DEFINE_ALIGN_BUFFER(struct RxDesc, rx_ring, NUM_RX_DESC, RTL8169_ALIGN);
>
> -/* Create a static buffer of size RX_BUF_SZ for each
> -RX Descriptor  All descriptors point to a
> -part of this buffer */
> -static unsigned char rxb[NUM_RX_DESC * RX_BUF_SIZE];
> +/*
> + * Create a static buffer of size RX_BUF_SZ for each TX Descriptor. All
> + * descriptors point to a part of this buffer.
> + */
> +DEFINE_ALIGN_BUFFER(u8, txb, NUM_TX_DESC * RX_BUF_SIZE, RTL8169_ALIGN);
> +
> +/*
> + * Create a static buffer of size RX_BUF_SZ for each RX Descriptor. All
> + * descriptors point to a part of this buffer.
> + */
> +DEFINE_ALIGN_BUFFER(u8, rxb, NUM_RX_DESC * RX_BUF_SIZE, RTL8169_ALIGN);
>
>  struct rtl8169_private {
>         void *mmio_addr;        /* memory map physical address */
> @@ -301,8 +319,6 @@ struct rtl8169_private {
>         unsigned long cur_rx;   /* Index into the Rx descriptor buffer of next Rx pkt. */
>         unsigned long cur_tx;   /* Index into the Tx descriptor buffer of next Rx pkt. */
>         unsigned long dirty_tx;
> -       unsigned char *TxDescArrays;    /* Index of Tx Descriptor buffer */
> -       unsigned char *RxDescArrays;    /* Index of Rx Descriptor buffer */
>         struct TxDesc *TxDescArray;     /* Index of 256-alignment Tx Descriptor buffer */
>         struct RxDesc *RxDescArray;     /* Index of 256-alignment Rx Descriptor buffer */
>         unsigned char *RxBufferRings;   /* Index of Rx Buffer  */
> @@ -710,16 +726,6 @@ static int rtl_reset(struct eth_device *dev, bd_t *bis)
>         printf ("%s\n", __FUNCTION__);
>  #endif
>
> -       tpc->TxDescArrays = tx_ring;
> -       /* Tx Desscriptor needs 256 bytes alignment; */
> -       tpc->TxDescArray = (struct TxDesc *) ((unsigned long)(tpc->TxDescArrays +
> -                                                             255) & ~255);
> -
> -       tpc->RxDescArrays = rx_ring;
> -       /* Rx Desscriptor needs 256 bytes alignment; */
> -       tpc->RxDescArray = (struct RxDesc *) ((unsigned long)(tpc->RxDescArrays +
> -                                                             255) & ~255);
> -
>         rtl8169_init_ring(dev);
>         rtl8169_hw_start(dev);
>         /* Construct a perfect filter frame with the mac address as first match
> @@ -761,10 +767,6 @@ static void rtl_halt(struct eth_device *dev)
>
>         RTL_W32(RxMissed, 0);
>
> -       tpc->TxDescArrays = NULL;
> -       tpc->RxDescArrays = NULL;
> -       tpc->TxDescArray = NULL;
> -       tpc->RxDescArray = NULL;
>         for (i = 0; i < NUM_RX_DESC; i++) {
>                 tpc->RxBufferRing[i] = NULL;
>         }
> @@ -909,6 +911,9 @@ static int rtl_init(struct eth_device *dev, bd_t *bis)
>  #endif
>         }
>
> +       tpc->TxDescArray = tx_ring;
> +       tpc->RxDescArray = rx_ring;
> +
>         return 1;
>  }
>
> --
> 2.0.4
>
> _______________________________________________
> U-Boot mailing list
> U-Boot at lists.denx.de
> http://lists.denx.de/mailman/listinfo/u-boot

-- 
Nobuhiro Iwamatsu

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

* [U-Boot] [PATCH v2 04/40] fdt: Add functions to retrieve strings
  2014-09-08 15:02     ` Simon Glass
@ 2015-03-25 23:23       ` Simon Glass
  2015-07-14 19:48         ` Simon Glass
  0 siblings, 1 reply; 104+ messages in thread
From: Simon Glass @ 2015-03-25 23:23 UTC (permalink / raw)
  To: u-boot

Hi Thierry,

On 8 September 2014 at 09:02, Simon Glass <sjg@chromium.org> wrote:
> Applied to u-boot-fdt/next, thanks!

Did you submit these patches to dtc upstream? I don't see them applied.

Regards,
SImon

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

* [U-Boot] [PATCH v2 04/40] fdt: Add functions to retrieve strings
  2015-03-25 23:23       ` Simon Glass
@ 2015-07-14 19:48         ` Simon Glass
  2015-07-15 11:17           ` Thierry Reding
  0 siblings, 1 reply; 104+ messages in thread
From: Simon Glass @ 2015-07-14 19:48 UTC (permalink / raw)
  To: u-boot

+Scott, Masahiro

Hi Thierry,

On 25 March 2015 at 17:23, Simon Glass <sjg@chromium.org> wrote:
> Hi Thierry,
>
> On 8 September 2014 at 09:02, Simon Glass <sjg@chromium.org> wrote:
>> Applied to u-boot-fdt/next, thanks!
>
> Did you submit these patches to dtc upstream? I don't see them applied.

Ping? Masahiro has now sent a series on top of your patches, so we
need to sort this out.

Regards,
Simon

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

* [U-Boot] [PATCH v2 04/40] fdt: Add functions to retrieve strings
  2015-07-14 19:48         ` Simon Glass
@ 2015-07-15 11:17           ` Thierry Reding
  2015-07-15 11:35             ` Albert ARIBAUD
  0 siblings, 1 reply; 104+ messages in thread
From: Thierry Reding @ 2015-07-15 11:17 UTC (permalink / raw)
  To: u-boot

On Tue, Jul 14, 2015 at 01:48:45PM -0600, Simon Glass wrote:
> +Scott, Masahiro
> 
> Hi Thierry,
> 
> On 25 March 2015 at 17:23, Simon Glass <sjg@chromium.org> wrote:
> > Hi Thierry,
> >
> > On 8 September 2014 at 09:02, Simon Glass <sjg@chromium.org> wrote:
> >> Applied to u-boot-fdt/next, thanks!
> >
> > Did you submit these patches to dtc upstream? I don't see them applied.
> 
> Ping? Masahiro has now sent a series on top of your patches, so we
> need to sort this out.

I sent these to the DTC maintainers and the list, with you and Masahiro
in Cc. They patches should be eqivalent to what's in U-Boot except for
the node parameter that I renamed nodeoffset for consistency with libfdt
and the testsuite bits.

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

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

* [U-Boot] [PATCH v2 04/40] fdt: Add functions to retrieve strings
  2015-07-15 11:17           ` Thierry Reding
@ 2015-07-15 11:35             ` Albert ARIBAUD
  2015-07-15 11:52               ` Thierry Reding
  0 siblings, 1 reply; 104+ messages in thread
From: Albert ARIBAUD @ 2015-07-15 11:35 UTC (permalink / raw)
  To: u-boot

Hello Thierry,

On Wed, 15 Jul 2015 13:17:18 +0200, Thierry Reding
<thierry.reding@gmail.com> wrote:
> On Tue, Jul 14, 2015 at 01:48:45PM -0600, Simon Glass wrote:
> > +Scott, Masahiro
> > 
> > Hi Thierry,
> > 
> > On 25 March 2015 at 17:23, Simon Glass <sjg@chromium.org> wrote:
> > > Hi Thierry,
> > >
> > > On 8 September 2014 at 09:02, Simon Glass <sjg@chromium.org> wrote:
> > >> Applied to u-boot-fdt/next, thanks!
> > >
> > > Did you submit these patches to dtc upstream? I don't see them applied.
> > 
> > Ping? Masahiro has now sent a series on top of your patches, so we
> > need to sort this out.
> 
> I sent these to the DTC maintainers and the list, with you and Masahiro
> in Cc. They patches should be eqivalent to what's in U-Boot except for
> the node parameter that I renamed nodeoffset for consistency with libfdt
> and the testsuite bits.

Do you mean there are intrinsic incompatibilities between U-Boot and
Linux that make it impossible to use the same name in both?

> Thierry

Amicalement,
-- 
Albert.

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

* [U-Boot] [PATCH v2 04/40] fdt: Add functions to retrieve strings
  2015-07-15 11:35             ` Albert ARIBAUD
@ 2015-07-15 11:52               ` Thierry Reding
  0 siblings, 0 replies; 104+ messages in thread
From: Thierry Reding @ 2015-07-15 11:52 UTC (permalink / raw)
  To: u-boot

On Wed, Jul 15, 2015 at 01:35:26PM +0200, Albert ARIBAUD wrote:
> Hello Thierry,
> 
> On Wed, 15 Jul 2015 13:17:18 +0200, Thierry Reding
> <thierry.reding@gmail.com> wrote:
> > On Tue, Jul 14, 2015 at 01:48:45PM -0600, Simon Glass wrote:
> > > +Scott, Masahiro
> > > 
> > > Hi Thierry,
> > > 
> > > On 25 March 2015 at 17:23, Simon Glass <sjg@chromium.org> wrote:
> > > > Hi Thierry,
> > > >
> > > > On 8 September 2014 at 09:02, Simon Glass <sjg@chromium.org> wrote:
> > > >> Applied to u-boot-fdt/next, thanks!
> > > >
> > > > Did you submit these patches to dtc upstream? I don't see them applied.
> > > 
> > > Ping? Masahiro has now sent a series on top of your patches, so we
> > > need to sort this out.
> > 
> > I sent these to the DTC maintainers and the list, with you and Masahiro
> > in Cc. They patches should be eqivalent to what's in U-Boot except for
> > the node parameter that I renamed nodeoffset for consistency with libfdt
> > and the testsuite bits.
> 
> Do you mean there are intrinsic incompatibilities between U-Boot and
> Linux that make it impossible to use the same name in both?

No, I don't think so. Back at the time I must have assumed that node was
the consistent name used in U-Boot, but it seems like these string
functions are now the only ones in libfdt that use this. I'd expect that
to fix itself when libfdt gets sync'ed back from the upstream copy.

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

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

end of thread, other threads:[~2015-07-15 11:52 UTC | newest]

Thread overview: 104+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2014-08-26 15:33 [U-Boot] [PATCH v2 00/40] ARM: tegra: Add PCIe support Thierry Reding
2014-08-26 15:33 ` [U-Boot] [PATCH v2 01/40] vsprintf: Add modifier for phys_addr_t Thierry Reding
2014-08-26 17:04   ` Stephen Warren
2014-08-27  7:01     ` Thierry Reding
2014-08-27 17:41       ` Stephen Warren
2014-08-28 10:38         ` Thierry Reding
2014-09-17  0:44           ` [U-Boot] [U-Boot, v2, " Tom Rini
2014-08-26 23:14   ` [U-Boot] [PATCH v2 " Simon Glass
2014-08-27  7:37     ` Thierry Reding
2014-08-27 15:24       ` Simon Glass
2014-08-26 15:33 ` [U-Boot] [PATCH v2 02/40] fdt: Add a function to count strings Thierry Reding
2014-08-27 18:51   ` Simon Glass
2014-09-08 15:01     ` Simon Glass
2014-08-26 15:33 ` [U-Boot] [PATCH v2 03/40] fdt: Add a function to get the index of a string Thierry Reding
2014-08-27 18:51   ` Simon Glass
2014-09-08 15:02     ` Simon Glass
2014-08-26 15:33 ` [U-Boot] [PATCH v2 04/40] fdt: Add functions to retrieve strings Thierry Reding
2014-08-27 18:53   ` Simon Glass
2014-09-08 15:02     ` Simon Glass
2015-03-25 23:23       ` Simon Glass
2015-07-14 19:48         ` Simon Glass
2015-07-15 11:17           ` Thierry Reding
2015-07-15 11:35             ` Albert ARIBAUD
2015-07-15 11:52               ` Thierry Reding
2014-08-26 15:33 ` [U-Boot] [PATCH v2 05/40] fdt: Add resource parsing functions Thierry Reding
2014-08-27 18:53   ` Simon Glass
2014-09-08 15:02   ` Simon Glass
2014-08-26 15:33 ` [U-Boot] [PATCH v2 06/40] fdt: Add a function to return PCI BDF triplet Thierry Reding
2014-09-08 15:03   ` Simon Glass
2014-08-26 15:33 ` [U-Boot] [PATCH v2 07/40] fdt: Add a subnodes iterator macro Thierry Reding
2014-09-08 15:03   ` Simon Glass
2014-08-26 15:33 ` [U-Boot] [PATCH v2 08/40] pci: Abort early if bus does not exist Thierry Reding
2014-08-26 15:33 ` [U-Boot] [PATCH v2 09/40] pci: Honour pci_skip_dev() Thierry Reding
2014-08-26 15:33 ` [U-Boot] [PATCH v2 10/40] Add pr_fmt() macro Thierry Reding
2014-08-26 15:33 ` [U-Boot] [PATCH v2 11/40] i2c: Initialize the correct bus Thierry Reding
2014-08-27  4:52   ` Heiko Schocher
2014-08-27  5:12     ` Thierry Reding
2014-08-27  5:26       ` Heiko Schocher
2014-08-26 15:34 ` [U-Boot] [PATCH v2 12/40] i2c: Refactor adapter initialization Thierry Reding
2014-08-26 15:34 ` [U-Boot] [PATCH v2 13/40] i2c: Add high-level API Thierry Reding
2014-08-27  5:21   ` Heiko Schocher
2014-08-27  6:21     ` Thierry Reding
2014-08-27  7:07       ` Heiko Schocher
2014-08-27  8:51         ` Thierry Reding
2014-08-27  9:56           ` Heiko Schocher
2014-08-27 11:41             ` Thierry Reding
2014-08-27 19:10               ` Simon Glass
2014-08-28  9:53                 ` Heiko Schocher
2014-08-26 15:34 ` [U-Boot] [PATCH v2 14/40] i2c: tegra: Implement i2c_get_bus_num_fdt() Thierry Reding
2014-09-02 19:24   ` Simon Glass
2014-08-26 15:34 ` [U-Boot] [PATCH v2 15/40] power: Add AMS AS3722 PMIC support Thierry Reding
2014-08-27  5:26   ` Heiko Schocher
2014-08-27  6:28     ` Thierry Reding
2014-08-27  7:18       ` Heiko Schocher
2014-08-26 15:34 ` [U-Boot] [PATCH v2 16/40] ARM: tegra: Implement tegra_plle_enable() Thierry Reding
2014-08-26 15:34 ` [U-Boot] [PATCH v2 17/40] ARM: tegra: Provide PCIEXCLK reset ID Thierry Reding
2014-08-26 15:34 ` [U-Boot] [PATCH v2 18/40] ARM: tegra: Implement powergate support Thierry Reding
2014-08-26 15:34 ` [U-Boot] [PATCH v2 19/40] ARM: tegra: Implement XUSB pad controller Thierry Reding
2014-08-26 15:34 ` [U-Boot] [PATCH v2 20/40] ARM: tegra: Add XUSB pad controller on Tegra124 Thierry Reding
2014-08-26 15:34 ` [U-Boot] [PATCH v2 21/40] ARM: tegra: Enable XUSB pad controller on Jetson TK1 Thierry Reding
2014-08-26 15:34 ` [U-Boot] [PATCH v2 22/40] pci: tegra: Add Tegra PCIe driver Thierry Reding
2014-08-26 15:34 ` [U-Boot] [PATCH v2 23/40] ARM: tegra: Add Tegra20 PCIe device tree node Thierry Reding
2014-08-26 15:34 ` [U-Boot] [PATCH v2 24/40] ARM: tegra: Enable PCIe on TrimSlice Thierry Reding
2014-08-26 15:34 ` [U-Boot] [PATCH v2 25/40] ARM: tegra: Add GIC for Tegra30 Thierry Reding
2014-08-26 15:34 ` [U-Boot] [PATCH v2 26/40] ARM: tegra: Add Tegra30 PCIe device tree node Thierry Reding
2014-08-26 15:34 ` [U-Boot] [PATCH v2 27/40] ARM: tegra: Enable PCIe on Cardhu Thierry Reding
2014-08-26 15:34 ` [U-Boot] [PATCH v2 28/40] ARM: tegra: Enable PCIe on Beaver Thierry Reding
2014-08-26 15:34 ` [U-Boot] [PATCH v2 29/40] ARM: tegra: Add GIC for Tegra124 Thierry Reding
2014-08-26 15:34 ` [U-Boot] [PATCH v2 30/40] ARM: tegra: Add Tegra124 PCIe device tree node Thierry Reding
2014-08-26 15:34 ` [U-Boot] [PATCH v2 31/40] ARM: tegra: Enable PCIe on Jetson TK1 Thierry Reding
2014-08-26 15:34 ` [U-Boot] [PATCH v2 32/40] ARM: cache_v7: Various minor cleanups Thierry Reding
2014-08-27 18:56   ` Simon Glass
2014-11-08  8:30   ` Albert ARIBAUD
2014-08-26 15:34 ` [U-Boot] [PATCH v2 33/40] ARM: cache-cp15: Use more accurate types Thierry Reding
2014-08-27 18:57   ` Simon Glass
2014-11-08  8:31   ` Albert ARIBAUD
2014-08-26 15:34 ` [U-Boot] [PATCH v2 34/40] malloc: Output region when debugging Thierry Reding
2014-08-27 18:58   ` Simon Glass
2014-11-08  8:31   ` Albert ARIBAUD
2014-08-26 15:34 ` [U-Boot] [PATCH v2 35/40] ARM: Implement non-cached memory support Thierry Reding
2014-08-27 19:07   ` Simon Glass
2014-10-24 19:11   ` Stephen Warren
2014-11-12 15:49     ` Simon Glass
2014-08-26 15:34 ` [U-Boot] [PATCH v2 36/40] ARM: tegra: Enable non-cached memory Thierry Reding
2014-08-26 15:34 ` [U-Boot] [PATCH v2 37/40] net: rtl8169: Honor CONFIG_SYS_RX_ETH_BUFFER Thierry Reding
2014-08-26 15:34 ` [U-Boot] [PATCH v2 38/40] net: rtl8169: Properly align buffers Thierry Reding
2014-11-12 23:37   ` Nobuhiro Iwamatsu
2014-08-26 15:34 ` [U-Boot] [PATCH v2 39/40] net: rtl8169: Use non-cached memory if available Thierry Reding
2014-08-26 15:34 ` [U-Boot] [PATCH v2 40/40] net: rtl8169: Add support for RTL-8168/8111g Thierry Reding
2014-09-11 16:00 ` [U-Boot] [PATCH v2 00/40] ARM: tegra: Add PCIe support Albert ARIBAUD
2014-09-11 16:17   ` Stephen Warren
2014-09-11 19:20     ` Simon Glass
2014-09-18  8:43       ` Albert ARIBAUD
2014-09-18 18:01         ` Simon Glass
2014-10-23  3:07   ` Simon Glass
2014-10-23  8:11     ` Thierry Reding
2014-10-23 18:33       ` Simon Glass
2014-09-28 22:48 ` Simon Glass
2014-09-29  8:11   ` Thierry Reding
2014-09-29 13:54     ` Simon Glass
2014-10-06 12:24     ` Heiko Schocher
2014-10-26 19:07 ` Albert ARIBAUD
2014-10-26 19:29   ` Albert ARIBAUD
2014-10-27 23:55   ` Simon Glass

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.