All of lore.kernel.org
 help / color / mirror / Atom feed
* [U-Boot] [PATCH v3 0/30] ARM: tegra: Add PCIe support
@ 2014-11-13  1:26 Simon Glass
  2014-11-13  1:26 ` [U-Boot] [PATCH v3 01/30] vsprintf: Add modifier for phys_addr_t Simon Glass
                   ` (29 more replies)
  0 siblings, 30 replies; 45+ messages in thread
From: Simon Glass @ 2014-11-13  1:26 UTC (permalink / raw)
  To: u-boot

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

(Commit message updated by Simon Glass <sjg@chromium.org> who is sending
this series originally created by Thierry)

This series adds PCIe support for Tegra20, Tegra30 and Tegra124. The size is
mostly due to the large number of infrastructure that's added (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.

Patch 2 is a minor cleanup to the PCI command that prevents a spew of error
messages if a bus does not exist. Patch 3 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 4 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.

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

Patches 6-11 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 12 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 13-21.

Patches 22-25 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 26 enables non-cached memory support on Tegra.

(Note from Simon: These patches may have already been applied in the ARM
tree, but I can't see them there).

Finally, patches 27-30 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.

Note from Simon: I have:

- rebased this on top of the I2C driver model series
- dropped the I2C framework patches
- adjust the PMIC driver and code that calls it to use driver mode
- tested the I2C changes on Jetson-TK1

Changes in v3:
- Use driver model for the PMIC
- Use driver model to access the PMIC
- Use driver model to access the PMIC
- Avoid build error with noncached_init() when the dcache is disabled
- Remove cache-line size warning if dcache is disabled

Thierry Reding (30):
  vsprintf: Add modifier for phys_addr_t
  pci: Abort early if bus does not exist
  pci: Honour pci_skip_dev()
  Add pr_fmt() macro
  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                       |   89 ++
 arch/arm/dts/tegra20-trimslice.dts               |   69 ++
 arch/arm/dts/tegra20.dtsi                        |   59 ++
 arch/arm/dts/tegra30-beaver.dts                  |  245 +++++
 arch/arm/dts/tegra30-cardhu.dts                  |  362 +++++++
 arch/arm/dts/tegra30.dtsi                        |   83 ++
 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                             |   44 +
 board/compulab/trimslice/trimslice.c             |    8 +
 board/nvidia/cardhu/cardhu.c                     |   52 +
 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/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                           |  264 +++++
 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/tegra20-car.h          |    2 +-
 include/dt-bindings/clock/tegra30-car.h          |    2 +-
 include/dt-bindings/pinctrl/pinctrl-tegra-xusb.h |    7 +
 include/fdtdec.h                                 |    6 +
 include/pci.h                                    |    1 +
 include/power/as3722.h                           |   27 +
 lib/fdtdec.c                                     |    5 +
 lib/vsprintf.c                                   |   16 +-
 57 files changed, 4471 insertions(+), 57 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/pinctrl/pinctrl-tegra-xusb.h
 create mode 100644 include/power/as3722.h

-- 
2.1.0.rc2.206.gedb03e5

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

* [U-Boot] [PATCH v3 01/30] vsprintf: Add modifier for phys_addr_t
  2014-11-13  1:26 [U-Boot] [PATCH v3 0/30] ARM: tegra: Add PCIe support Simon Glass
@ 2014-11-13  1:26 ` Simon Glass
  2014-11-17 10:18   ` Thierry Reding
  2014-11-24 22:11   ` [U-Boot] [U-Boot, v3, " Tom Rini
  2014-11-13  1:26 ` [U-Boot] [PATCH v3 02/30] pci: Abort early if bus does not exist Simon Glass
                   ` (28 subsequent siblings)
  29 siblings, 2 replies; 45+ messages in thread
From: Simon Glass @ 2014-11-13  1:26 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>
Tested-by: Stephen Warren <swarren@nvidia.com>
Signed-off-by: Simon Glass <sjg@chromium.org>
---

Changes in v3: None

 lib/vsprintf.c | 16 ++++++++++++++--
 1 file changed, 14 insertions(+), 2 deletions(-)

diff --git a/lib/vsprintf.c b/lib/vsprintf.c
index b585713..6b5a1e9 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.1.0.rc2.206.gedb03e5

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

* [U-Boot] [PATCH v3 02/30] pci: Abort early if bus does not exist
  2014-11-13  1:26 [U-Boot] [PATCH v3 0/30] ARM: tegra: Add PCIe support Simon Glass
  2014-11-13  1:26 ` [U-Boot] [PATCH v3 01/30] vsprintf: Add modifier for phys_addr_t Simon Glass
@ 2014-11-13  1:26 ` Simon Glass
  2014-11-24 22:11   ` [U-Boot] [U-Boot, v3, " Tom Rini
  2014-11-13  1:26 ` [U-Boot] [PATCH v3 03/30] pci: Honour pci_skip_dev() Simon Glass
                   ` (27 subsequent siblings)
  29 siblings, 1 reply; 45+ messages in thread
From: Simon Glass @ 2014-11-13  1:26 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>
Signed-off-by: Simon Glass <sjg@chromium.org>
---

Changes in v3: None

 common/cmd_pci.c | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/common/cmd_pci.c b/common/cmd_pci.c
index a1ba42e..5a6048c 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.1.0.rc2.206.gedb03e5

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

* [U-Boot] [PATCH v3 03/30] pci: Honour pci_skip_dev()
  2014-11-13  1:26 [U-Boot] [PATCH v3 0/30] ARM: tegra: Add PCIe support Simon Glass
  2014-11-13  1:26 ` [U-Boot] [PATCH v3 01/30] vsprintf: Add modifier for phys_addr_t Simon Glass
  2014-11-13  1:26 ` [U-Boot] [PATCH v3 02/30] pci: Abort early if bus does not exist Simon Glass
@ 2014-11-13  1:26 ` Simon Glass
  2014-11-24 22:11   ` [U-Boot] [U-Boot,v3,03/30] " Tom Rini
  2014-11-13  1:26 ` [U-Boot] [PATCH v3 04/30] Add pr_fmt() macro Simon Glass
                   ` (26 subsequent siblings)
  29 siblings, 1 reply; 45+ messages in thread
From: Simon Glass @ 2014-11-13  1:26 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>
Signed-off-by: Simon Glass <sjg@chromium.org>
---

Changes in v3: None

 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 5a6048c..e3a77e3 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 60c333e..0d321a6 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 2ff7365..d211351 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.1.0.rc2.206.gedb03e5

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

* [U-Boot] [PATCH v3 04/30] Add pr_fmt() macro
  2014-11-13  1:26 [U-Boot] [PATCH v3 0/30] ARM: tegra: Add PCIe support Simon Glass
                   ` (2 preceding siblings ...)
  2014-11-13  1:26 ` [U-Boot] [PATCH v3 03/30] pci: Honour pci_skip_dev() Simon Glass
@ 2014-11-13  1:26 ` Simon Glass
  2014-11-24 22:11   ` [U-Boot] [U-Boot,v3,04/30] " Tom Rini
  2014-11-13  1:26 ` [U-Boot] [PATCH v3 05/30] power: Add AMS AS3722 PMIC support Simon Glass
                   ` (25 subsequent siblings)
  29 siblings, 1 reply; 45+ messages in thread
From: Simon Glass @ 2014-11-13  1:26 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>
Signed-off-by: Simon Glass <sjg@chromium.org>
---

Changes in v3: None

 include/common.h | 14 +++++++++-----
 1 file changed, 9 insertions(+), 5 deletions(-)

diff --git a/include/common.h b/include/common.h
index ecf7fca..4f6f461 100644
--- a/include/common.h
+++ b/include/common.h
@@ -96,15 +96,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...)			\
@@ -126,7 +130,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.1.0.rc2.206.gedb03e5

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

* [U-Boot] [PATCH v3 05/30] power: Add AMS AS3722 PMIC support
  2014-11-13  1:26 [U-Boot] [PATCH v3 0/30] ARM: tegra: Add PCIe support Simon Glass
                   ` (3 preceding siblings ...)
  2014-11-13  1:26 ` [U-Boot] [PATCH v3 04/30] Add pr_fmt() macro Simon Glass
@ 2014-11-13  1:26 ` Simon Glass
  2014-11-17 10:04   ` Thierry Reding
  2014-11-13  1:26 ` [U-Boot] [PATCH v3 06/30] ARM: tegra: Implement tegra_plle_enable() Simon Glass
                   ` (24 subsequent siblings)
  29 siblings, 1 reply; 45+ messages in thread
From: Simon Glass @ 2014-11-13  1:26 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>
Signed-off-by: Simon Glass <sjg@chromium.org>
---

Changes in v3:
- Use driver model for the PMIC

 drivers/power/Makefile |   1 +
 drivers/power/as3722.c | 264 +++++++++++++++++++++++++++++++++++++++++++++++++
 include/fdtdec.h       |   1 +
 include/power/as3722.h |  27 +++++
 lib/fdtdec.c           |   1 +
 5 files changed, 294 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 dc64e4d..b309731 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 0000000..1a6ebcc
--- /dev/null
+++ b/drivers/power/as3722.c
@@ -0,0 +1,264 @@
+/*
+ * Copyright (C) 2014 NVIDIA Corporation
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+#define pr_fmt(fmt) "as3722: " fmt
+
+#include <common.h>
+#include <dm.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
+
+static int as3722_read(struct udevice *pmic, u8 reg, u8 *value)
+{
+	int err;
+
+	err = i2c_read(pmic, reg, value, 1);
+	if (err < 0)
+		return err;
+
+	return 0;
+}
+
+static int as3722_write(struct udevice *pmic, u8 reg, u8 value)
+{
+	int err;
+
+	err = i2c_write(pmic, reg, &value, 1);
+	if (err < 0)
+		return err;
+
+	return 0;
+}
+
+static int as3722_read_id(struct udevice *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 udevice *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 udevice *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 udevice *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 udevice *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 udevice *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 udevice *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 udevice *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 udevice **devp)
+{
+	struct udevice *pmic;
+	u8 id, revision;
+	int bus = 0;
+	int address = 0x40;
+	int err;
+
+	err = i2c_get_chip_for_busnum(bus, address, &pmic);
+	if (err)
+		return err;
+	err = as3722_read_id(pmic, &id, &revision);
+	if (err < 0) {
+		error("failed to read ID: %d", err);
+		return err;
+	}
+
+	if (id != AS3722_DEVICE_ID) {
+		error("unknown device");
+		return -ENOENT;
+	}
+
+	debug("AS3722 revision %#x found on I2C bus %u, address %#x\n",
+	      revision, bus, address);
+	*devp = pmic;
+
+	return 0;
+}
diff --git a/include/fdtdec.h b/include/fdtdec.h
index 4ae77be..782d6ca 100644
--- a/include/fdtdec.h
+++ b/include/fdtdec.h
@@ -118,6 +118,7 @@ enum fdt_compat_id {
 	COMPAT_SAMSUNG_EXYNOS_SYSMMU,	/* Exynos sysmmu */
 	COMPAT_PARADE_PS8625,		/* Parade PS8622 EDP->LVDS bridge */
 	COMPAT_INTEL_LPC,		/* Intel Low Pin Count I/F */
+	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 0000000..aa966d2
--- /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 udevice;
+
+int as3722_init(struct udevice **devp);
+int as3722_sd_enable(struct udevice *pmic, unsigned int sd);
+int as3722_sd_set_voltage(struct udevice *pmic, unsigned int sd, u8 value);
+int as3722_ldo_enable(struct udevice *pmic, unsigned int ldo);
+int as3722_ldo_set_voltage(struct udevice *pmic, unsigned int ldo, u8 value);
+int as3722_gpio_configure(struct udevice *pmic, unsigned int gpio,
+			  unsigned long flags);
+int as3722_gpio_direction_output(struct udevice *pmic, unsigned int gpio,
+				 unsigned int level);
+
+#endif /* __POWER_AS3722_H__ */
diff --git a/lib/fdtdec.c b/lib/fdtdec.c
index da6ef6b..378002a 100644
--- a/lib/fdtdec.c
+++ b/lib/fdtdec.c
@@ -73,6 +73,7 @@ static const char * const compat_names[COMPAT_COUNT] = {
 	COMPAT(SAMSUNG_EXYNOS_SYSMMU, "samsung,sysmmu-v3.3"),
 	COMPAT(PARADE_PS8625, "parade,ps8625"),
 	COMPAT(COMPAT_INTEL_LPC, "intel,lpc"),
+	COMPAT(AMS_AS3722, "ams,as3722"),
 };
 
 const char *fdtdec_get_compatible(enum fdt_compat_id id)
-- 
2.1.0.rc2.206.gedb03e5

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

* [U-Boot] [PATCH v3 06/30] ARM: tegra: Implement tegra_plle_enable()
  2014-11-13  1:26 [U-Boot] [PATCH v3 0/30] ARM: tegra: Add PCIe support Simon Glass
                   ` (4 preceding siblings ...)
  2014-11-13  1:26 ` [U-Boot] [PATCH v3 05/30] power: Add AMS AS3722 PMIC support Simon Glass
@ 2014-11-13  1:26 ` Simon Glass
  2014-11-13  1:26 ` [U-Boot] [PATCH v3 07/30] ARM: tegra: Provide PCIEXCLK reset ID Simon Glass
                   ` (23 subsequent siblings)
  29 siblings, 0 replies; 45+ messages in thread
From: Simon Glass @ 2014-11-13  1:26 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>
Signed-off-by: Simon Glass <sjg@chromium.org>
---

Changes in v3: None

 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 7394363..fc8bd19 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 0c4f5fb..d55fbc8 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 80ba2d8..8e5c498 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 8e39d21..8e65086 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 889c65a..4df8da9 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 2f24a75..410c352 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.1.0.rc2.206.gedb03e5

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

* [U-Boot] [PATCH v3 07/30] ARM: tegra: Provide PCIEXCLK reset ID
  2014-11-13  1:26 [U-Boot] [PATCH v3 0/30] ARM: tegra: Add PCIe support Simon Glass
                   ` (5 preceding siblings ...)
  2014-11-13  1:26 ` [U-Boot] [PATCH v3 06/30] ARM: tegra: Implement tegra_plle_enable() Simon Glass
@ 2014-11-13  1:26 ` Simon Glass
  2014-11-13  1:26 ` [U-Boot] [PATCH v3 08/30] ARM: tegra: Implement powergate support Simon Glass
                   ` (22 subsequent siblings)
  29 siblings, 0 replies; 45+ messages in thread
From: Simon Glass @ 2014-11-13  1:26 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>
Signed-off-by: Simon Glass <sjg@chromium.org>
---

Changes in v3: None

 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 d55fbc8..7b9e10c 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 8e5c498..0eb0f0a 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 a09cb01..894be08 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.1.0.rc2.206.gedb03e5

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

* [U-Boot] [PATCH v3 08/30] ARM: tegra: Implement powergate support
  2014-11-13  1:26 [U-Boot] [PATCH v3 0/30] ARM: tegra: Add PCIe support Simon Glass
                   ` (6 preceding siblings ...)
  2014-11-13  1:26 ` [U-Boot] [PATCH v3 07/30] ARM: tegra: Provide PCIEXCLK reset ID Simon Glass
@ 2014-11-13  1:26 ` Simon Glass
  2014-11-13  1:26 ` [U-Boot] [PATCH v3 09/30] ARM: tegra: Implement XUSB pad controller Simon Glass
                   ` (21 subsequent siblings)
  29 siblings, 0 replies; 45+ messages in thread
From: Simon Glass @ 2014-11-13  1:26 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>
Signed-off-by: Simon Glass <sjg@chromium.org>
---

Changes in v3: None

 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 a18c318..c7603ee 100644
--- a/arch/arm/cpu/tegra-common/Makefile
+++ b/arch/arm/cpu/tegra-common/Makefile
@@ -13,5 +13,6 @@ 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
 obj-$(CONFIG_TEGRA124) += vpr.o
diff --git a/arch/arm/cpu/tegra-common/powergate.c b/arch/arm/cpu/tegra-common/powergate.c
new file mode 100644
index 0000000..439cff3
--- /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 0000000..130b58b
--- /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 0000000..260ea80
--- /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 0000000..8a0cfba
--- /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 0000000..439d88b
--- /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 0000000..c70e44b
--- /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.1.0.rc2.206.gedb03e5

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

* [U-Boot] [PATCH v3 09/30] ARM: tegra: Implement XUSB pad controller
  2014-11-13  1:26 [U-Boot] [PATCH v3 0/30] ARM: tegra: Add PCIe support Simon Glass
                   ` (7 preceding siblings ...)
  2014-11-13  1:26 ` [U-Boot] [PATCH v3 08/30] ARM: tegra: Implement powergate support Simon Glass
@ 2014-11-13  1:26 ` Simon Glass
  2014-11-13  1:26 ` [U-Boot] [PATCH v3 10/30] ARM: tegra: Add XUSB pad controller on Tegra124 Simon Glass
                   ` (20 subsequent siblings)
  29 siblings, 0 replies; 45+ messages in thread
From: Simon Glass @ 2014-11-13  1:26 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>
Signed-off-by: Simon Glass <sjg@chromium.org>
---

Changes in v3: None

 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 c7603ee..a78869e 100644
--- a/arch/arm/cpu/tegra-common/Makefile
+++ b/arch/arm/cpu/tegra-common/Makefile
@@ -14,5 +14,6 @@ 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
 obj-$(CONFIG_TEGRA124) += vpr.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 0000000..65f8d2e
--- /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 ff77992..7b59fb1 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 0000000..43af883
--- /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 0000000..b4b4c8b
--- /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 769fe59..4fa7235 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"
@@ -129,6 +130,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 0000000..914d56d
--- /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 782d6ca..e756f42 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 378002a..ffae4cf 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.1.0.rc2.206.gedb03e5

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

* [U-Boot] [PATCH v3 10/30] ARM: tegra: Add XUSB pad controller on Tegra124
  2014-11-13  1:26 [U-Boot] [PATCH v3 0/30] ARM: tegra: Add PCIe support Simon Glass
                   ` (8 preceding siblings ...)
  2014-11-13  1:26 ` [U-Boot] [PATCH v3 09/30] ARM: tegra: Implement XUSB pad controller Simon Glass
@ 2014-11-13  1:26 ` Simon Glass
  2014-11-13  1:26 ` [U-Boot] [PATCH v3 11/30] ARM: tegra: Enable XUSB pad controller on Jetson TK1 Simon Glass
                   ` (19 subsequent siblings)
  29 siblings, 0 replies; 45+ messages in thread
From: Simon Glass @ 2014-11-13  1:26 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>
Signed-off-by: Simon Glass <sjg@chromium.org>
---

Changes in v3: None

 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 3288f28..a756336 100644
--- a/arch/arm/dts/tegra124.dtsi
+++ b/arch/arm/dts/tegra124.dtsi
@@ -1,6 +1,7 @@
 #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>
 
 #include "skeleton.dtsi"
 
@@ -258,6 +259,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.1.0.rc2.206.gedb03e5

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

* [U-Boot] [PATCH v3 11/30] ARM: tegra: Enable XUSB pad controller on Jetson TK1
  2014-11-13  1:26 [U-Boot] [PATCH v3 0/30] ARM: tegra: Add PCIe support Simon Glass
                   ` (9 preceding siblings ...)
  2014-11-13  1:26 ` [U-Boot] [PATCH v3 10/30] ARM: tegra: Add XUSB pad controller on Tegra124 Simon Glass
@ 2014-11-13  1:26 ` Simon Glass
  2014-11-13  1:26 ` [U-Boot] [PATCH v3 12/30] pci: tegra: Add Tegra PCIe driver Simon Glass
                   ` (18 subsequent siblings)
  29 siblings, 0 replies; 45+ messages in thread
From: Simon Glass @ 2014-11-13  1:26 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>
Signed-off-by: Simon Glass <sjg@chromium.org>
---

Changes in v3: None

 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 f6fe9a0..91b4c1d 100644
--- a/arch/arm/dts/tegra124-jetson-tk1.dts
+++ b/arch/arm/dts/tegra124-jetson-tk1.dts
@@ -69,6 +69,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.1.0.rc2.206.gedb03e5

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

* [U-Boot] [PATCH v3 12/30] pci: tegra: Add Tegra PCIe driver
  2014-11-13  1:26 [U-Boot] [PATCH v3 0/30] ARM: tegra: Add PCIe support Simon Glass
                   ` (10 preceding siblings ...)
  2014-11-13  1:26 ` [U-Boot] [PATCH v3 11/30] ARM: tegra: Enable XUSB pad controller on Jetson TK1 Simon Glass
@ 2014-11-13  1:26 ` Simon Glass
  2014-11-13  1:26 ` [U-Boot] [PATCH v3 13/30] ARM: tegra: Add Tegra20 PCIe device tree node Simon Glass
                   ` (17 subsequent siblings)
  29 siblings, 0 replies; 45+ messages in thread
From: Simon Glass @ 2014-11-13  1:26 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>
Signed-off-by: Simon Glass <sjg@chromium.org>
---

Changes in v3: None

 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 e73a498..8eb2320 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 0000000..a03ad5f
--- /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 e756f42..49a9ab5 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 ffae4cf..0bbf5e1 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.1.0.rc2.206.gedb03e5

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

* [U-Boot] [PATCH v3 13/30] ARM: tegra: Add Tegra20 PCIe device tree node
  2014-11-13  1:26 [U-Boot] [PATCH v3 0/30] ARM: tegra: Add PCIe support Simon Glass
                   ` (11 preceding siblings ...)
  2014-11-13  1:26 ` [U-Boot] [PATCH v3 12/30] pci: tegra: Add Tegra PCIe driver Simon Glass
@ 2014-11-13  1:26 ` Simon Glass
  2014-11-13  1:27 ` [U-Boot] [PATCH v3 14/30] ARM: tegra: Enable PCIe on TrimSlice Simon Glass
                   ` (16 subsequent siblings)
  29 siblings, 0 replies; 45+ messages in thread
From: Simon Glass @ 2014-11-13  1:26 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>
Signed-off-by: Simon Glass <sjg@chromium.org>
---

Changes in v3: None

 arch/arm/dts/tegra20.dtsi               | 59 +++++++++++++++++++++++++++++++++
 include/dt-bindings/clock/tegra20-car.h |  2 +-
 2 files changed, 60 insertions(+), 1 deletion(-)

diff --git a/arch/arm/dts/tegra20.dtsi b/arch/arm/dts/tegra20.dtsi
index 5f927f7..b8c8a92 100644
--- a/arch/arm/dts/tegra20.dtsi
+++ b/arch/arm/dts/tegra20.dtsi
@@ -332,6 +332,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
index 9406207..a1ae9a8 100644
--- a/include/dt-bindings/clock/tegra20-car.h
+++ b/include/dt-bindings/clock/tegra20-car.h
@@ -92,7 +92,7 @@
 #define TEGRA20_CLK_OWR 71
 #define TEGRA20_CLK_AFI 72
 #define TEGRA20_CLK_CSITE 73
-/* 74 */
+#define TEGRA20_CLK_PCIE_XCLK 74
 #define TEGRA20_CLK_AVPUCQ 75
 #define TEGRA20_CLK_LA 76
 /* 77 */
-- 
2.1.0.rc2.206.gedb03e5

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

* [U-Boot] [PATCH v3 14/30] ARM: tegra: Enable PCIe on TrimSlice
  2014-11-13  1:26 [U-Boot] [PATCH v3 0/30] ARM: tegra: Add PCIe support Simon Glass
                   ` (12 preceding siblings ...)
  2014-11-13  1:26 ` [U-Boot] [PATCH v3 13/30] ARM: tegra: Add Tegra20 PCIe device tree node Simon Glass
@ 2014-11-13  1:27 ` Simon Glass
  2014-11-13  1:27 ` [U-Boot] [PATCH v3 15/30] ARM: tegra: Add GIC for Tegra30 Simon Glass
                   ` (15 subsequent siblings)
  29 siblings, 0 replies; 45+ messages in thread
From: Simon Glass @ 2014-11-13  1:27 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>
Signed-off-by: Simon Glass <sjg@chromium.org>
---

Changes in v3: None

 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 74e8a16..1637cbd 100644
--- a/arch/arm/dts/tegra20-trimslice.dts
+++ b/arch/arm/dts/tegra20-trimslice.dts
@@ -47,6 +47,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 */
 	};
@@ -66,4 +80,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 723293f..c9da80d 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 a254f86..59f4f67 100644
--- a/include/configs/trimslice.h
+++ b/include/configs/trimslice.h
@@ -60,6 +60,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.1.0.rc2.206.gedb03e5

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

* [U-Boot] [PATCH v3 15/30] ARM: tegra: Add GIC for Tegra30
  2014-11-13  1:26 [U-Boot] [PATCH v3 0/30] ARM: tegra: Add PCIe support Simon Glass
                   ` (13 preceding siblings ...)
  2014-11-13  1:27 ` [U-Boot] [PATCH v3 14/30] ARM: tegra: Enable PCIe on TrimSlice Simon Glass
@ 2014-11-13  1:27 ` Simon Glass
  2014-11-13  1:27 ` [U-Boot] [PATCH v3 16/30] ARM: tegra: Add Tegra30 PCIe device tree node Simon Glass
                   ` (14 subsequent siblings)
  29 siblings, 0 replies; 45+ messages in thread
From: Simon Glass @ 2014-11-13  1:27 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>
Signed-off-by: Simon Glass <sjg@chromium.org>
---

Changes in v3: None

 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 fb92a0f..1db334a 100644
--- a/arch/arm/dts/tegra30.dtsi
+++ b/arch/arm/dts/tegra30.dtsi
@@ -6,6 +6,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.1.0.rc2.206.gedb03e5

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

* [U-Boot] [PATCH v3 16/30] ARM: tegra: Add Tegra30 PCIe device tree node
  2014-11-13  1:26 [U-Boot] [PATCH v3 0/30] ARM: tegra: Add PCIe support Simon Glass
                   ` (14 preceding siblings ...)
  2014-11-13  1:27 ` [U-Boot] [PATCH v3 15/30] ARM: tegra: Add GIC for Tegra30 Simon Glass
@ 2014-11-13  1:27 ` Simon Glass
  2014-11-13  1:27 ` [U-Boot] [PATCH v3 17/30] ARM: tegra: Enable PCIe on Cardhu Simon Glass
                   ` (13 subsequent siblings)
  29 siblings, 0 replies; 45+ messages in thread
From: Simon Glass @ 2014-11-13  1:27 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>
Signed-off-by: Simon Glass <sjg@chromium.org>
---

Changes in v3: None

 arch/arm/dts/tegra30.dtsi               | 74 +++++++++++++++++++++++++++++++++
 include/dt-bindings/clock/tegra30-car.h |  2 +-
 2 files changed, 75 insertions(+), 1 deletion(-)

diff --git a/arch/arm/dts/tegra30.dtsi b/arch/arm/dts/tegra30.dtsi
index 1db334a..5ea7e34 100644
--- a/arch/arm/dts/tegra30.dtsi
+++ b/arch/arm/dts/tegra30.dtsi
@@ -16,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
index 889e49b..2244582 100644
--- a/include/dt-bindings/clock/tegra30-car.h
+++ b/include/dt-bindings/clock/tegra30-car.h
@@ -92,7 +92,7 @@
 #define TEGRA30_CLK_OWR 71
 #define TEGRA30_CLK_AFI 72
 #define TEGRA30_CLK_CSITE 73
-/* 74 */
+#define TEGRA30_CLK_PCIEX 74
 #define TEGRA30_CLK_AVPUCQ 75
 #define TEGRA30_CLK_LA 76
 /* 77 */
-- 
2.1.0.rc2.206.gedb03e5

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

* [U-Boot] [PATCH v3 17/30] ARM: tegra: Enable PCIe on Cardhu
  2014-11-13  1:26 [U-Boot] [PATCH v3 0/30] ARM: tegra: Add PCIe support Simon Glass
                   ` (15 preceding siblings ...)
  2014-11-13  1:27 ` [U-Boot] [PATCH v3 16/30] ARM: tegra: Add Tegra30 PCIe device tree node Simon Glass
@ 2014-11-13  1:27 ` Simon Glass
  2014-11-13  1:27 ` [U-Boot] [PATCH v3 18/30] ARM: tegra: Enable PCIe on Beaver Simon Glass
                   ` (12 subsequent siblings)
  29 siblings, 0 replies; 45+ messages in thread
From: Simon Glass @ 2014-11-13  1:27 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>
Signed-off-by: Simon Glass <sjg@chromium.org>
---

Changes in v3:
- Use driver model to access the PMIC

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

diff --git a/arch/arm/dts/tegra30-cardhu.dts b/arch/arm/dts/tegra30-cardhu.dts
index 1b8ed73..e13d0fb 100644
--- a/arch/arm/dts/tegra30-cardhu.dts
+++ b/arch/arm/dts/tegra30-cardhu.dts
@@ -27,6 +27,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>;
@@ -50,6 +75,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 {
@@ -74,4 +200,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 026f45c..95c4ff2 100644
--- a/board/nvidia/cardhu/cardhu.c
+++ b/board/nvidia/cardhu/cardhu.c
@@ -9,8 +9,11 @@
 #include <dm.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
@@ -83,3 +86,52 @@ void pin_mux_mmc(void)
 	board_sdmmc_voltage_init();
 }
 #endif	/* MMC */
+
+#ifdef CONFIG_PCI_TEGRA
+int tegra_pcie_board_init(void)
+{
+	struct udevice *dev;
+	u8 addr, data[1];
+	int err;
+
+	err = i2c_get_chip_for_busnum(0, PMU_I2C_ADDRESS, &dev);
+	if (err) {
+		debug("failed to find PMU bus\n");
+		return err;
+	}
+
+	/* TPS659110: LDO1_REG = 1.05V, ACTIVE */
+	data[0] = 0x15;
+	addr = 0x30;
+
+	err = i2c_write(dev, addr, 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(dev, addr, data, 1);
+	if (err) {
+		debug("failed to set AVDD supply\n");
+		return err;
+	}
+
+	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 758b7ad..5e13b65 100644
--- a/include/configs/cardhu.h
+++ b/include/configs/cardhu.h
@@ -78,6 +78,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.1.0.rc2.206.gedb03e5

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

* [U-Boot] [PATCH v3 18/30] ARM: tegra: Enable PCIe on Beaver
  2014-11-13  1:26 [U-Boot] [PATCH v3 0/30] ARM: tegra: Add PCIe support Simon Glass
                   ` (16 preceding siblings ...)
  2014-11-13  1:27 ` [U-Boot] [PATCH v3 17/30] ARM: tegra: Enable PCIe on Cardhu Simon Glass
@ 2014-11-13  1:27 ` Simon Glass
  2014-11-13  1:27 ` [U-Boot] [PATCH v3 19/30] ARM: tegra: Add GIC for Tegra124 Simon Glass
                   ` (11 subsequent siblings)
  29 siblings, 0 replies; 45+ messages in thread
From: Simon Glass @ 2014-11-13  1:27 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>
Signed-off-by: Simon Glass <sjg@chromium.org>
---

Changes in v3: None

 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 9acd84d..5903af6 100644
--- a/arch/arm/dts/tegra30-beaver.dts
+++ b/arch/arm/dts/tegra30-beaver.dts
@@ -28,6 +28,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>;
@@ -51,6 +78,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 {
@@ -86,4 +217,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 5d765f3..5df460c 100644
--- a/include/configs/beaver.h
+++ b/include/configs/beaver.h
@@ -76,6 +76,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.1.0.rc2.206.gedb03e5

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

* [U-Boot] [PATCH v3 19/30] ARM: tegra: Add GIC for Tegra124
  2014-11-13  1:26 [U-Boot] [PATCH v3 0/30] ARM: tegra: Add PCIe support Simon Glass
                   ` (17 preceding siblings ...)
  2014-11-13  1:27 ` [U-Boot] [PATCH v3 18/30] ARM: tegra: Enable PCIe on Beaver Simon Glass
@ 2014-11-13  1:27 ` Simon Glass
  2014-11-13  1:27 ` [U-Boot] [PATCH v3 20/30] ARM: tegra: Add Tegra124 PCIe device tree node Simon Glass
                   ` (10 subsequent siblings)
  29 siblings, 0 replies; 45+ messages in thread
From: Simon Glass @ 2014-11-13  1:27 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>
Signed-off-by: Simon Glass <sjg@chromium.org>
---

Changes in v3: None

 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 a756336..1b603d2 100644
--- a/arch/arm/dts/tegra124.dtsi
+++ b/arch/arm/dts/tegra124.dtsi
@@ -7,6 +7,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.1.0.rc2.206.gedb03e5

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

* [U-Boot] [PATCH v3 20/30] ARM: tegra: Add Tegra124 PCIe device tree node
  2014-11-13  1:26 [U-Boot] [PATCH v3 0/30] ARM: tegra: Add PCIe support Simon Glass
                   ` (18 preceding siblings ...)
  2014-11-13  1:27 ` [U-Boot] [PATCH v3 19/30] ARM: tegra: Add GIC for Tegra124 Simon Glass
@ 2014-11-13  1:27 ` Simon Glass
  2014-11-13  1:27 ` [U-Boot] [PATCH v3 21/30] ARM: tegra: Enable PCIe on Jetson TK1 Simon Glass
                   ` (9 subsequent siblings)
  29 siblings, 0 replies; 45+ messages in thread
From: Simon Glass @ 2014-11-13  1:27 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>
Signed-off-by: Simon Glass <sjg@chromium.org>
---

Changes in v3: None

 arch/arm/dts/tegra124.dtsi | 66 ++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 66 insertions(+)

diff --git a/arch/arm/dts/tegra124.dtsi b/arch/arm/dts/tegra124.dtsi
index 1b603d2..40f8609 100644
--- a/arch/arm/dts/tegra124.dtsi
+++ b/arch/arm/dts/tegra124.dtsi
@@ -9,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>;
-- 
2.1.0.rc2.206.gedb03e5

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

* [U-Boot] [PATCH v3 21/30] ARM: tegra: Enable PCIe on Jetson TK1
  2014-11-13  1:26 [U-Boot] [PATCH v3 0/30] ARM: tegra: Add PCIe support Simon Glass
                   ` (19 preceding siblings ...)
  2014-11-13  1:27 ` [U-Boot] [PATCH v3 20/30] ARM: tegra: Add Tegra124 PCIe device tree node Simon Glass
@ 2014-11-13  1:27 ` Simon Glass
  2014-11-13  1:27 ` [U-Boot] [PATCH v3 22/30] ARM: cache_v7: Various minor cleanups Simon Glass
                   ` (8 subsequent siblings)
  29 siblings, 0 replies; 45+ messages in thread
From: Simon Glass @ 2014-11-13  1:27 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>
Signed-off-by: Simon Glass <sjg@chromium.org>
---

Changes in v3:
- Use driver model to access the PMIC

 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 91b4c1d..51fef54 100644
--- a/arch/arm/dts/tegra124-jetson-tk1.dts
+++ b/arch/arm/dts/tegra124-jetson-tk1.dts
@@ -29,6 +29,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>;
@@ -49,9 +69,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 {
@@ -117,4 +323,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 5d37718..daa74a4 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 udevice *pmic;
+	int err;
+
+	err = as3722_init(&pmic);
+	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 a7d7665..0a79c7c 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"
 
 /* High-level configuration options */
@@ -61,6 +64,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.1.0.rc2.206.gedb03e5

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

* [U-Boot] [PATCH v3 22/30] ARM: cache_v7: Various minor cleanups
  2014-11-13  1:26 [U-Boot] [PATCH v3 0/30] ARM: tegra: Add PCIe support Simon Glass
                   ` (20 preceding siblings ...)
  2014-11-13  1:27 ` [U-Boot] [PATCH v3 21/30] ARM: tegra: Enable PCIe on Jetson TK1 Simon Glass
@ 2014-11-13  1:27 ` Simon Glass
  2014-11-14  8:00   ` Albert ARIBAUD
  2014-11-13  1:27 ` [U-Boot] [PATCH v3 23/30] ARM: cache-cp15: Use more accurate types Simon Glass
                   ` (7 subsequent siblings)
  29 siblings, 1 reply; 45+ messages in thread
From: Simon Glass @ 2014-11-13  1:27 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>
Acked-by: Simon Glass <sjg@chromium.org>
Signed-off-by: Simon Glass <sjg@chromium.org>
---

Changes in v3: None

 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 a2c4032..0f9d837 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.1.0.rc2.206.gedb03e5

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

* [U-Boot] [PATCH v3 23/30] ARM: cache-cp15: Use more accurate types
  2014-11-13  1:26 [U-Boot] [PATCH v3 0/30] ARM: tegra: Add PCIe support Simon Glass
                   ` (21 preceding siblings ...)
  2014-11-13  1:27 ` [U-Boot] [PATCH v3 22/30] ARM: cache_v7: Various minor cleanups Simon Glass
@ 2014-11-13  1:27 ` Simon Glass
  2014-11-14  8:00   ` Albert ARIBAUD
  2014-11-13  1:27 ` [U-Boot] [PATCH v3 24/30] malloc: Output region when debugging Simon Glass
                   ` (6 subsequent siblings)
  29 siblings, 1 reply; 45+ messages in thread
From: Simon Glass @ 2014-11-13  1:27 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>
Signed-off-by: Simon Glass <sjg@chromium.org>
---

Changes in v3: None

 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 ca2d44f..61e2914 100644
--- a/arch/arm/include/asm/system.h
+++ b/arch/arm/include/asm/system.h
@@ -201,7 +201,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 2155fe8..0291afa 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.1.0.rc2.206.gedb03e5

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

* [U-Boot] [PATCH v3 24/30] malloc: Output region when debugging
  2014-11-13  1:26 [U-Boot] [PATCH v3 0/30] ARM: tegra: Add PCIe support Simon Glass
                   ` (22 preceding siblings ...)
  2014-11-13  1:27 ` [U-Boot] [PATCH v3 23/30] ARM: cache-cp15: Use more accurate types Simon Glass
@ 2014-11-13  1:27 ` Simon Glass
  2014-11-24 22:11   ` [U-Boot] [U-Boot, v3, " Tom Rini
  2014-11-13  1:27 ` [U-Boot] [PATCH v3 25/30] ARM: Implement non-cached memory support Simon Glass
                   ` (5 subsequent siblings)
  29 siblings, 1 reply; 45+ messages in thread
From: Simon Glass @ 2014-11-13  1:27 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>
Acked-by: Simon Glass <sjg@chromium.org>
Signed-off-by: Simon Glass <sjg@chromium.org>
---

Changes in v3: None

 common/dlmalloc.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/common/dlmalloc.c b/common/dlmalloc.c
index d87834d..991229d 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.1.0.rc2.206.gedb03e5

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

* [U-Boot] [PATCH v3 25/30] ARM: Implement non-cached memory support
  2014-11-13  1:26 [U-Boot] [PATCH v3 0/30] ARM: tegra: Add PCIe support Simon Glass
                   ` (23 preceding siblings ...)
  2014-11-13  1:27 ` [U-Boot] [PATCH v3 24/30] malloc: Output region when debugging Simon Glass
@ 2014-11-13  1:27 ` Simon Glass
  2014-11-13  1:27 ` [U-Boot] [PATCH v3 26/30] ARM: tegra: Enable non-cached memory Simon Glass
                   ` (4 subsequent siblings)
  29 siblings, 0 replies; 45+ messages in thread
From: Simon Glass @ 2014-11-13  1:27 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>
Signed-off-by: Simon Glass <sjg@chromium.org>
---

Changes in v3:
- Avoid build error with noncached_init() when the dcache is disabled

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

diff --git a/README b/README
index c3a9dfc..717a88b 100644
--- a/README
+++ b/README
@@ -3877,6 +3877,25 @@ Configuration Settings:
 		Pre-relocation malloc() is only supported on ARM and sandbox
 		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 61e2914..89f2294 100644
--- a/arch/arm/include/asm/system.h
+++ b/arch/arm/include/asm/system.h
@@ -212,6 +212,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 4e597a4..6c2dfa1 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,46 @@ __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;
+
+#ifndef CONFIG_SYS_DCACHE_OFF
+	mmu_set_region_dcache_behaviour(noncached_start, size, DCACHE_OFF);
+#endif
+}
+
+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 7c33900..2fe0e8b 100644
--- a/common/board_r.c
+++ b/common/board_r.c
@@ -264,6 +264,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)
 {
@@ -716,6 +724,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.1.0.rc2.206.gedb03e5

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

* [U-Boot] [PATCH v3 26/30] ARM: tegra: Enable non-cached memory
  2014-11-13  1:26 [U-Boot] [PATCH v3 0/30] ARM: tegra: Add PCIe support Simon Glass
                   ` (24 preceding siblings ...)
  2014-11-13  1:27 ` [U-Boot] [PATCH v3 25/30] ARM: Implement non-cached memory support Simon Glass
@ 2014-11-13  1:27 ` Simon Glass
  2014-11-13  1:27 ` [U-Boot] [PATCH v3 27/30] net: rtl8169: Honor CONFIG_SYS_RX_ETH_BUFFER Simon Glass
                   ` (3 subsequent siblings)
  29 siblings, 0 replies; 45+ messages in thread
From: Simon Glass @ 2014-11-13  1:27 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>
Signed-off-by: Simon Glass <sjg@chromium.org>
---

Changes in v3: None

 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 ac9858d..379b2d8 100644
--- a/include/configs/tegra-common.h
+++ b/include/configs/tegra-common.h
@@ -48,6 +48,7 @@
  */
 #define CONFIG_SYS_MALLOC_LEN		(4 << 20)	/* 4MB  */
 #define CONFIG_SYS_MALLOC_F_LEN	(1 << 10)
+#define CONFIG_SYS_NONCACHED_MEMORY	(1 << 20)	/* 1 MiB */
 
 /*
  * NS16550 Configuration
-- 
2.1.0.rc2.206.gedb03e5

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

* [U-Boot] [PATCH v3 27/30] net: rtl8169: Honor CONFIG_SYS_RX_ETH_BUFFER
  2014-11-13  1:26 [U-Boot] [PATCH v3 0/30] ARM: tegra: Add PCIe support Simon Glass
                   ` (25 preceding siblings ...)
  2014-11-13  1:27 ` [U-Boot] [PATCH v3 26/30] ARM: tegra: Enable non-cached memory Simon Glass
@ 2014-11-13  1:27 ` Simon Glass
  2014-11-13  1:27 ` [U-Boot] [PATCH v3 28/30] net: rtl8169: Properly align buffers Simon Glass
                   ` (2 subsequent siblings)
  29 siblings, 0 replies; 45+ messages in thread
From: Simon Glass @ 2014-11-13  1:27 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>
Signed-off-by: Simon Glass <sjg@chromium.org>
---

Changes in v3: None

 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 c3ce175..955b2e1 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.1.0.rc2.206.gedb03e5

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

* [U-Boot] [PATCH v3 28/30] net: rtl8169: Properly align buffers
  2014-11-13  1:26 [U-Boot] [PATCH v3 0/30] ARM: tegra: Add PCIe support Simon Glass
                   ` (26 preceding siblings ...)
  2014-11-13  1:27 ` [U-Boot] [PATCH v3 27/30] net: rtl8169: Honor CONFIG_SYS_RX_ETH_BUFFER Simon Glass
@ 2014-11-13  1:27 ` Simon Glass
  2014-11-13  1:27 ` [U-Boot] [PATCH v3 29/30] net: rtl8169: Use non-cached memory if available Simon Glass
  2014-11-13  1:27 ` [U-Boot] [PATCH v3 30/30] net: rtl8169: Add support for RTL-8168/8111g Simon Glass
  29 siblings, 0 replies; 45+ messages in thread
From: Simon Glass @ 2014-11-13  1:27 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>
Signed-off-by: Simon Glass <sjg@chromium.org>
---

Changes in v3: None

 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 955b2e1..fc8c31e 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  */
@@ -711,16 +727,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
@@ -762,10 +768,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;
 	}
@@ -910,6 +912,9 @@ static int rtl_init(struct eth_device *dev, bd_t *bis)
 #endif
 	}
 
+	tpc->TxDescArray = tx_ring;
+	tpc->RxDescArray = rx_ring;
+
 	return 1;
 }
 
-- 
2.1.0.rc2.206.gedb03e5

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

* [U-Boot] [PATCH v3 29/30] net: rtl8169: Use non-cached memory if available
  2014-11-13  1:26 [U-Boot] [PATCH v3 0/30] ARM: tegra: Add PCIe support Simon Glass
                   ` (27 preceding siblings ...)
  2014-11-13  1:27 ` [U-Boot] [PATCH v3 28/30] net: rtl8169: Properly align buffers Simon Glass
@ 2014-11-13  1:27 ` Simon Glass
  2014-11-17 10:16   ` Thierry Reding
  2014-11-13  1:27 ` [U-Boot] [PATCH v3 30/30] net: rtl8169: Add support for RTL-8168/8111g Simon Glass
  29 siblings, 1 reply; 45+ messages in thread
From: Simon Glass @ 2014-11-13  1:27 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>
Signed-off-by: Simon Glass <sjg@chromium.org>
---

Changes in v3:
- Remove cache-line size warning if dcache is disabled

 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 fc8c31e..cd26c36 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
+#if !defined(CONFIG_SYS_NONCACHED_MEMORY) && !defined(CONFIG_SYS_DCACHE_OFF)
 #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)
@@ -912,10 +949,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)
@@ -929,6 +972,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)
@@ -967,9 +1011,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.1.0.rc2.206.gedb03e5

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

* [U-Boot] [PATCH v3 30/30] net: rtl8169: Add support for RTL-8168/8111g
  2014-11-13  1:26 [U-Boot] [PATCH v3 0/30] ARM: tegra: Add PCIe support Simon Glass
                   ` (28 preceding siblings ...)
  2014-11-13  1:27 ` [U-Boot] [PATCH v3 29/30] net: rtl8169: Use non-cached memory if available Simon Glass
@ 2014-11-13  1:27 ` Simon Glass
  2014-11-17 10:14   ` Thierry Reding
  29 siblings, 1 reply; 45+ messages in thread
From: Simon Glass @ 2014-11-13  1:27 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>
Signed-off-by: Simon Glass <sjg@chromium.org>
---

Changes in v3: None

 drivers/net/rtl8169.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/net/rtl8169.c b/drivers/net/rtl8169.c
index cd26c36..e4705ce 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.1.0.rc2.206.gedb03e5

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

* [U-Boot] [PATCH v3 22/30] ARM: cache_v7: Various minor cleanups
  2014-11-13  1:27 ` [U-Boot] [PATCH v3 22/30] ARM: cache_v7: Various minor cleanups Simon Glass
@ 2014-11-14  8:00   ` Albert ARIBAUD
  2014-11-15  1:54     ` Simon Glass
  0 siblings, 1 reply; 45+ messages in thread
From: Albert ARIBAUD @ 2014-11-14  8:00 UTC (permalink / raw)
  To: u-boot

Hello Simon,

I've actually applied v2 of this patch and PRed it to u-boot/master)
and accidentally not acked it.

Apologies.

On Wed, 12 Nov 2014 18:27:08 -0700, Simon Glass <sjg@chromium.org>
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>
> Signed-off-by: Simon Glass <sjg@chromium.org>
> ---
> 
> Changes in v3: None
> 
>  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 a2c4032..0f9d837 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.1.0.rc2.206.gedb03e5
> 



Amicalement,
-- 
Albert.

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

* [U-Boot] [PATCH v3 23/30] ARM: cache-cp15: Use more accurate types
  2014-11-13  1:27 ` [U-Boot] [PATCH v3 23/30] ARM: cache-cp15: Use more accurate types Simon Glass
@ 2014-11-14  8:00   ` Albert ARIBAUD
  0 siblings, 0 replies; 45+ messages in thread
From: Albert ARIBAUD @ 2014-11-14  8:00 UTC (permalink / raw)
  To: u-boot

Hello Simon,

I've actually applied v2 of this patch and PRed it to u-boot/master)
and accidentally not acked it.

Apologies.

On Wed, 12 Nov 2014 18:27:09 -0700, Simon Glass <sjg@chromium.org>
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>
> Signed-off-by: Simon Glass <sjg@chromium.org>
> ---
> 
> Changes in v3: None
> 
>  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 ca2d44f..61e2914 100644
> --- a/arch/arm/include/asm/system.h
> +++ b/arch/arm/include/asm/system.h
> @@ -201,7 +201,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 2155fe8..0291afa 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.1.0.rc2.206.gedb03e5
> 



Amicalement,
-- 
Albert.

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

* [U-Boot] [PATCH v3 22/30] ARM: cache_v7: Various minor cleanups
  2014-11-14  8:00   ` Albert ARIBAUD
@ 2014-11-15  1:54     ` Simon Glass
  0 siblings, 0 replies; 45+ messages in thread
From: Simon Glass @ 2014-11-15  1:54 UTC (permalink / raw)
  To: u-boot

Hi Albert,

On 14 November 2014 01:00, Albert ARIBAUD <albert.u.boot@aribaud.net> wrote:
> Hello Simon,
>
> I've actually applied v2 of this patch and PRed it to u-boot/master)
> and accidentally not acked it.
>
> Apologies.

No problem, I think it will be fine. Thanks for letting me know.

- Simon

>
> On Wed, 12 Nov 2014 18:27:08 -0700, Simon Glass <sjg@chromium.org>
> 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>
>> Signed-off-by: Simon Glass <sjg@chromium.org>
>> ---
>>
>> Changes in v3: None
>>
>>  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 a2c4032..0f9d837 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.1.0.rc2.206.gedb03e5
>>
>
>
>
> Amicalement,
> --
> Albert.

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

* [U-Boot] [PATCH v3 05/30] power: Add AMS AS3722 PMIC support
  2014-11-13  1:26 ` [U-Boot] [PATCH v3 05/30] power: Add AMS AS3722 PMIC support Simon Glass
@ 2014-11-17 10:04   ` Thierry Reding
  2014-11-17 18:30     ` Simon Glass
  0 siblings, 1 reply; 45+ messages in thread
From: Thierry Reding @ 2014-11-17 10:04 UTC (permalink / raw)
  To: u-boot

On Wed, Nov 12, 2014 at 06:26:51PM -0700, Simon Glass wrote:
[...]
> diff --git a/drivers/power/as3722.c b/drivers/power/as3722.c
[...]
> +int as3722_init(struct udevice **devp)
> +{
> +	struct udevice *pmic;
> +	u8 id, revision;
> +	int bus = 0;
> +	int address = 0x40;

Is there a reason for bus and address to not be unsigned? I also take it
that the plan is to eventually query these from the udevice/DT once I2C
has been converted to DM?

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/20141117/6102e960/attachment.pgp>

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

* [U-Boot] [PATCH v3 30/30] net: rtl8169: Add support for RTL-8168/8111g
  2014-11-13  1:27 ` [U-Boot] [PATCH v3 30/30] net: rtl8169: Add support for RTL-8168/8111g Simon Glass
@ 2014-11-17 10:14   ` Thierry Reding
  0 siblings, 0 replies; 45+ messages in thread
From: Thierry Reding @ 2014-11-17 10:14 UTC (permalink / raw)
  To: u-boot

On Wed, Nov 12, 2014 at 06:27:16PM -0700, Simon Glass wrote:
> From: Thierry Reding <treding@nvidia.com>
> 
> This network interface card in found on the NVIDIA Jetson TK1.

Self-correct: s/in found/is found/

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/20141117/00509f75/attachment.pgp>

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

* [U-Boot] [PATCH v3 29/30] net: rtl8169: Use non-cached memory if available
  2014-11-13  1:27 ` [U-Boot] [PATCH v3 29/30] net: rtl8169: Use non-cached memory if available Simon Glass
@ 2014-11-17 10:16   ` Thierry Reding
  0 siblings, 0 replies; 45+ messages in thread
From: Thierry Reding @ 2014-11-17 10:16 UTC (permalink / raw)
  To: u-boot

On Wed, Nov 12, 2014 at 06:27:15PM -0700, Simon Glass wrote:
[...]
> diff --git a/drivers/net/rtl8169.c b/drivers/net/rtl8169.c
> index fc8c31e..cd26c36 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.

Self-correct: s/driver allocate/driver to allocate/

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/20141117/165fbcda/attachment.pgp>

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

* [U-Boot] [PATCH v3 01/30] vsprintf: Add modifier for phys_addr_t
  2014-11-13  1:26 ` [U-Boot] [PATCH v3 01/30] vsprintf: Add modifier for phys_addr_t Simon Glass
@ 2014-11-17 10:18   ` Thierry Reding
  2014-11-17 18:31     ` Simon Glass
  2014-11-24 22:11   ` [U-Boot] [U-Boot, v3, " Tom Rini
  1 sibling, 1 reply; 45+ messages in thread
From: Thierry Reding @ 2014-11-17 10:18 UTC (permalink / raw)
  To: u-boot

Hi Simon,

Thanks for taking this over. Besides the three small nitpicks (which
aren't really blockers, so feel free to ignore) this looks like what I
would've done had I respun the series.

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/20141117/6275886a/attachment.pgp>

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

* [U-Boot] [PATCH v3 05/30] power: Add AMS AS3722 PMIC support
  2014-11-17 10:04   ` Thierry Reding
@ 2014-11-17 18:30     ` Simon Glass
  0 siblings, 0 replies; 45+ messages in thread
From: Simon Glass @ 2014-11-17 18:30 UTC (permalink / raw)
  To: u-boot

Hi Thierry,

On 17 November 2014 10:04, Thierry Reding <treding@nvidia.com> wrote:
> On Wed, Nov 12, 2014 at 06:26:51PM -0700, Simon Glass wrote:
> [...]
>> diff --git a/drivers/power/as3722.c b/drivers/power/as3722.c
> [...]
>> +int as3722_init(struct udevice **devp)
>> +{
>> +     struct udevice *pmic;
>> +     u8 id, revision;
>> +     int bus = 0;
>> +     int address = 0x40;
>
> Is there a reason for bus and address to not be unsigned? I also take it
> that the plan is to eventually query these from the udevice/DT once I2C
> has been converted to DM?

They can be unsigned but I didn't think it was important. They should
probably be const too...

This does in fact use DM for I2C - I place this series on top of the
I2C series. I'm going to give it a few more days for people like
you/Tom/Stephen to take a look at the Tegra DM conversion for I2C,
then I'll bring it through the DM tree, and likely this series too,
after fixing the nits.

The near-term plan is to use the PMIC support when it moves to DM. But
for now this is pretty clean.

Regards,
Simon

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

* [U-Boot] [PATCH v3 01/30] vsprintf: Add modifier for phys_addr_t
  2014-11-17 10:18   ` Thierry Reding
@ 2014-11-17 18:31     ` Simon Glass
  0 siblings, 0 replies; 45+ messages in thread
From: Simon Glass @ 2014-11-17 18:31 UTC (permalink / raw)
  To: u-boot

On 17 November 2014 10:18, Thierry Reding <treding@nvidia.com> wrote:
> Hi Simon,
>
> Thanks for taking this over. Besides the three small nitpicks (which
> aren't really blockers, so feel free to ignore) this looks like what I
> would've done had I respun the series.

Great - thanks for going through this.

- Simon

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

* [U-Boot] [U-Boot, v3, 01/30] vsprintf: Add modifier for phys_addr_t
  2014-11-13  1:26 ` [U-Boot] [PATCH v3 01/30] vsprintf: Add modifier for phys_addr_t Simon Glass
  2014-11-17 10:18   ` Thierry Reding
@ 2014-11-24 22:11   ` Tom Rini
  1 sibling, 0 replies; 45+ messages in thread
From: Tom Rini @ 2014-11-24 22:11 UTC (permalink / raw)
  To: u-boot

On Wed, Nov 12, 2014 at 06:26:47PM -0700, Simon Glass 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.
> 
> Signed-off-by: Thierry Reding <treding@nvidia.com>
> Tested-by: Stephen Warren <swarren@nvidia.com>
> Signed-off-by: Simon Glass <sjg@chromium.org>

Applied to u-boot/master, thanks!

-- 
Tom
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 836 bytes
Desc: Digital signature
URL: <http://lists.denx.de/pipermail/u-boot/attachments/20141124/757058dc/attachment.pgp>

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

* [U-Boot] [U-Boot, v3, 02/30] pci: Abort early if bus does not exist
  2014-11-13  1:26 ` [U-Boot] [PATCH v3 02/30] pci: Abort early if bus does not exist Simon Glass
@ 2014-11-24 22:11   ` Tom Rini
  0 siblings, 0 replies; 45+ messages in thread
From: Tom Rini @ 2014-11-24 22:11 UTC (permalink / raw)
  To: u-boot

On Wed, Nov 12, 2014 at 06:26:48PM -0700, Simon Glass wrote:

> 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>
> Signed-off-by: Simon Glass <sjg@chromium.org>

Applied to u-boot/master, thanks!

-- 
Tom
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 836 bytes
Desc: Digital signature
URL: <http://lists.denx.de/pipermail/u-boot/attachments/20141124/60231deb/attachment.pgp>

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

* [U-Boot] [U-Boot,v3,03/30] pci: Honour pci_skip_dev()
  2014-11-13  1:26 ` [U-Boot] [PATCH v3 03/30] pci: Honour pci_skip_dev() Simon Glass
@ 2014-11-24 22:11   ` Tom Rini
  0 siblings, 0 replies; 45+ messages in thread
From: Tom Rini @ 2014-11-24 22:11 UTC (permalink / raw)
  To: u-boot

On Wed, Nov 12, 2014 at 06:26:49PM -0700, Simon Glass wrote:

> 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>
> Signed-off-by: Simon Glass <sjg@chromium.org>

Applied to u-boot/master, thanks!

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

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

* [U-Boot] [U-Boot,v3,04/30] Add pr_fmt() macro
  2014-11-13  1:26 ` [U-Boot] [PATCH v3 04/30] Add pr_fmt() macro Simon Glass
@ 2014-11-24 22:11   ` Tom Rini
  0 siblings, 0 replies; 45+ messages in thread
From: Tom Rini @ 2014-11-24 22:11 UTC (permalink / raw)
  To: u-boot

On Wed, Nov 12, 2014 at 06:26:50PM -0700, Simon Glass wrote:

> From: Thierry Reding <treding@nvidia.com>
> 
> This macro can be overridden in source files (before including common.h)
> and can be used to specify a prefix for debug and error messages. An
> example of how to use this is shown below:
> 
> 	#define pr_fmt(fmt) "foo: " fmt
> 
> 	#include <common.h>
> 
> 	...
> 	debug("bar");
> 
> The resulting message will read:
> 
> 	foo: bar
> 
> Acked-by: Simon Glass <sjg@chromium.org>
> Signed-off-by: Thierry Reding <treding@nvidia.com>
> Signed-off-by: Simon Glass <sjg@chromium.org>

Applied to u-boot/master, thanks!

-- 
Tom
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 836 bytes
Desc: Digital signature
URL: <http://lists.denx.de/pipermail/u-boot/attachments/20141124/9e9a36a0/attachment.pgp>

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

* [U-Boot] [U-Boot, v3, 24/30] malloc: Output region when debugging
  2014-11-13  1:27 ` [U-Boot] [PATCH v3 24/30] malloc: Output region when debugging Simon Glass
@ 2014-11-24 22:11   ` Tom Rini
  0 siblings, 0 replies; 45+ messages in thread
From: Tom Rini @ 2014-11-24 22:11 UTC (permalink / raw)
  To: u-boot

On Wed, Nov 12, 2014 at 06:27:10PM -0700, Simon Glass 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>
> Acked-by: Simon Glass <sjg@chromium.org>
> Signed-off-by: Simon Glass <sjg@chromium.org>

Applied to u-boot/master, thanks!

-- 
Tom
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 836 bytes
Desc: Digital signature
URL: <http://lists.denx.de/pipermail/u-boot/attachments/20141124/28ba8a50/attachment.pgp>

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

end of thread, other threads:[~2014-11-24 22:11 UTC | newest]

Thread overview: 45+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2014-11-13  1:26 [U-Boot] [PATCH v3 0/30] ARM: tegra: Add PCIe support Simon Glass
2014-11-13  1:26 ` [U-Boot] [PATCH v3 01/30] vsprintf: Add modifier for phys_addr_t Simon Glass
2014-11-17 10:18   ` Thierry Reding
2014-11-17 18:31     ` Simon Glass
2014-11-24 22:11   ` [U-Boot] [U-Boot, v3, " Tom Rini
2014-11-13  1:26 ` [U-Boot] [PATCH v3 02/30] pci: Abort early if bus does not exist Simon Glass
2014-11-24 22:11   ` [U-Boot] [U-Boot, v3, " Tom Rini
2014-11-13  1:26 ` [U-Boot] [PATCH v3 03/30] pci: Honour pci_skip_dev() Simon Glass
2014-11-24 22:11   ` [U-Boot] [U-Boot,v3,03/30] " Tom Rini
2014-11-13  1:26 ` [U-Boot] [PATCH v3 04/30] Add pr_fmt() macro Simon Glass
2014-11-24 22:11   ` [U-Boot] [U-Boot,v3,04/30] " Tom Rini
2014-11-13  1:26 ` [U-Boot] [PATCH v3 05/30] power: Add AMS AS3722 PMIC support Simon Glass
2014-11-17 10:04   ` Thierry Reding
2014-11-17 18:30     ` Simon Glass
2014-11-13  1:26 ` [U-Boot] [PATCH v3 06/30] ARM: tegra: Implement tegra_plle_enable() Simon Glass
2014-11-13  1:26 ` [U-Boot] [PATCH v3 07/30] ARM: tegra: Provide PCIEXCLK reset ID Simon Glass
2014-11-13  1:26 ` [U-Boot] [PATCH v3 08/30] ARM: tegra: Implement powergate support Simon Glass
2014-11-13  1:26 ` [U-Boot] [PATCH v3 09/30] ARM: tegra: Implement XUSB pad controller Simon Glass
2014-11-13  1:26 ` [U-Boot] [PATCH v3 10/30] ARM: tegra: Add XUSB pad controller on Tegra124 Simon Glass
2014-11-13  1:26 ` [U-Boot] [PATCH v3 11/30] ARM: tegra: Enable XUSB pad controller on Jetson TK1 Simon Glass
2014-11-13  1:26 ` [U-Boot] [PATCH v3 12/30] pci: tegra: Add Tegra PCIe driver Simon Glass
2014-11-13  1:26 ` [U-Boot] [PATCH v3 13/30] ARM: tegra: Add Tegra20 PCIe device tree node Simon Glass
2014-11-13  1:27 ` [U-Boot] [PATCH v3 14/30] ARM: tegra: Enable PCIe on TrimSlice Simon Glass
2014-11-13  1:27 ` [U-Boot] [PATCH v3 15/30] ARM: tegra: Add GIC for Tegra30 Simon Glass
2014-11-13  1:27 ` [U-Boot] [PATCH v3 16/30] ARM: tegra: Add Tegra30 PCIe device tree node Simon Glass
2014-11-13  1:27 ` [U-Boot] [PATCH v3 17/30] ARM: tegra: Enable PCIe on Cardhu Simon Glass
2014-11-13  1:27 ` [U-Boot] [PATCH v3 18/30] ARM: tegra: Enable PCIe on Beaver Simon Glass
2014-11-13  1:27 ` [U-Boot] [PATCH v3 19/30] ARM: tegra: Add GIC for Tegra124 Simon Glass
2014-11-13  1:27 ` [U-Boot] [PATCH v3 20/30] ARM: tegra: Add Tegra124 PCIe device tree node Simon Glass
2014-11-13  1:27 ` [U-Boot] [PATCH v3 21/30] ARM: tegra: Enable PCIe on Jetson TK1 Simon Glass
2014-11-13  1:27 ` [U-Boot] [PATCH v3 22/30] ARM: cache_v7: Various minor cleanups Simon Glass
2014-11-14  8:00   ` Albert ARIBAUD
2014-11-15  1:54     ` Simon Glass
2014-11-13  1:27 ` [U-Boot] [PATCH v3 23/30] ARM: cache-cp15: Use more accurate types Simon Glass
2014-11-14  8:00   ` Albert ARIBAUD
2014-11-13  1:27 ` [U-Boot] [PATCH v3 24/30] malloc: Output region when debugging Simon Glass
2014-11-24 22:11   ` [U-Boot] [U-Boot, v3, " Tom Rini
2014-11-13  1:27 ` [U-Boot] [PATCH v3 25/30] ARM: Implement non-cached memory support Simon Glass
2014-11-13  1:27 ` [U-Boot] [PATCH v3 26/30] ARM: tegra: Enable non-cached memory Simon Glass
2014-11-13  1:27 ` [U-Boot] [PATCH v3 27/30] net: rtl8169: Honor CONFIG_SYS_RX_ETH_BUFFER Simon Glass
2014-11-13  1:27 ` [U-Boot] [PATCH v3 28/30] net: rtl8169: Properly align buffers Simon Glass
2014-11-13  1:27 ` [U-Boot] [PATCH v3 29/30] net: rtl8169: Use non-cached memory if available Simon Glass
2014-11-17 10:16   ` Thierry Reding
2014-11-13  1:27 ` [U-Boot] [PATCH v3 30/30] net: rtl8169: Add support for RTL-8168/8111g Simon Glass
2014-11-17 10:14   ` Thierry Reding

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.