Skip to contentSkip to conversation

ARM: tegra: Add PCIe support

PATCH Superseded Thierry Reding 7 participants 104 messages Aug 26, 2014 – Jul 15, 2015

Subsystems (10)
lore
Share & tools
lore
#0 lore raw

v2 cover ARM: tegra: Add PCIe support

From: Thierry Reding <[email protected]>

This series adds PCIe support for Tegra20, Tegra30 and Tegra124. The size is mostly due to the large number of infrastructure that's added (libfdt, Tegra specific drivers required by the PCIe driver). In this version I've included all patches that were previously split into three separate series. Spreading them over multiple series is probably not worth it since there might be some dependencies between them and only the end result gives a completely working setup.

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

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

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

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

Patches 11-14 are some cleanup and refactoring of I2C core code, the addition of a higher level API that makes it easier for I2C client drivers to talk to devices. The Tegra I2C driver now implements i2c_get_bus_num_fdt() to obtain bus numbers corresponding to a DT node.

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

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

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

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

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

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

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

Thierry Reding (40):
vsprintf: Add modifier for phys_addr_t
fdt: Add a function to count strings
fdt: Add a function to get the index of a string
fdt: Add functions to retrieve strings
fdt: Add resource parsing functions
fdt: Add a function to return PCI BDF triplet
fdt: Add a subnodes iterator macro
pci: Abort early if bus does not exist
pci: Honour pci_skip_dev()
Add pr_fmt() macro
i2c: Initialize the correct bus
i2c: Refactor adapter initialization
i2c: Add high-level API
i2c: tegra: Implement i2c_get_bus_num_fdt()
power: Add AMS AS3722 PMIC support
ARM: tegra: Implement tegra_plle_enable()
ARM: tegra: Provide PCIEXCLK reset ID
ARM: tegra: Implement powergate support
ARM: tegra: Implement XUSB pad controller
ARM: tegra: Add XUSB pad controller on Tegra124
ARM: tegra: Enable XUSB pad controller on Jetson TK1
pci: tegra: Add Tegra PCIe driver
ARM: tegra: Add Tegra20 PCIe device tree node
ARM: tegra: Enable PCIe on TrimSlice
ARM: tegra: Add GIC for Tegra30
ARM: tegra: Add Tegra30 PCIe device tree node
ARM: tegra: Enable PCIe on Cardhu
ARM: tegra: Enable PCIe on Beaver
ARM: tegra: Add GIC for Tegra124
ARM: tegra: Add Tegra124 PCIe device tree node
ARM: tegra: Enable PCIe on Jetson TK1
ARM: cache_v7: Various minor cleanups
ARM: cache-cp15: Use more accurate types
malloc: Output region when debugging
ARM: Implement non-cached memory support
ARM: tegra: Enable non-cached memory
net: rtl8169: Honor CONFIG_SYS_RX_ETH_BUFFER
net: rtl8169: Properly align buffers
net: rtl8169: Use non-cached memory if available
net: rtl8169: Add support for RTL-8168/8111g

 README                                           |   19 +
 arch/arm/cpu/armv7/cache_v7.c                    |   14 +-
 arch/arm/cpu/tegra-common/Makefile               |    2 +
 arch/arm/cpu/tegra-common/powergate.c            |  102 ++
 arch/arm/cpu/tegra-common/xusb-padctl.c          |   39 +
 arch/arm/cpu/tegra124-common/Makefile            |    1 +
 arch/arm/cpu/tegra124-common/clock.c             |  109 +++
 arch/arm/cpu/tegra124-common/xusb-padctl.c       |  716 ++++++++++++++
 arch/arm/cpu/tegra20-common/clock.c              |  141 ++-
 arch/arm/cpu/tegra30-common/clock.c              |  155 +++
 arch/arm/dts/tegra124-jetson-tk1.dts             |  373 +++++++
 arch/arm/dts/tegra124.dtsi                       |   90 ++
 arch/arm/dts/tegra20-trimslice.dts               |   69 ++
 arch/arm/dts/tegra20.dtsi                        |   60 ++
 arch/arm/dts/tegra30-beaver.dts                  |  245 +++++
 arch/arm/dts/tegra30-cardhu.dts                  |  362 +++++++
 arch/arm/dts/tegra30.dtsi                        |   84 ++
 arch/arm/include/asm/arch-tegra/powergate.h      |   38 +
 arch/arm/include/asm/arch-tegra/xusb-padctl.h    |   24 +
 arch/arm/include/asm/arch-tegra114/powergate.h   |    6 +
 arch/arm/include/asm/arch-tegra124/clock.h       |    2 +
 arch/arm/include/asm/arch-tegra124/powergate.h   |    6 +
 arch/arm/include/asm/arch-tegra20/clock-tables.h |    2 +-
 arch/arm/include/asm/arch-tegra20/clock.h        |    2 +
 arch/arm/include/asm/arch-tegra20/powergate.h    |    6 +
 arch/arm/include/asm/arch-tegra30/clock.h        |    2 +
 arch/arm/include/asm/arch-tegra30/powergate.h    |    6 +
 arch/arm/include/asm/system.h                    |    7 +-
 arch/arm/lib/cache-cp15.c                        |    6 +-
 arch/arm/lib/cache.c                             |   42 +
 board/compulab/trimslice/trimslice.c             |    8 +
 board/nvidia/cardhu/cardhu.c                     |   56 ++
 board/nvidia/common/board.c                      |    3 +
 board/nvidia/jetson-tk1/jetson-tk1.c             |   52 +
 common/board_r.c                                 |   11 +
 common/cmd_pci.c                                 |    7 +
 common/dlmalloc.c                                |    3 +
 drivers/i2c/i2c_core.c                           |   80 +-
 drivers/i2c/tegra_i2c.c                          |   13 +
 drivers/net/rtl8169.c                            |  127 ++-
 drivers/pci/Makefile                             |    1 +
 drivers/pci/pci.c                                |    3 +
 drivers/pci/pci_tegra.c                          | 1143 ++++++++++++++++++++++
 drivers/power/Makefile                           |    1 +
 drivers/power/as3722.c                           |  300 ++++++
 include/common.h                                 |   14 +-
 include/configs/beaver.h                         |   10 +
 include/configs/cardhu.h                         |   10 +
 include/configs/jetson-tk1.h                     |   13 +
 include/configs/tegra-common.h                   |    1 +
 include/configs/trimslice.h                      |   10 +
 include/dt-bindings/clock/tegra124-car.h         |  341 +++++++
 include/dt-bindings/clock/tegra20-car.h          |  158 +++
 include/dt-bindings/clock/tegra30-car.h          |  265 +++++
 include/dt-bindings/pinctrl/pinctrl-tegra-xusb.h |    7 +
 include/fdtdec.h                                 |   69 ++
 include/i2c.h                                    |   96 ++
 include/libfdt.h                                 |   72 ++
 include/pci.h                                    |    1 +
 include/power/as3722.h                           |   27 +
 lib/fdtdec.c                                     |   76 ++
 lib/libfdt/fdt_ro.c                              |   76 ++
 lib/vsprintf.c                                   |   16 +-
 63 files changed, 5736 insertions(+), 64 deletions(-)
 create mode 100644 arch/arm/cpu/tegra-common/powergate.c
 create mode 100644 arch/arm/cpu/tegra-common/xusb-padctl.c
 create mode 100644 arch/arm/cpu/tegra124-common/xusb-padctl.c
 create mode 100644 arch/arm/include/asm/arch-tegra/powergate.h
 create mode 100644 arch/arm/include/asm/arch-tegra/xusb-padctl.h
 create mode 100644 arch/arm/include/asm/arch-tegra114/powergate.h
 create mode 100644 arch/arm/include/asm/arch-tegra124/powergate.h
 create mode 100644 arch/arm/include/asm/arch-tegra20/powergate.h
 create mode 100644 arch/arm/include/asm/arch-tegra30/powergate.h
 create mode 100644 drivers/pci/pci_tegra.c
 create mode 100644 drivers/power/as3722.c
 create mode 100644 include/dt-bindings/clock/tegra124-car.h
 create mode 100644 include/dt-bindings/clock/tegra20-car.h
 create mode 100644 include/dt-bindings/clock/tegra30-car.h
 create mode 100644 include/dt-bindings/pinctrl/pinctrl-tegra-xusb.h
 create mode 100644 include/power/as3722.h
Signature · 1 line
2.0.4
#1 lore raw

PATCH v2 1/40 vsprintf: Add modifier for phys_addr_t

From: Thierry Reding <[email protected]>

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.

---
 lib/vsprintf.c | 16 ++++++++++++++--
 1 file changed, 14 insertions(+), 2 deletions(-)
lib/vsprintf.c +14 -2
index 7ec758e40fc5..044d5551bdd0 100644
@@ -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,
Signature · 1 line
2.0.4
#2 lore raw

PATCH v2 1/40 vsprintf: Add modifier for phys_addr_t

Quoted 7 lines · Thierry Reding

From: Thierry Reding <[email protected]>

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:

Quoted 6 lines
	phys_addr_t start = 0;

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

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

The series,

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

pci_hose_bus_to_phys: invalid physical address

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

#3 lore raw

PATCH v2 1/40 vsprintf: Add modifier for phys_addr_t

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

From: Thierry Reding <[email protected]>

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:

Quoted 6 lines
	phys_addr_t start = 0;

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

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

The series,

Quoted 7 lines

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

pci_hose_bus_to_phys: invalid physical address

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

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

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

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

#4 lore raw

PATCH v2 1/40 vsprintf: Add modifier for phys_addr_t

Quoted 23 lines · Thierry Reding
Quoted 22 lines · Stephen Warren
Quoted 7 lines · Thierry Reding

From: Thierry Reding <[email protected]>

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:

Quoted 6 lines
	phys_addr_t start = 0;

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

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

The series,

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

Quoted 8 lines
Quoted 4 lines

pci_hose_bus_to_phys: invalid physical address

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

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

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

Quoted 2 lines

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

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

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

#5 lore raw

PATCH v2 1/40 vsprintf: Add modifier for phys_addr_t

Quoted 39 lines · Stephen Warren
Quoted 23 lines · Thierry Reding
Quoted 22 lines · Stephen Warren
Quoted 7 lines · Thierry Reding

From: Thierry Reding <[email protected]>

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:

Quoted 6 lines
	phys_addr_t start = 0;

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

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

The series,

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

Quoted 8 lines
Quoted 4 lines

pci_hose_bus_to_phys: invalid physical address

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

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

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

Quoted 2 lines

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

Quoted 8 lines

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

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

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

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

#6 lore raw

PATCH v2 1/40 vsprintf: Add modifier for phys_addr_t

Quoted 11 lines

From: Thierry Reding <[email protected]>
Date: Thu, 28 Aug 2014 12:26:58 +0200
Subject: [PATCH] rtl8169: Defer network packet processing

When network protocol errors occur (such as a file not being found on a TFTP server), the processing done by the NetReceive() function will end up calling the driver's .halt() implementation. However, after that the device no longer has access to the memory buffers and will cause errors such as this in the rtl_recv() function when trying to hand descriptors back to the device:

Quoted 8 lines

pci_hose_bus_to_phys: invalid physical address

This can be fixed by deferring processing of network packets until the descriptors have been handed back. That way rtl_halt() tearing down network buffers is not going to prevent access to the buffers.

Applied to u-boot/master, thanks!

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

PATCH v2 1/40 vsprintf: Add modifier for phys_addr_t

In reply to Thierry Reding

Hi Thierry,

Quoted 8 lines · Thierry Reding

From: Thierry Reding <[email protected]>

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:

Quoted 6 lines
        phys_addr_t start = 0;

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

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

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

Quoted 11 lines
---
 lib/vsprintf.c | 16 ++++++++++++++--
 1 file changed, 14 insertions(+), 2 deletions(-)
lib/vsprintf.c +0 -0
index 7ec758e40fc5..044d5551bdd0 100644

lib/vsprintf.c static char *ip4_addr_string(char *buf, char *end, u8 *addr, int field_width, · line 522

Quoted 5 lines
lib/vsprintf.c +2 -0
@@ -518,6 +518,8 @@ static char *ip4_addr_string(char *buf, char *end, u8 *addr, int field_width,
 static char *pointer(const char *fmt, char *buf, char *end, void *ptr,
                int field_width, int precision, int flags)
 {
+       u64 num = (uintptr_t)ptr;
+

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

Quoted 32 lines
lib/vsprintf.c +12 -3
        /*
         * 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,
--
Quoted 2 lines

2.0.4

Regards,
Simon

#8 lore raw

PATCH v2 1/40 vsprintf: Add modifier for phys_addr_t

Quoted 13 lines · Simon Glass

Hi Thierry,

Quoted 10 lines · Thierry Reding

From: Thierry Reding <[email protected]>

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;
Quoted 7 lines
Quoted 4 lines
        printf("start: %pa\n", &start);

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

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

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

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

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

lib/vsprintf.c static char *ip4_addr_string(char *buf, char *end, u8 *addr, int field_width, · line 522

Quoted 10 lines
lib/vsprintf.c +2 -0
index 7ec758e40fc5..044d5551bdd0 100644
@@ -518,6 +518,8 @@ static char *ip4_addr_string(char *buf, char *end, u8 *addr, int field_width,
 static char *pointer(const char *fmt, char *buf, char *end, void *ptr,
                int field_width, int precision, int flags)
 {
+       u64 num = (uintptr_t)ptr;
+

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

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

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

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

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

#9 lore raw

PATCH v2 1/40 vsprintf: Add modifier for phys_addr_t

Hi Thierry,

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

Hi Thierry,

Quoted 10 lines · Thierry Reding

From: Thierry Reding <[email protected]>

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;
Quoted 7 lines
Quoted 4 lines
        printf("start: %pa\n", &start);

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

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

Quoted 6 lines

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

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

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

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

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

Quoted 23 lines
Quoted 6 lines
Quoted 6 lines
---
 lib/vsprintf.c | 16 ++++++++++++++--
 1 file changed, 14 insertions(+), 2 deletions(-)
Quoted 13 lines

lib/vsprintf.c static char *ip4_addr_string(char *buf, char *end, u8 *addr, int field_width, · line 522

Quoted 10 lines
lib/vsprintf.c +2 -0
index 7ec758e40fc5..044d5551bdd0 100644
@@ -518,6 +518,8 @@ static char *ip4_addr_string(char *buf, char *end, u8 *addr, int field_width,
 static char *pointer(const char *fmt, char *buf, char *end, void *ptr,
                int field_width, int precision, int flags)
 {
+       u64 num = (uintptr_t)ptr;
+

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

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

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

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

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

Regards,
Simon

Quoted 2 lines

Thierry

#10 lore raw

PATCH v2 2/40 fdt: Add a function to count strings

In reply to Thierry Reding

From: Thierry Reding <[email protected]>

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

---
 include/libfdt.h    |  9 +++++++++
 lib/libfdt/fdt_ro.c | 20 ++++++++++++++++++++
 2 files changed, 29 insertions(+)
include/libfdt.h +9 -0
index a1ef1e15df3d..cf97bf0b3b52 100644
@@ -857,6 +857,15 @@ int fdt_node_offset_by_compatible(const void *fdt, int startoffset,
  */
 int fdt_stringlist_contains(const char *strlist, int listlen, const char *str);
 
+/**
+ * fdt_count_strings - count the number of strings in a string list
+ * @fdt: pointer to the device tree blob
+ * @node: offset of the node
+ * @property: name of the property containing the string list
+ * @return: the number of strings in the given property
+ */
+int fdt_count_strings(const void *fdt, int node, const char *property);
+
 /**********************************************************************/
 /* Read-only functions (addressing related)                           */
 /**********************************************************************/
lib/libfdt/fdt_ro.c +20 -0
index 36af0435254b..cb06a9b50d85 100644
@@ -491,6 +491,26 @@ int fdt_stringlist_contains(const char *strlist, int listlen, const char *str)
 	return 0;
 }
 
+int fdt_count_strings(const void *fdt, int node, const char *property)
+{
+	int length, i, count = 0;
+	const char *list;
+
+	list = fdt_getprop(fdt, node, property, &length);
+	if (!list)
+		return -length;
+
+	for (i = 0; i < length; i++) {
+		int len = strlen(list);
+
+		list += len + 1;
+		i += len;
+		count++;
+	}
+
+	return count;
+}
+
 int fdt_node_check_compatible(const void *fdt, int nodeoffset,
 			      const char *compatible)
 {
Signature · 1 line
2.0.4
#11 lore raw

PATCH v2 2/40 fdt: Add a function to count strings

Hi Thierry,

Quoted 6 lines · Thierry Reding

From: Thierry Reding <[email protected]>

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

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

Regards,
Simon

#12 lore raw

PATCH v2 2/40 fdt: Add a function to count strings

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

#13 lore raw

PATCH v2 3/40 fdt: Add a function to get the index of a string

In reply to Thierry Reding

From: Thierry Reding <[email protected]>

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

---
Changes in v2:
- rename to fdt_find_string() to remove naming conflicts with other new functions
- correctly increment string list pointer

 include/libfdt.h    | 11 +++++++++++
 lib/libfdt/fdt_ro.c | 26 ++++++++++++++++++++++++++
 2 files changed, 37 insertions(+)
include/libfdt.h +11 -0
index cf97bf0b3b52..d0dea668eea2 100644
@@ -866,6 +866,17 @@ int fdt_stringlist_contains(const char *strlist, int listlen, const char *str);
  */
 int fdt_count_strings(const void *fdt, int node, const char *property);
 
+/**
+ * fdt_find_string - find a string in a string list and return its index
+ * @fdt: pointer to the device tree blob
+ * @node: offset of the node
+ * @property: name of the property containing the string list
+ * @string: string to look up in the string list
+ * @return: the index of the string or negative on error
+ */
+int fdt_find_string(const void *fdt, int node, const char *property,
+		    const char *string);
+
 /**********************************************************************/
 /* Read-only functions (addressing related)                           */
 /**********************************************************************/
lib/libfdt/fdt_ro.c +26 -0
index cb06a9b50d85..fec4a0a141fd 100644
@@ -511,6 +511,32 @@ int fdt_count_strings(const void *fdt, int node, const char *property)
 	return count;
 }
 
+int fdt_find_string(const void *fdt, int node, const char *property,
+		    const char *string)
+{
+	const char *list, *end;
+	int len, index = 0;
+
+	list = fdt_getprop(fdt, node, property, &len);
+	if (!list)
+		return len;
+
+	end = list + len;
+	len = strlen(string);
+
+	while (list < end) {
+		int l = strlen(list);
+
+		if (l == len && memcmp(list, string, len) == 0)
+			return index;
+
+		list += l + 1;
+		index++;
+	}
+
+	return -FDT_ERR_NOTFOUND;
+}
+
 int fdt_node_check_compatible(const void *fdt, int nodeoffset,
 			      const char *compatible)
 {
Signature · 1 line
2.0.4
#14 lore raw

PATCH v2 3/40 fdt: Add a function to get the index of a string

Hi Thierry,

Quoted 7 lines · Thierry Reding

From: Thierry Reding <[email protected]>

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

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

Regards,
Simon

#15 lore raw

PATCH v2 3/40 fdt: Add a function to get the index of a string

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

#16 lore raw

PATCH v2 4/40 fdt: Add functions to retrieve strings

In reply to Thierry Reding

From: Thierry Reding <[email protected]>

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

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

---
 include/libfdt.h    | 27 +++++++++++++++++++++++++++
 lib/libfdt/fdt_ro.c | 30 ++++++++++++++++++++++++++++++
 2 files changed, 57 insertions(+)
include/libfdt.h +27 -0
index d0dea668eea2..2dfc6d9e5ce7 100644
@@ -877,6 +877,33 @@ int fdt_count_strings(const void *fdt, int node, const char *property);
 int fdt_find_string(const void *fdt, int node, const char *property,
 		    const char *string);
 
+/**
+ * fdt_get_string_index() - obtain the string at a given index in a string list
+ * @fdt: pointer to the device tree blob
+ * @node: offset of the node
+ * @property: name of the property containing the string list
+ * @index: index of the string to return
+ * @output: return location for the string
+ * @return: 0 if the string was found or a negative error code otherwise
+ */
+int fdt_get_string_index(const void *fdt, int node, const char *property,
+			 int index, const char **output);
+
+/**
+ * fdt_get_string() - obtain the string at a given index in a string list
+ * @fdt: pointer to the device tree blob
+ * @node: offset of the node
+ * @property: name of the property containing the string list
+ * @output: return location for the string
+ * @return: 0 if the string was found or a negative error code otherwise
+ *
+ * This is a shortcut for:
+ *
+ *	fdt_get_string_index(fdt, node, property, 0, output).
+ */
+int fdt_get_string(const void *fdt, int node, const char *property,
+		   const char **output);
+
 /**********************************************************************/
 /* Read-only functions (addressing related)                           */
 /**********************************************************************/
lib/libfdt/fdt_ro.c +30 -0
index fec4a0a141fd..03733e574f71 100644
@@ -537,6 +537,36 @@ int fdt_find_string(const void *fdt, int node, const char *property,
 	return -FDT_ERR_NOTFOUND;
 }
 
+int fdt_get_string_index(const void *fdt, int node, const char *property,
+			 int index, const char **output)
+{
+	const char *list;
+	int length, i;
+
+	list = fdt_getprop(fdt, node, property, &length);
+
+	for (i = 0; i < length; i++) {
+		int len = strlen(list);
+
+		if (index == 0) {
+			*output = list;
+			return 0;
+		}
+
+		list += len + 1;
+		i += len;
+		index--;
+	}
+
+	return FDT_ERR_NOTFOUND;
+}
+
+int fdt_get_string(const void *fdt, int node, const char *property,
+		   const char **output)
+{
+	return fdt_get_string_index(fdt, node, property, 0, output);
+}
+
 int fdt_node_check_compatible(const void *fdt, int nodeoffset,
 			      const char *compatible)
 {
Signature · 1 line
2.0.4
#17 lore raw

PATCH v2 4/40 fdt: Add functions to retrieve strings

Hi Thierry,

Quoted 9 lines · Thierry Reding

From: Thierry Reding <[email protected]>

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

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

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

Regards,
Simon

#18 lore raw

PATCH v2 4/40 fdt: Add functions to retrieve strings

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

#19 lore raw

PATCH v2 4/40 fdt: Add functions to retrieve strings

Hi Thierry,

Quoted 1 line · Simon Glass

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

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

Regards,
SImon

#20 lore raw

PATCH v2 4/40 fdt: Add functions to retrieve strings

+Scott, Masahiro

Hi Thierry,

Quoted 6 lines · Simon Glass

Hi Thierry,

Quoted 1 line · Simon Glass

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

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

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

Regards,
Simon

#21 lore raw

PATCH v2 4/40 fdt: Add functions to retrieve strings

Quoted 7 lines · Simon Glass

+Scott, Masahiro

Hi Thierry,

Quoted 2 lines · Simon Glass

Hi Thierry,

Quoted 7 lines
Quoted 4 lines · Simon Glass
Quoted 1 line

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

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

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

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

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

#22 lore raw

PATCH v2 4/40 fdt: Add functions to retrieve strings

Hello Thierry,

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

+Scott, Masahiro

Hi Thierry,

Quoted 6 lines · Simon Glass

Hi Thierry,

Quoted 1 line · Simon Glass

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

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

Quoted 7 lines
Quoted 2 lines

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

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

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

Quoted 1 line

Thierry

Amicalement,

Signature · 1 line
Albert.
#23 lore raw

PATCH v2 4/40 fdt: Add functions to retrieve strings

Quoted 20 lines · Albert ARIBAUD

Hello Thierry,

Quoted 16 lines · Thierry Reding
Quoted 14 lines · Simon Glass

+Scott, Masahiro

Hi Thierry,

Quoted 6 lines · Simon Glass

Hi Thierry,

Quoted 1 line · Simon Glass

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

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

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

Quoted 7 lines
Quoted 4 lines

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

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

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

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

#24 lore raw

PATCH v2 5/40 fdt: Add resource parsing functions

In reply to Thierry Reding

From: Thierry Reding <[email protected]>

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

---
Changes in v2:
- use existing fdt_address_cells() and fdt_size_cells() functions
- add clarifying comments to struct fdt_resource declaration
- rename names variable to prop_names for clarity
- properly handle 64-bit addresses (compile-tested only)
- update for fdt_get_string_index() -> fdt_find_string() rename

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

61 lines not on this page · raw message

Signature · 1 line
2.0.4
#27 lore raw

PATCH v2 6/40 fdt: Add a function to return PCI BDF triplet

In reply to Thierry Reding

From: Thierry Reding <[email protected]>

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

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

PATCH v2 6/40 fdt: Add a function to return PCI BDF triplet

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

#29 lore raw

PATCH v2 7/40 fdt: Add a subnodes iterator macro

In reply to Thierry Reding

From: Thierry Reding <[email protected]>

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

---
Changes in v2:
- specify the data types in the comment because the macro doesn't have them

 include/libfdt.h | 25 +++++++++++++++++++++++++
 1 file changed, 25 insertions(+)
include/libfdt.h +25 -0
index 2dfc6d9e5ce7..f3cbb637be41 100644
@@ -163,6 +163,31 @@ int fdt_first_subnode(const void *fdt, int offset);
  */
 int fdt_next_subnode(const void *fdt, int offset);
 
+/**
+ * fdt_for_each_subnode - iterate over all subnodes of a parent
+ *
+ * This is actually a wrapper around a for loop and would be used like so:
+ *
+ *	fdt_for_each_subnode(fdt, node, parent) {
+ *		...
+ *		use node
+ *		...
+ *	}
+ *
+ * Note that this is implemented as a macro and node is used as iterator in
+ * the loop. It should therefore be a locally allocated variable. The parent
+ * variable on the other hand is never modified, so it can be constant or
+ * even a literal.
+ *
+ * @fdt:	FDT blob (const void *)
+ * @node:	child node (int)
+ * @parent:	parent node (int)
+ */
+#define fdt_for_each_subnode(fdt, node, parent)		\
+	for (node = fdt_first_subnode(fdt, parent);	\
+	     node >= 0;					\
+	     node = fdt_next_subnode(fdt, node))
+
 /**********************************************************************/
 /* General functions                                                  */
 /**********************************************************************/
Signature · 1 line
2.0.4
#30 lore raw

PATCH v2 7/40 fdt: Add a subnodes iterator macro

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

#31 lore raw

PATCH v2 8/40 pci: Abort early if bus does not exist

In reply to Thierry Reding

From: Thierry Reding <[email protected]>

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

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

PATCH v2 9/40 pci: Honour pci_skip_dev()

In reply to Thierry Reding

From: Thierry Reding <[email protected]>

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

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

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

PATCH v2 10/40 Add pr_fmt() macro

In reply to Thierry Reding

From: Thierry Reding <[email protected]>

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

	#define pr_fmt(fmt) "foo: " fmt

	#include <common.h>

	...
	debug("bar");

The resulting message will read:

foo: bar

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

PATCH v2 11/40 i2c: Initialize the correct bus

In reply to Thierry Reding

From: Thierry Reding <[email protected]>

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

---
 drivers/i2c/i2c_core.c | 15 +++++++++------
 1 file changed, 9 insertions(+), 6 deletions(-)
drivers/i2c/i2c_core.c +9 -6
index 18d6736601c1..cca455bc9c63 100644
@@ -214,17 +214,20 @@ static int i2c_mux_disconnet_all(void)
  * Initializes one bus. Will initialize the parent adapter. No current bus
  * changes, no mux (if any) setup.
  */
-static void i2c_init_bus(unsigned int bus_no, int speed, int slaveaddr)
+static void i2c_init_bus(unsigned int bus, int speed, int slaveaddr)
 {
-	if (bus_no >= CONFIG_SYS_NUM_I2C_BUSES)
+	struct i2c_adapter *adapter;
+
+	if (bus >= CONFIG_SYS_NUM_I2C_BUSES)
 		return;
 
-	I2C_ADAP->init(I2C_ADAP, speed, slaveaddr);
+	adapter = i2c_get_adapter(I2C_ADAPTER(bus));
+	adapter->init(adapter, speed, slaveaddr);
 
 	if (gd->flags & GD_FLG_RELOC) {
-		I2C_ADAP->init_done = 1;
-		I2C_ADAP->speed = speed;
-		I2C_ADAP->slaveaddr = slaveaddr;
+		adapter->init_done = 1;
+		adapter->speed = speed;
+		adapter->slaveaddr = slaveaddr;
 	}
 }
 
Signature · 1 line
2.0.4
#35 lore raw

PATCH v2 11/40 i2c: Initialize the correct bus

Hello Thierry,

Am 26.08.2014 17:33, schrieb Thierry Reding:

Quoted 8 lines

From: Thierry Reding<[email protected]>

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

Quoted 4 lines
---
  drivers/i2c/i2c_core.c | 15 +++++++++------
  1 file changed, 9 insertions(+), 6 deletions(-)

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

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

bye,
Heiko

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

PATCH v2 11/40 i2c: Initialize the correct bus

Quoted 11 lines · Heiko Schocher

Hello Thierry,

Am 26.08.2014 17:33, schrieb Thierry Reding:

Quoted 8 lines

From: Thierry Reding<[email protected]>

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

Quoted 7 lines
Quoted 4 lines
---
 drivers/i2c/i2c_core.c | 15 +++++++++------
 1 file changed, 9 insertions(+), 6 deletions(-)

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

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

Thierry

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

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

#37 lore raw

PATCH v2 11/40 i2c: Initialize the correct bus

Hello Thierry,

Am 27.08.2014 07:12, schrieb Thierry Reding:

Quoted 20 lines · Heiko Schocher
Quoted 11 lines

Hello Thierry,

Am 26.08.2014 17:33, schrieb Thierry Reding:

Quoted 8 lines

From: Thierry Reding<[email protected]>

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

Quoted 7 lines
Quoted 4 lines
---
  drivers/i2c/i2c_core.c | 15 +++++++++------
  1 file changed, 9 insertions(+), 6 deletions(-)

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

Quoted 7 lines

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

Yes, I think we could drop the bus_no parameter.

bye,
Heiko

Quoted 38 lines

Thierry

Quoted 35 lines
Quoted 21 lines
drivers/i2c/i2c_core.c +6 -3
index 18d6736601c1..cca455bc9c63 100644
@@ -214,17 +214,20 @@ static int i2c_mux_disconnet_all(void)
   * Initializes one bus. Will initialize the parent adapter. No current bus
   * changes, no mux (if any) setup.
   */
-static void i2c_init_bus(unsigned int bus_no, int speed, int slaveaddr)
+static void i2c_init_bus(unsigned int bus, int speed, int slaveaddr)
  {
-	if (bus_no>= CONFIG_SYS_NUM_I2C_BUSES)
+	struct i2c_adapter *adapter;
+
+	if (bus>= CONFIG_SYS_NUM_I2C_BUSES)
  		return;
 
-	I2C_ADAP->init(I2C_ADAP, speed, slaveaddr);
+	adapter = i2c_get_adapter(I2C_ADAPTER(bus));
+	adapter->init(adapter, speed, slaveaddr);
 

drivers/i2c/i2c_core.c static int i2c_mux_disconnet_all(void) · line 233

Quoted 10 lines
drivers/i2c/i2c_core.c +3 -3
  	if (gd->flags&   GD_FLG_RELOC) {
-		I2C_ADAP->init_done = 1;
-		I2C_ADAP->speed = speed;
-		I2C_ADAP->slaveaddr = slaveaddr;
+		adapter->init_done = 1;
+		adapter->speed = speed;
+		adapter->slaveaddr = slaveaddr;
  	}
  }
 

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

Signature · 2 lines
DENX Software Engineering GmbH,     MD: Wolfgang Denk & Detlev Zundel
HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
#38 lore raw

PATCH v2 12/40 i2c: Refactor adapter initialization

In reply to Thierry Reding

From: Thierry Reding <[email protected]>

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

---
 drivers/i2c/i2c_core.c | 20 +++++++++++++-------
 1 file changed, 13 insertions(+), 7 deletions(-)
drivers/i2c/i2c_core.c +13 -7
index cca455bc9c63..f6179a16244b 100644
@@ -207,6 +207,18 @@ static int i2c_mux_disconnet_all(void)
 }
 #endif
 
+static void i2c_adapter_init(struct i2c_adapter *adapter, unsigned int speed,
+			     unsigned int slaveaddr)
+{
+	adapter->init(adapter, speed, slaveaddr);
+
+	if (gd->flags & GD_FLG_RELOC) {
+		adapter->slaveaddr = slaveaddr;
+		adapter->speed = speed;
+		adapter->init_done = 1;
+	}
+}
+
 /*
  * i2c_init_bus():
  * ---------------
@@ -222,13 +234,7 @@ static void i2c_init_bus(unsigned int bus, int speed, int slaveaddr)
 		return;
 
 	adapter = i2c_get_adapter(I2C_ADAPTER(bus));
-	adapter->init(adapter, speed, slaveaddr);
-
-	if (gd->flags & GD_FLG_RELOC) {
-		adapter->init_done = 1;
-		adapter->speed = speed;
-		adapter->slaveaddr = slaveaddr;
-	}
+	i2c_adapter_init(adapter, speed, slaveaddr);
 }
 
 /* implement possible board specific board init */
Signature · 1 line
2.0.4
#39 lore raw

PATCH v2 13/40 i2c: Add high-level API

In reply to Thierry Reding

From: Thierry Reding <[email protected]>

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

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

---
 drivers/i2c/i2c_core.c | 53 ++++++++++++++++++++++++++++
 include/i2c.h          | 96 ++++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 149 insertions(+)
drivers/i2c/i2c_core.c +53 -0
index f6179a16244b..88c7af546b0b 100644
@@ -410,3 +410,56 @@ void __i2c_init(int speed, int slaveaddr)
 }
 void i2c_init(int speed, int slaveaddr)
 	__attribute__((weak, alias("__i2c_init")));
+
+struct i2c_adapter *i2c_adapter_get(unsigned int index)
+{
+	struct i2c_adapter *adapter = ll_entry_start(struct i2c_adapter, i2c);
+	unsigned int num = ll_entry_count(struct i2c_adapter, i2c);
+	unsigned int i;
+
+	if (index >= num)
+		return NULL;
+
+	for (i = 0; i < index; i++)
+		adapter++;
+
+	i2c_adapter_init(adapter, adapter->speed, adapter->slaveaddr);
+	return adapter;
+}
+
+int i2c_adapter_read(struct i2c_adapter *adapter, uint8_t chip,
+		     unsigned int address, size_t alen, void *buffer,
+		     size_t size)
+{
+	return adapter->read(adapter, chip, address, alen, buffer, size);
+}
+
+int i2c_adapter_write(struct i2c_adapter *adapter, uint8_t chip,
+		      unsigned int address, size_t alen, void *buffer,
+		      size_t size)
+{
+	return adapter->write(adapter, chip, address, alen, buffer, size);
+}
+
+int i2c_client_init(struct i2c_client *client, struct i2c_adapter *adapter,
+		    uint8_t address)
+{
+	client->adapter = adapter;
+	client->address = address;
+
+	return 0;
+}
+
+int i2c_client_read(struct i2c_client *client, unsigned int address,
+		    size_t alen, void *buffer, size_t size)
+{
+	return i2c_adapter_read(client->adapter, client->address, address,
+				alen, buffer, size);
+}
+
+int i2c_client_write(struct i2c_client *client, unsigned int address,
+		     size_t alen, void *buffer, size_t size)
+{
+	return i2c_adapter_write(client->adapter, client->address, address,
+				 alen, buffer, size);
+}
include/i2c.h +96 -0

114 lines not on this page · raw message

Signature · 1 line
2.0.4
#40 lore raw

PATCH v2 13/40 i2c: Add high-level API

Hello Thierry,

Am 26.08.2014 17:34, schrieb Thierry Reding:

Quoted 3 lines

From: Thierry Reding<[email protected]>

This API operates on I2C adapters or I2C clients (a new type of object

which is a bad idea ...

Quoted 3 lines

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

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

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

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

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

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

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

Your code did not check this!

Why is i2c_set_bus_num() such a problem?

Quoted 193 lines

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

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

PATCH v2 13/40 i2c: Add high-level API

Quoted 9 lines · Heiko Schocher

Hello Thierry,

Am 26.08.2014 17:34, schrieb Thierry Reding:

Quoted 3 lines

From: Thierry Reding<[email protected]>

This API operates on I2C adapters or I2C clients (a new type of object

which is a bad idea ...

Quoted 7 lines
Quoted 3 lines

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

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

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

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

Quoted 13 lines

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

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

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

Quoted 2 lines

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

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

Quoted 7 lines

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

Your code did not check this!

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

Quoted 1 line

Why is i2c_set_bus_num() such a problem?

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

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

#42 lore raw

PATCH v2 13/40 i2c: Add high-level API

Hello Thierry,

Am 27.08.2014 08:21, schrieb Thierry Reding:

Quoted 14 lines · Heiko Schocher
Quoted 13 lines

Hello Thierry,

Am 26.08.2014 17:34, schrieb Thierry Reding:

Quoted 3 lines

From: Thierry Reding<[email protected]>

This API operates on I2C adapters or I2C clients (a new type of object

which is a bad idea ...

Quoted 3 lines

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

Quoted 6 lines
Quoted 3 lines

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

That's not what code does today. Everybody calls i2c_set_bus_num() once and then does a bunch of transactions on that bus. Given that U-Boot

Yes, sadly. This has historical reasons ...

Quoted 1 line

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

Yes, U-Boot is singlethread only.

Quoted 3 lines

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

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

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

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

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

Quoted 6 lines

this isn't going to work (in a multithreaded environment the switch to a different mux could happen between the call to i2c_set_bus_num() and the bus access).

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

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

Quoted 13 lines
Quoted 13 lines

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

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

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

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

That's complexity that users shouldn't have to worry about. They should

Exactly!

Quoted 2 lines

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

Yes!

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

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

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

Quoted 9 lines
Quoted 7 lines

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

Your code did not check this!

Like I said, a lot of code in U-Boot doesn't check this. And quite

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

Patches welcome!

Quoted 2 lines

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

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

Quoted 4 lines
Quoted 1 line

Why is i2c_set_bus_num() such a problem?

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

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

bye,
Heiko

Signature · 2 lines
DENX Software Engineering GmbH,     MD: Wolfgang Denk & Detlev Zundel
HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
#43 lore raw

PATCH v2 13/40 i2c: Add high-level API

Quoted 36 lines · Heiko Schocher

Hello Thierry,

Am 27.08.2014 08:21, schrieb Thierry Reding:

Quoted 14 lines · Heiko Schocher
Quoted 13 lines

Hello Thierry,

Am 26.08.2014 17:34, schrieb Thierry Reding:

Quoted 3 lines

From: Thierry Reding<[email protected]>

This API operates on I2C adapters or I2C clients (a new type of object

which is a bad idea ...

Quoted 3 lines

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

Quoted 6 lines
Quoted 3 lines

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

That's not what code does today. Everybody calls i2c_set_bus_num() once and then does a bunch of transactions on that bus. Given that U-Boot

Yes, sadly. This has historical reasons ...

Quoted 1 line

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

Yes, U-Boot is singlethread only.

Quoted 3 lines

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

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

Quoted 7 lines

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

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

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

Quoted 3 lines

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

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

Quoted 8 lines
Quoted 6 lines

this isn't going to work (in a multithreaded environment the switch to a different mux could happen between the call to i2c_set_bus_num() and the bus access).

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

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

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

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

Quoted 30 lines
Quoted 13 lines
Quoted 13 lines

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

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

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

Quoted 4 lines
Quoted 2 lines

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

That's complexity that users shouldn't have to worry about. They should

Exactly!

Quoted 2 lines

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

Yes!

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

Quoted 5 lines

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

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

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

Quoted 8 lines
Quoted 8 lines
Quoted 7 lines

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

Your code did not check this!

Quoted 8 lines
Quoted 1 line

Like I said, a lot of code in U-Boot doesn't check this. And quite

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

Patches welcome!

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

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

Quoted 7 lines
Quoted 2 lines

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

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

Quoted 7 lines
Quoted 4 lines
Quoted 1 line

Why is i2c_set_bus_num() such a problem?

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

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

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

Transitioning step by step is a lot less complicated.

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

#44 lore raw

PATCH v2 13/40 i2c: Add high-level API

Hello Thierry,

Am 27.08.2014 10:51, schrieb Thierry Reding:

Quoted 40 lines · Heiko Schocher
Quoted 39 lines

Hello Thierry,

Am 27.08.2014 08:21, schrieb Thierry Reding:

Quoted 14 lines · Heiko Schocher
Quoted 13 lines

Hello Thierry,

Am 26.08.2014 17:34, schrieb Thierry Reding:

Quoted 3 lines

From: Thierry Reding<[email protected]>

This API operates on I2C adapters or I2C clients (a new type of object

which is a bad idea ...

Quoted 3 lines

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

Quoted 6 lines
Quoted 3 lines

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

That's not what code does today. Everybody calls i2c_set_bus_num() once and then does a bunch of transactions on that bus. Given that U-Boot

Yes, sadly. This has historical reasons ...

Quoted 1 line

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

Yes, U-Boot is singlethread only.

Quoted 3 lines

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

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

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

Quoted 8 lines
Quoted 4 lines

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

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

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

Currently we have two "versions" of i2c_adapter:

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

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

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

Quoted 9 lines
Quoted 3 lines

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

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

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

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

Quoted 4 lines
Quoted 4 lines
Quoted 4 lines

this isn't going to work (in a multithreaded environment the switch to a different mux could happen between the call to i2c_set_bus_num() and the bus access).

Quoted 8 lines
Quoted 4 lines
Quoted 2 lines

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

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

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

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

Quoted 1 line

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

You ignore again muxes ...

Quoted 1 line

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

What does i2c_set_bus_num() ?

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

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

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

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

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

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

Why not defining:

[1]:
int i2c_bus_read(int bus, uint8_t chip,
unsigned int address, size_t alen, void *buffer, size_t size)

{
     i2c_set_bus_num(bus);
     return i2c_read(chip, address, alen, buffer, size);
}

int i2c_bus_write(int bus, uint8_t chip,
unsigned int address, size_t alen, void *buffer, size_t size)

{
     i2c_set_bus_num(bus);
     return i2c_write(chip, address, alen, buffer, size);
}

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

looking deeper in your approach:

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

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

Quoted 37 lines

adapters are made aware of a hierarchy if there are muxes, but I think that's worthwhile to do in any case. Also if ever I2C muxing needs to gain device tree support having the muxes set up dynamically will be pretty much a prerequisite.

Quoted 32 lines
Quoted 13 lines
Quoted 13 lines

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

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

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

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

That's complexity that users shouldn't have to worry about. They should

Exactly!

Quoted 2 lines

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

Yes!

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

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

Quoted 8 lines
Quoted 3 lines

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

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

Oh!

Quoted 2 lines

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

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

Quoted 15 lines
Quoted 15 lines
Quoted 9 lines
Quoted 7 lines

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

Your code did not check this!

Like I said, a lot of code in U-Boot doesn't check this. And quite

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

Quoted 7 lines
Quoted 1 line

Patches welcome!

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

Sound like use/introduce DM for I2C!

Quoted 5 lines

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

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

Quoted 9 lines
Quoted 9 lines
Quoted 2 lines

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

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

Quoted 2 lines
Quoted 1 line

Why is i2c_set_bus_num() such a problem?

Quoted 7 lines
Quoted 5 lines
Quoted 2 lines

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

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

Doing this kind of conversion is a nightmare. We'd be changing an API

Full Ack.

Quoted 6 lines

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

Transitioning step by step is a lot less complicated.

Ok, it was worth a try ;-)

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

bye,
Heiko

Signature · 2 lines
DENX Software Engineering GmbH,     MD: Wolfgang Denk & Detlev Zundel
HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
#45 lore raw

PATCH v2 13/40 i2c: Add high-level API

Quoted 48 lines · Heiko Schocher

Hello Thierry,

Am 27.08.2014 10:51, schrieb Thierry Reding:

Quoted 45 lines · Heiko Schocher
Quoted 43 lines

Hello Thierry,

Am 27.08.2014 08:21, schrieb Thierry Reding:

Quoted 14 lines · Heiko Schocher
Quoted 13 lines

Hello Thierry,

Am 26.08.2014 17:34, schrieb Thierry Reding:

Quoted 3 lines

From: Thierry Reding<[email protected]>

This API operates on I2C adapters or I2C clients (a new type of object

which is a bad idea ...

Quoted 3 lines

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

Quoted 6 lines
Quoted 3 lines

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

That's not what code does today. Everybody calls i2c_set_bus_num() once and then does a bunch of transactions on that bus. Given that U-Boot

Yes, sadly. This has historical reasons ...

Quoted 1 line

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

Yes, U-Boot is singlethread only.

Quoted 3 lines

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

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

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

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

Quoted 6 lines
Quoted 3 lines

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

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

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

Quoted 11 lines

Currently we have two "versions" of i2c_adapter:

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

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

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

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

Quoted 7 lines
Quoted 7 lines
Quoted 7 lines
Quoted 6 lines

this isn't going to work (in a multithreaded environment the switch to a different mux could happen between the call to i2c_set_bus_num() and the bus access).

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

Quoted 7 lines
Quoted 5 lines
Quoted 1 line

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

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

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

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

Quoted 6 lines
Quoted 1 line

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

You ignore again muxes ...

Quoted 1 line

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

Quoted 8 lines

What does i2c_set_bus_num() ?

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

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

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

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

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

Quoted 11 lines

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

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

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

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

Correct.

Quoted 14 lines

Why not defining:

[1]:
int i2c_bus_read(int bus, uint8_t chip,
unsigned int address, size_t alen, void *buffer, size_t size)

{
    i2c_set_bus_num(bus);
    return i2c_read(chip, address, alen, buffer, size);
}

int i2c_bus_write(int bus, uint8_t chip,
unsigned int address, size_t alen, void *buffer, size_t size)

Quoted 8 lines
{
    i2c_set_bus_num(bus);
    return i2c_write(chip, address, alen, buffer, size);
}

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

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

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

Quoted 11 lines

looking deeper in your approach:

drivers/i2c/i2c_core.c +8 -0
+int i2c_client_init(struct i2c_client *client, struct i2c_adapter *adapter,
+            uint8_t address)
+{
+    client->adapter = adapter;
+    client->address = address;
+
+    return 0;
+}
Quoted 3 lines

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

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

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

Quoted 46 lines
Quoted 37 lines

adapters are made aware of a hierarchy if there are muxes, but I think that's worthwhile to do in any case. Also if ever I2C muxing needs to gain device tree support having the muxes set up dynamically will be pretty much a prerequisite.

Quoted 32 lines
Quoted 13 lines
Quoted 13 lines

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

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

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

Quoted 4 lines
Quoted 2 lines

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

That's complexity that users shouldn't have to worry about. They should

Exactly!

Quoted 2 lines

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

Yes!

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

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

Quoted 8 lines
Quoted 3 lines

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

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

Quoted 7 lines

Oh!

Quoted 2 lines

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

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

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

Quoted 8 lines
Quoted 5 lines

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

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

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

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

#46 lore raw

PATCH v2 13/40 i2c: Add high-level API

Hi Thierry,

Quoted 68 lines · Thierry Reding
Quoted 48 lines · Heiko Schocher

Hello Thierry,

Am 27.08.2014 10:51, schrieb Thierry Reding:

Quoted 45 lines · Heiko Schocher
Quoted 43 lines

Hello Thierry,

Am 27.08.2014 08:21, schrieb Thierry Reding:

Quoted 14 lines · Heiko Schocher
Quoted 13 lines

Hello Thierry,

Am 26.08.2014 17:34, schrieb Thierry Reding:

Quoted 3 lines

From: Thierry Reding<[email protected]>

This API operates on I2C adapters or I2C clients (a new type of object

which is a bad idea ...

Quoted 3 lines

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

Quoted 6 lines
Quoted 3 lines

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

That's not what code does today. Everybody calls i2c_set_bus_num() once and then does a bunch of transactions on that bus. Given that U-Boot

Yes, sadly. This has historical reasons ...

Quoted 1 line

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

Yes, U-Boot is singlethread only.

Quoted 3 lines

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

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

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

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

Quoted 6 lines
Quoted 3 lines

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

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

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

Quoted 8 lines

Currently we have two "versions" of i2c_adapter:

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

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

Quoted 7 lines
Quoted 3 lines

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

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

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

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

Regards,
Simon

#47 lore raw

PATCH v2 13/40 i2c: Add high-level API

Hello Simon,

Am 27.08.2014 21:10, schrieb Simon Glass:

Quoted 79 lines

Hi Thierry,

Quoted 68 lines · Thierry Reding
Quoted 48 lines · Heiko Schocher

Hello Thierry,

Am 27.08.2014 10:51, schrieb Thierry Reding:

Quoted 45 lines · Heiko Schocher
Quoted 43 lines

Hello Thierry,

Am 27.08.2014 08:21, schrieb Thierry Reding:

Quoted 14 lines · Heiko Schocher
Quoted 13 lines

Hello Thierry,

Am 26.08.2014 17:34, schrieb Thierry Reding:

Quoted 3 lines

From: Thierry Reding<[email protected]>

This API operates on I2C adapters or I2C clients (a new type of object

which is a bad idea ...

Quoted 3 lines

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

Quoted 6 lines
Quoted 3 lines

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

That's not what code does today. Everybody calls i2c_set_bus_num() once and then does a bunch of transactions on that bus. Given that U-Boot

Yes, sadly. This has historical reasons ...

Quoted 1 line

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

Yes, U-Boot is singlethread only.

Quoted 3 lines

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

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

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

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

Quoted 6 lines
Quoted 3 lines

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

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

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

Quoted 8 lines

Currently we have two "versions" of i2c_adapter:

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

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

Quoted 7 lines
Quoted 3 lines

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

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

Quoted 8 lines

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

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

That sounds great! I vote for using DM.

bye,
Heiko

Signature · 2 lines
DENX Software Engineering GmbH,     MD: Wolfgang Denk & Detlev Zundel
HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
#48 lore raw

PATCH v2 14/40 i2c: tegra: Implement i2c_get_bus_num_fdt()

In reply to Thierry Reding

From: Thierry Reding <[email protected]>

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

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

PATCH v2 15/40 power: Add AMS AS3722 PMIC support

In reply to Thierry Reding

From: Thierry Reding <[email protected]>

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

---
 drivers/power/Makefile |   1 +
 drivers/power/as3722.c | 300 +++++++++++++++++++++++++++++++++++++++++++++++++
 include/fdtdec.h       |   1 +
 include/power/as3722.h |  27 +++++
 lib/fdtdec.c           |   1 +
 5 files changed, 330 insertions(+)
 create mode 100644 drivers/power/as3722.c
 create mode 100644 include/power/as3722.h
drivers/power/Makefile +1 -0
index dc64e4d32bff..b3097316e27e 100644
@@ -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
drivers/power/as3722.c new file +300 -0

300 lines not on this page · raw message

include/fdtdec.h +1 -0
index 5c669a5c8e03..3c38375397df 100644
@@ -115,6 +115,7 @@ enum fdt_compat_id {
 	COMPAT_SANDBOX_LCD_SDL,		/* Sandbox LCD emulation with SDL */
 	COMPAT_TI_TPS65090,		/* Texas Instrument TPS65090 */
 	COMPAT_NXP_PTN3460,		/* NXP PTN3460 DP/LVDS bridge */
+	COMPAT_AMS_AS3722,		/* AMS AS3722 PMIC */
 
 	COMPAT_COUNT,
 };
include/power/as3722.h new file +27 -0
new file mode 100644
index 000000000000..2c2e45a44bab
@@ -0,0 +1,27 @@
+/*
+ * Copyright (C) 2014 NVIDIA Corporation
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+#ifndef __POWER_AS3722_H__
+#define __POWER_AS3722_H__
+
+#include <asm/types.h>
+
+#define AS3722_GPIO_OUTPUT_VDDH (1 << 0)
+#define AS3722_GPIO_INVERT (1 << 1)
+
+struct as3722;
+
+int as3722_init(struct as3722 **pmic, const void *fdt);
+int as3722_sd_enable(struct as3722 *pmic, unsigned int sd);
+int as3722_sd_set_voltage(struct as3722 *pmic, unsigned int sd, u8 value);
+int as3722_ldo_enable(struct as3722 *pmic, unsigned int ldo);
+int as3722_ldo_set_voltage(struct as3722 *pmic, unsigned int ldo, u8 value);
+int as3722_gpio_configure(struct as3722 *pmic, unsigned int gpio,
+			  unsigned long flags);
+int as3722_gpio_direction_output(struct as3722 *pmic, unsigned int gpio,
+				 unsigned int level);
+
+#endif /* __POWER_AS3722_H__ */
lib/fdtdec.c +1 -0
index fa5da0c0147d..cddd86c3186f 100644
@@ -70,6 +70,7 @@ static const char * const compat_names[COMPAT_COUNT] = {
 	COMPAT(SANDBOX_LCD_SDL, "sandbox,lcd-sdl"),
 	COMPAT(TI_TPS65090, "ti,tps65090"),
 	COMPAT(COMPAT_NXP_PTN3460, "nxp,ptn3460"),
+	COMPAT(AMS_AS3722, "ams,as3722"),
 };
 
 const char *fdtdec_get_compatible(enum fdt_compat_id id)
Signature · 1 line
2.0.4
#51 lore raw

PATCH v2 15/40 power: Add AMS AS3722 PMIC support

Hello Thierry,

Am 26.08.2014 17:34, schrieb Thierry Reding:

Quoted 297 lines

From: Thierry Reding<[email protected]>

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

---
  drivers/power/Makefile |   1 +
  drivers/power/as3722.c | 300 +++++++++++++++++++++++++++++++++++++++++++++++++
  include/fdtdec.h       |   1 +
  include/power/as3722.h |  27 +++++
  lib/fdtdec.c           |   1 +
  5 files changed, 330 insertions(+)

create mode 100644 drivers/power/as3722.c
create mode 100644 include/power/as3722.h

drivers/power/Makefile +1 -0
index dc64e4d32bff..b3097316e27e 100644
@@ -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
drivers/power/as3722.c new file +263 -0
new file mode 100644
index 000000000000..59d1bf1b50b0
@@ -0,0 +1,300 @@
+/*
+ * Copyright (C) 2014 NVIDIA Corporation
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+#define pr_fmt(fmt) "as3722: " fmt
+
+#include<common.h>
+#include<errno.h>
+#include<fdtdec.h>
+#include<i2c.h>
+
+#include<power/as3722.h>
+
+#define AS3722_SD_VOLTAGE(n) (0x00 + (n))
+#define AS3722_GPIO_CONTROL(n) (0x08 + (n))
+#define  AS3722_GPIO_CONTROL_MODE_OUTPUT_VDDH (1<<  0)
+#define  AS3722_GPIO_CONTROL_MODE_OUTPUT_VDDL (7<<  0)
+#define  AS3722_GPIO_CONTROL_INVERT (1<<  7)
+#define AS3722_LDO_VOLTAGE(n) (0x10 + (n))
+#define AS3722_GPIO_SIGNAL_OUT 0x20
+#define AS3722_SD_CONTROL 0x4d
+#define AS3722_LDO_CONTROL 0x4e
+#define AS3722_ASIC_ID1 0x90
+#define  AS3722_DEVICE_ID 0x0c
+#define AS3722_ASIC_ID2 0x91
+
+struct as3722 {
+	struct i2c_client client;
+	u8 address;
+};
+
+static struct as3722 as3722_pmic;
+
+static int as3722_read(struct as3722 *pmic, u8 reg, u8 *value)
+{
+	int err;
+
+	err = i2c_client_read(&pmic->client, reg, 1, value, 1);
+	if (err<  0)
+		return err;
+
+	return 0;
+}
+
+static int as3722_write(struct as3722 *pmic, u8 reg, u8 value)
+{
+	int err;
+
+	err = i2c_client_write(&pmic->client, reg, 1,&value, 1);
+	if (err<  0)
+		return err;
+
+	return 0;
+}
+
+static int as3722_read_id(struct as3722 *pmic, u8 *id, u8 *revision)
+{
+	int err;
+
+	err = as3722_read(pmic, AS3722_ASIC_ID1, id);
+	if (err) {
+		error("failed to read ID1 register: %d", err);
+		return err;
+	}
+
+	err = as3722_read(pmic, AS3722_ASIC_ID2, revision);
+	if (err) {
+		error("failed to read ID2 register: %d", err);
+		return err;
+	}
+
+	return 0;
+}
+
+int as3722_sd_enable(struct as3722 *pmic, unsigned int sd)
+{
+	u8 value;
+	int err;
+
+	if (sd>  6)
+		return -EINVAL;
+
+	err = as3722_read(pmic, AS3722_SD_CONTROL,&value);
+	if (err) {
+		error("failed to read SD control register: %d", err);
+		return err;
+	}
+
+	value |= 1<<  sd;
+
+	err = as3722_write(pmic, AS3722_SD_CONTROL, value);
+	if (err<  0) {
+		error("failed to write SD control register: %d", err);
+		return err;
+	}
+
+	return 0;
+}
+
+int as3722_sd_set_voltage(struct as3722 *pmic, unsigned int sd, u8 value)
+{
+	int err;
+
+	if (sd>  6)
+		return -EINVAL;
+
+	err = as3722_write(pmic, AS3722_SD_VOLTAGE(sd), value);
+	if (err<  0) {
+		error("failed to write SD%u voltage register: %d", sd, err);
+		return err;
+	}
+
+	return 0;
+}
+
+int as3722_ldo_enable(struct as3722 *pmic, unsigned int ldo)
+{
+	u8 value;
+	int err;
+
+	if (ldo>  11)
+		return -EINVAL;
+
+	err = as3722_read(pmic, AS3722_LDO_CONTROL,&value);
+	if (err) {
+		error("failed to read LDO control register: %d", err);
+		return err;
+	}
+
+	value |= 1<<  ldo;
+
+	err = as3722_write(pmic, AS3722_LDO_CONTROL, value);
+	if (err<  0) {
+		error("failed to write LDO control register: %d", err);
+		return err;
+	}
+
+	return 0;
+}
+
+int as3722_ldo_set_voltage(struct as3722 *pmic, unsigned int ldo, u8 value)
+{
+	int err;
+
+	if (ldo>  11)
+		return -EINVAL;
+
+	err = as3722_write(pmic, AS3722_LDO_VOLTAGE(ldo), value);
+	if (err<  0) {
+		error("failed to write LDO%u voltage register: %d", ldo,
+		      err);
+		return err;
+	}
+
+	return 0;
+}
+
+int as3722_gpio_configure(struct as3722 *pmic, unsigned int gpio,
+			  unsigned long flags)
+{
+	u8 value = 0;
+	int err;
+
+	if (flags&  AS3722_GPIO_OUTPUT_VDDH)
+		value |= AS3722_GPIO_CONTROL_MODE_OUTPUT_VDDH;
+
+	if (flags&  AS3722_GPIO_INVERT)
+		value |= AS3722_GPIO_CONTROL_INVERT;
+
+	err = as3722_write(pmic, AS3722_GPIO_CONTROL(gpio), value);
+	if (err) {
+		error("failed to configure GPIO#%u: %d", gpio, err);
+		return err;
+	}
+
+	return 0;
+}
+
+static int as3722_gpio_set(struct as3722 *pmic, unsigned int gpio,
+			   unsigned int level)
+{
+	const char *l;
+	u8 value;
+	int err;
+
+	if (gpio>  7)
+		return -EINVAL;
+
+	err = as3722_read(pmic, AS3722_GPIO_SIGNAL_OUT,&value);
+	if (err<  0) {
+		error("failed to read GPIO signal out register: %d", err);
+		return err;
+	}
+
+	if (level == 0) {
+		value&= ~(1<<  gpio);
+		l = "low";
+	} else {
+		value |= 1<<  gpio;
+		l = "high";
+	}
+
+	err = as3722_write(pmic, AS3722_GPIO_SIGNAL_OUT, value);
+	if (err) {
+		error("failed to set GPIO#%u %s: %d", gpio, l, err);
+		return err;
+	}
+
+	return 0;
+}
+
+int as3722_gpio_direction_output(struct as3722 *pmic, unsigned int gpio,
+				 unsigned int level)
+{
+	u8 value;
+	int err;
+
+	if (gpio>  7)
+		return -EINVAL;
+
+	if (level == 0)
+		value = AS3722_GPIO_CONTROL_MODE_OUTPUT_VDDL;
+	else
+		value = AS3722_GPIO_CONTROL_MODE_OUTPUT_VDDH;
+
+	err = as3722_write(pmic, AS3722_GPIO_CONTROL(gpio), value);
+	if (err) {
+		error("failed to configure GPIO#%u as output: %d", gpio, err);
+		return err;
+	}
+
+	err = as3722_gpio_set(pmic, gpio, level);
+	if (err<  0) {
+		error("failed to set GPIO#%u high: %d", gpio, err);
+		return err;
+	}
+
+	return 0;
+}
+
+int as3722_init(struct as3722 **pmicp, const void *fdt)
+{
+	struct as3722 *pmic =&as3722_pmic;
+	int count, nodes[1], i;
+	int err;
+
+	count = fdtdec_find_aliases_for_id(fdt, NULL, COMPAT_AMS_AS3722,
+					   nodes, ARRAY_SIZE(nodes));
+	for (i = 0; i<  count; i++) {
+		int parent = fdt_parent_offset(fdt, nodes[i]), bus;
+		struct i2c_adapter *adapter;
+		fdt_addr_t address;
+		u8 id, revision;
+
+		bus = i2c_get_bus_num_fdt(parent);
+		if (bus<  0) {
+			error("invalid bus %d", bus);
+			continue;
+		}
+
+		address = fdtdec_get_addr(fdt, nodes[i], "reg");

drivers/power/as3722.c line 273

Quoted 10 lines
drivers/power/as3722.c new file +10 -0
+		if (address == FDT_ADDR_T_NONE) {
+			error("slave address not found");
+			continue;
+		}
+
+		adapter = i2c_adapter_get(bus);
+		if (!adapter) {
+			error("I2C adapter for bus %d not found", bus);
+			continue;
+		}

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

bye,
Heiko

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

PATCH v2 15/40 power: Add AMS AS3722 PMIC support

Quoted 3 lines · Heiko Schocher

Hello Thierry,

Am 26.08.2014 17:34, schrieb Thierry Reding:

[...]

Quoted 27 lines
Quoted 27 lines
drivers/power/as3722.c new file +27 -0
+int as3722_init(struct as3722 **pmicp, const void *fdt)
+{
+	struct as3722 *pmic =&as3722_pmic;
+	int count, nodes[1], i;
+	int err;
+
+	count = fdtdec_find_aliases_for_id(fdt, NULL, COMPAT_AMS_AS3722,
+					   nodes, ARRAY_SIZE(nodes));
+	for (i = 0; i<  count; i++) {
+		int parent = fdt_parent_offset(fdt, nodes[i]), bus;
+		struct i2c_adapter *adapter;
+		fdt_addr_t address;
+		u8 id, revision;
+
+		bus = i2c_get_bus_num_fdt(parent);
+		if (bus<  0) {
+			error("invalid bus %d", bus);
+			continue;
+		}
+
+		address = fdtdec_get_addr(fdt, nodes[i], "reg");
+		if (address == FDT_ADDR_T_NONE) {
+			error("slave address not found");
+			continue;
+		}
+
+		adapter = i2c_adapter_get(bus);
Quoted 8 lines

drivers/power/as3722.c line 273

Quoted 4 lines
drivers/power/as3722.c new file +4 -0
+		if (!adapter) {
+			error("I2C adapter for bus %d not found", bus);
+			continue;
+		}

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

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

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

#53 lore raw

PATCH v2 15/40 power: Add AMS AS3722 PMIC support

Hello Thierry,

Am 27.08.2014 08:28, schrieb Thierry Reding:

Quoted 41 lines · Heiko Schocher
Quoted 3 lines

Hello Thierry,

Am 26.08.2014 17:34, schrieb Thierry Reding:

[...]

Quoted 27 lines
Quoted 27 lines
drivers/power/as3722.c new file +27 -0
+int as3722_init(struct as3722 **pmicp, const void *fdt)
+{
+	struct as3722 *pmic =&as3722_pmic;
+	int count, nodes[1], i;
+	int err;
+
+	count = fdtdec_find_aliases_for_id(fdt, NULL, COMPAT_AMS_AS3722,
+					   nodes, ARRAY_SIZE(nodes));
+	for (i = 0; i<   count; i++) {
+		int parent = fdt_parent_offset(fdt, nodes[i]), bus;
+		struct i2c_adapter *adapter;
+		fdt_addr_t address;
+		u8 id, revision;
+
+		bus = i2c_get_bus_num_fdt(parent);
+		if (bus<   0) {
+			error("invalid bus %d", bus);
+			continue;
+		}
+
+		address = fdtdec_get_addr(fdt, nodes[i], "reg");
+		if (address == FDT_ADDR_T_NONE) {
+			error("slave address not found");
+			continue;
+		}
+
+		adapter = i2c_adapter_get(bus);
Quoted 8 lines

drivers/power/as3722.c line 273

Quoted 4 lines
drivers/power/as3722.c new file +4 -0
+		if (!adapter) {
+			error("I2C adapter for bus %d not found", bus);
+			continue;
+		}

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

Quoted 2 lines

As I explained earlier, I think requiring users to manually micro-manage the I2C busses is a bad idea. It's very tedious and error prone. It does

I fully aggree with you.

Quoted 4 lines

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

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

Quoted 3 lines

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

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

On my ToDo list:

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

bye,
Heiko

Signature · 2 lines
DENX Software Engineering GmbH,     MD: Wolfgang Denk & Detlev Zundel
HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
#54 lore raw

PATCH v2 16/40 ARM: tegra: Implement tegra_plle_enable()

In reply to Thierry Reding

From: Thierry Reding <[email protected]>

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

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

146 lines not on this page · raw message

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

163 lines not on this page · raw message

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

PATCH v2 17/40 ARM: tegra: Provide PCIEXCLK reset ID

In reply to Thierry Reding

From: Thierry Reding <[email protected]>

This reset is required for PCIe and the corresponding ID therefore needs to be defined. 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.

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

PATCH v2 18/40 ARM: tegra: Implement powergate support

In reply to Thierry Reding

From: Thierry Reding <[email protected]>

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

---
Changes in v2:
- wait for power-up/off operation to complete before returning
- document PCIE/VDEC mixup in REMOVE_CLAMPING register
- add symbolic name for REMOVE_CLAMPING register
- list all partitions available on existing SoCs

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

102 lines not on this page · raw message

arch/arm/include/asm/arch-tegra/powergate.h new file +38 -0
new file mode 100644
index 000000000000..130b58bef1b4
@@ -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
arch/arm/include/asm/arch-tegra114/powergate.h new file +6 -0
new file mode 100644
index 000000000000..260ea801b81b
@@ -0,0 +1,6 @@
+#ifndef _TEGRA114_POWERGATE_H_
+#define _TEGRA114_POWERGATE_H_
+
+#include <asm/arch-tegra/powergate.h>
+
+#endif /* _TEGRA114_POWERGATE_H_ */
arch/arm/include/asm/arch-tegra124/powergate.h new file +6 -0
new file mode 100644
index 000000000000..8a0cfbaf9665
@@ -0,0 +1,6 @@
+#ifndef _TEGRA124_POWERGATE_H_
+#define _TEGRA124_POWERGATE_H_
+
+#include <asm/arch-tegra/powergate.h>
+
+#endif /* _TEGRA124_POWERGATE_H_ */
arch/arm/include/asm/arch-tegra20/powergate.h new file +6 -0
new file mode 100644
index 000000000000..439d88b7022a
@@ -0,0 +1,6 @@
+#ifndef _TEGRA20_POWERGATE_H_
+#define _TEGRA20_POWERGATE_H_
+
+#include <asm/arch-tegra/powergate.h>
+
+#endif /* _TEGRA20_POWERGATE_H_ */
arch/arm/include/asm/arch-tegra30/powergate.h new file +6 -0
new file mode 100644
index 000000000000..c70e44b6216d
@@ -0,0 +1,6 @@
+#ifndef _TEGRA30_POWERGATE_H_
+#define _TEGRA30_POWERGATE_H_
+
+#include <asm/arch-tegra/powergate.h>
+
+#endif /* _TEGRA30_POWERGATE_H_ */
Signature · 1 line
2.0.4
#57 lore raw

PATCH v2 19/40 ARM: tegra: Implement XUSB pad controller

In reply to Thierry Reding

From: Thierry Reding <[email protected]>

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

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

---
Changes in v2:
- remove needless header files
- move more helpers to libfdt
- describe PHY type

 arch/arm/cpu/tegra-common/Makefile               |   1 +
 arch/arm/cpu/tegra-common/xusb-padctl.c          |  39 ++
 arch/arm/cpu/tegra124-common/Makefile            |   1 +
 arch/arm/cpu/tegra124-common/xusb-padctl.c       | 716 +++++++++++++++++++++++
 arch/arm/include/asm/arch-tegra/xusb-padctl.h    |  24 +
 board/nvidia/common/board.c                      |   3 +
 include/dt-bindings/pinctrl/pinctrl-tegra-xusb.h |   7 +
 include/fdtdec.h                                 |   2 +
 lib/fdtdec.c                                     |   1 +
 9 files changed, 794 insertions(+)
 create mode 100644 arch/arm/cpu/tegra-common/xusb-padctl.c
 create mode 100644 arch/arm/cpu/tegra124-common/xusb-padctl.c
 create mode 100644 arch/arm/include/asm/arch-tegra/xusb-padctl.h
 create mode 100644 include/dt-bindings/pinctrl/pinctrl-tegra-xusb.h
arch/arm/cpu/tegra-common/Makefile +1 -0
index fed618ba8fc9..528ffe0a2fcc 100644
@@ -14,4 +14,5 @@ obj-y += clock.o
 obj-y += lowlevel_init.o
 obj-y += pinmux-common.o
 obj-y += powergate.o
+obj-y += xusb-padctl.o
 obj-$(CONFIG_DISPLAY_CPUINFO) += sys_info.o
arch/arm/cpu/tegra-common/xusb-padctl.c new file +39 -0
new file mode 100644
index 000000000000..65f8d2ea967a
@@ -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)
+{
+}
arch/arm/cpu/tegra124-common/Makefile +1 -0
index ff77992b330c..7b59fb121614 100644
@@ -8,3 +8,4 @@
 obj-y	+= clock.o
 obj-y	+= funcmux.o
 obj-y	+= pinmux.o
+obj-y	+= xusb-padctl.o
arch/arm/cpu/tegra124-common/xusb-padctl.c new file +716 -0

716 lines not on this page · raw message

arch/arm/include/asm/arch-tegra/xusb-padctl.h new file +24 -0
new file mode 100644
index 000000000000..b4b4c8ba4d10
@@ -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
board/nvidia/common/board.c +3 -0
index d01abcee13c1..04573c980189 100644
@@ -37,6 +37,7 @@
 #include <asm/arch-tegra/tegra_mmc.h>
 #include <asm/arch-tegra/mmc.h>
 #endif
+#include <asm/arch-tegra/xusb-padctl.h>
 #include <i2c.h>
 #include <spi.h>
 #include "emc.h"
@@ -161,6 +162,8 @@ int board_init(void)
 	pin_mux_nand();
 #endif
 
+	tegra_xusb_padctl_init(gd->fdt_blob);
+
 #ifdef CONFIG_TEGRA_LP0
 	/* save Sdram params to PMC 2, 4, and 24 for WB0 */
 	warmboot_save_sdram_params();
include/dt-bindings/pinctrl/pinctrl-tegra-xusb.h new file +7 -0
new file mode 100644
index 000000000000..914d56da9324
@@ -0,0 +1,7 @@
+#ifndef _DT_BINDINGS_PINCTRL_TEGRA_XUSB_H
+#define _DT_BINDINGS_PINCTRL_TEGRA_XUSB_H 1
+
+#define TEGRA_XUSB_PADCTL_PCIE 0
+#define TEGRA_XUSB_PADCTL_SATA 1
+
+#endif /* _DT_BINDINGS_PINCTRL_TEGRA_XUSB_H */
include/fdtdec.h +2 -0
index 3c38375397df..364da6c67cd2 100644
@@ -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 */
lib/fdtdec.c +1 -0
index cddd86c3186f..f4851592687f 100644
@@ -41,6 +41,7 @@ static const char * const compat_names[COMPAT_COUNT] = {
 	COMPAT(NVIDIA_TEGRA20_SFLASH, "nvidia,tegra20-sflash"),
 	COMPAT(NVIDIA_TEGRA20_SLINK, "nvidia,tegra20-slink"),
 	COMPAT(NVIDIA_TEGRA114_SPI, "nvidia,tegra114-spi"),
+	COMPAT(NVIDIA_TEGRA124_XUSB_PADCTL, "nvidia,tegra124-xusb-padctl"),
 	COMPAT(SMSC_LAN9215, "smsc,lan9215"),
 	COMPAT(SAMSUNG_EXYNOS5_SROMC, "samsung,exynos-sromc"),
 	COMPAT(SAMSUNG_S3C2440_I2C, "samsung,s3c2440-i2c"),
Signature · 1 line
2.0.4
#58 lore raw

PATCH v2 20/40 ARM: tegra: Add XUSB pad controller on Tegra124

In reply to Thierry Reding

From: Thierry Reding <[email protected]>

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

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

PATCH v2 21/40 ARM: tegra: Enable XUSB pad controller on Jetson TK1

In reply to Thierry Reding

From: Thierry Reding <[email protected]>

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

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

PATCH v2 22/40 pci: tegra: Add Tegra PCIe driver

In reply to Thierry Reding

From: Thierry Reding <[email protected]>

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

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

---
Changes in v2:
- update copyright statement
- add Mike's Signed-off-by

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

1,143 lines not on this page · raw message

include/fdtdec.h +3 -0
index 364da6c67cd2..925133fa48d0 100644
@@ -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 */
lib/fdtdec.c +3 -0
index f4851592687f..9ec826205855 100644
@@ -41,6 +41,9 @@ static const char * const compat_names[COMPAT_COUNT] = {
 	COMPAT(NVIDIA_TEGRA20_SFLASH, "nvidia,tegra20-sflash"),
 	COMPAT(NVIDIA_TEGRA20_SLINK, "nvidia,tegra20-slink"),
 	COMPAT(NVIDIA_TEGRA114_SPI, "nvidia,tegra114-spi"),
+	COMPAT(NVIDIA_TEGRA124_PCIE, "nvidia,tegra124-pcie"),
+	COMPAT(NVIDIA_TEGRA30_PCIE, "nvidia,tegra30-pcie"),
+	COMPAT(NVIDIA_TEGRA20_PCIE, "nvidia,tegra20-pcie"),
 	COMPAT(NVIDIA_TEGRA124_XUSB_PADCTL, "nvidia,tegra124-xusb-padctl"),
 	COMPAT(SMSC_LAN9215, "smsc,lan9215"),
 	COMPAT(SAMSUNG_EXYNOS5_SROMC, "samsung,exynos-sromc"),
Signature · 1 line
2.0.4
#61 lore raw

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

In reply to Thierry Reding

From: Thierry Reding <[email protected]>

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

---
Changes in v2:
- add missing interrupt-map-mask and interrupt-map properties
- include unit address in device tree node name

 arch/arm/dts/tegra20.dtsi               |  60 ++++++++++++
 include/dt-bindings/clock/tegra20-car.h | 158 ++++++++++++++++++++++++++++++++
 2 files changed, 218 insertions(+)
 create mode 100644 include/dt-bindings/clock/tegra20-car.h
arch/arm/dts/tegra20.dtsi +60 -0
index a524f6eed410..39976864fa48 100644
@@ -1,3 +1,4 @@
+#include <dt-bindings/clock/tegra20-car.h>
 #include <dt-bindings/gpio/tegra-gpio.h>
 #include <dt-bindings/interrupt-controller/arm-gic.h>
 
@@ -301,6 +302,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>;
include/dt-bindings/clock/tegra20-car.h new file +158 -0

158 lines not on this page · raw message

Signature · 1 line
2.0.4
#62 lore raw

PATCH v2 24/40 ARM: tegra: Enable PCIe on TrimSlice

In reply to Thierry Reding

From: Thierry Reding <[email protected]>

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

---
Changes in v2:
- add all regulators from Linux kernel DTS
- use proper set of PCIe power supplies
- use unit-address in node name

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

PATCH v2 25/40 ARM: tegra: Add GIC for Tegra30

In reply to Thierry Reding

From: Thierry Reding <[email protected]>

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.

---
 arch/arm/dts/tegra30.dtsi | 9 +++++++++
 1 file changed, 9 insertions(+)
arch/arm/dts/tegra30.dtsi +9 -0
index 7be3791fc9a6..8b8940df796a 100644
@@ -5,6 +5,15 @@
 
 / {
 	compatible = "nvidia,tegra30";
+	interrupt-parent = <&intc>;
+
+	intc: interrupt-controller at 50041000 {
+		compatible = "arm,cortex-a9-gic";
+		reg = <0x50041000 0x1000
+		       0x50040100 0x0100>;
+		interrupt-controller;
+		#interrupt-cells = <3>;
+	};
 
 	tegra_car: clock {
 		compatible = "nvidia,tegra30-car";
Signature · 1 line
2.0.4
#64 lore raw

PATCH v2 26/40 ARM: tegra: Add Tegra30 PCIe device tree node

In reply to Thierry Reding

From: Thierry Reding <[email protected]>

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

---
Changes in v2:
- include unit address in device tree node name
- add missing interrupt-map-mask and interrupt-map properties

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

265 lines not on this page · raw message

Signature · 1 line
2.0.4
#65 lore raw

PATCH v2 27/40 ARM: tegra: Enable PCIe on Cardhu

In reply to Thierry Reding

From: Thierry Reding <[email protected]>

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

---
Changes in v2:
- write to instead of read from the LDO2_REG register to enable LDO2
- use proper set of PCIe power supplies
- use unit address in node name

 arch/arm/dts/tegra30-cardhu.dts | 362 ++++++++++++++++++++++++++++++++++++++++
 board/nvidia/cardhu/cardhu.c    |  56 +++++++
 include/configs/cardhu.h        |  10 ++
 3 files changed, 428 insertions(+)
arch/arm/dts/tegra30-cardhu.dts +362 -0
index ea2cf76ff3a8..54e08f59da12 100644
@@ -22,6 +22,31 @@
 		reg = <0x80000000 0x40000000>;
 	};
 
+	pcie-controller at 00003000 {
+		status = "okay";
+
+		/* AVDD_PEXA and VDD_PEXA inputs are grounded on Cardhu. */
+		avdd-pexb-supply = <&ldo1_reg>;
+		vdd-pexb-supply = <&ldo1_reg>;
+		avdd-pex-pll-supply = <&ldo1_reg>;
+		hvdd-pex-supply = <&pex_hvdd_3v3_reg>;
+		vddio-pex-ctl-supply = <&sys_3v3_reg>;
+		avdd-plle-supply = <&ldo2_reg>;
+
+		pci at 1,0 {
+			nvidia,num-lanes = <4>;
+		};
+
+		pci at 2,0 {
+			nvidia,num-lanes = <1>;
+		};
+
+		pci at 3,0 {
+			status = "okay";
+			nvidia,num-lanes = <1>;
+		};
+	};
+
 	i2c at 7000c000 {
 		status = "okay";
 		clock-frequency = <100000>;
@@ -45,6 +70,107 @@
 	i2c at 7000d000 {
 		status = "okay";
 		clock-frequency = <100000>;
+
+		pmic: tps65911 at 2d {
+			compatible = "ti,tps65911";
+			reg = <0x2d>;
+
+			interrupts = <GIC_SPI 86 IRQ_TYPE_LEVEL_HIGH>;
+			#interrupt-cells = <2>;
+			interrupt-controller;
+
+			ti,system-power-controller;
+
+			#gpio-cells = <2>;
+			gpio-controller;
+
+			vcc1-supply = <&vdd_ac_bat_reg>;
+			vcc2-supply = <&vdd_ac_bat_reg>;
+			vcc3-supply = <&vio_reg>;
+			vcc4-supply = <&vdd_5v0_reg>;
+			vcc5-supply = <&vdd_ac_bat_reg>;
+			vcc6-supply = <&vdd2_reg>;
+			vcc7-supply = <&vdd_ac_bat_reg>;
+			vccio-supply = <&vdd_ac_bat_reg>;
+
+			regulators {
+				vdd1_reg: vdd1 {
+					regulator-name = "vddio_ddr_1v2";
+					regulator-min-microvolt = <1200000>;
+					regulator-max-microvolt = <1200000>;
+					regulator-always-on;
+				};
+
+				vdd2_reg: vdd2 {
+					regulator-name = "vdd_1v5_gen";
+					regulator-min-microvolt = <1500000>;
+					regulator-max-microvolt = <1500000>;
+					regulator-always-on;
+				};
+
+				vddctrl_reg: vddctrl {
+					regulator-name = "vdd_cpu,vdd_sys";
+					regulator-min-microvolt = <1000000>;
+					regulator-max-microvolt = <1000000>;
+					regulator-always-on;
+				};
+
+				vio_reg: vio {
+					regulator-name = "vdd_1v8_gen";
+					regulator-min-microvolt = <1800000>;
+					regulator-max-microvolt = <1800000>;
+					regulator-always-on;
+				};
+
+				ldo1_reg: ldo1 {
+					regulator-name = "vdd_pexa,vdd_pexb";
+					regulator-min-microvolt = <1050000>;
+					regulator-max-microvolt = <1050000>;
+				};
+
+				ldo2_reg: ldo2 {
+					regulator-name = "vdd_sata,avdd_plle";
+					regulator-min-microvolt = <1050000>;
+					regulator-max-microvolt = <1050000>;
+				};
+
+				/* LDO3 is not connected to anything */
+
+				ldo4_reg: ldo4 {
+					regulator-name = "vdd_rtc";
+					regulator-min-microvolt = <1200000>;
+					regulator-max-microvolt = <1200000>;
+					regulator-always-on;
+				};
+
+				ldo5_reg: ldo5 {
+					regulator-name = "vddio_sdmmc,avdd_vdac";
+					regulator-min-microvolt = <3300000>;
+					regulator-max-microvolt = <3300000>;
+					regulator-always-on;
+				};
+
+				ldo6_reg: ldo6 {
+					regulator-name = "avdd_dsi_csi,pwrdet_mipi";
+					regulator-min-microvolt = <1200000>;
+					regulator-max-microvolt = <1200000>;
+				};
+
+				ldo7_reg: ldo7 {
+					regulator-name = "vdd_pllm,x,u,a_p_c_s";
+					regulator-min-microvolt = <1200000>;
+					regulator-max-microvolt = <1200000>;
+					regulator-always-on;
+				};
+
+				ldo8_reg: ldo8 {
+					regulator-name = "vdd_ddr_hs";
+					regulator-min-microvolt = <1000000>;
+					regulator-max-microvolt = <1000000>;
+					regulator-always-on;
+				};
+			};
+		};
 	};
 
 	spi at 7000da00 {
@@ -69,4 +195,240 @@
 		nvidia,vbus-gpio = <&gpio 236 0>;	/* PDD4 */
 		status = "okay";
 	};
+
+	regulators {
+		compatible = "simple-bus";
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		vdd_ac_bat_reg: regulator at 0 {
+			compatible = "regulator-fixed";
+			reg = <0>;
+			regulator-name = "vdd_ac_bat";
+			regulator-min-microvolt = <5000000>;
+			regulator-max-microvolt = <5000000>;
+			regulator-always-on;
+		};
+
+		cam_1v8_reg: regulator at 1 {
+			compatible = "regulator-fixed";
+			reg = <1>;
+			regulator-name = "cam_1v8";
+			regulator-min-microvolt = <1800000>;
+			regulator-max-microvolt = <1800000>;
+			enable-active-high;
+			gpio = <&gpio TEGRA_GPIO(BB, 4) GPIO_ACTIVE_HIGH>;
+			vin-supply = <&vio_reg>;
+		};
+
+		cp_5v_reg: regulator at 2 {
+			compatible = "regulator-fixed";
+			reg = <2>;
+			regulator-name = "cp_5v";
+			regulator-min-microvolt = <5000000>;
+			regulator-max-microvolt = <5000000>;
+			regulator-boot-on;
+			regulator-always-on;
+			enable-active-high;
+			gpio = <&pmic 0 GPIO_ACTIVE_HIGH>;
+		};
+
+		emmc_3v3_reg: regulator at 3 {
+			compatible = "regulator-fixed";
+			reg = <3>;
+			regulator-name = "emmc_3v3";
+			regulator-min-microvolt = <3300000>;
+			regulator-max-microvolt = <3300000>;
+			regulator-always-on;
+			regulator-boot-on;
+			enable-active-high;
+			gpio = <&gpio TEGRA_GPIO(D, 1) GPIO_ACTIVE_HIGH>;
+			vin-supply = <&sys_3v3_reg>;
+		};
+
+		modem_3v3_reg: regulator at 4 {
+			compatible = "regulator-fixed";
+			reg = <4>;
+			regulator-name = "modem_3v3";
+			regulator-min-microvolt = <3300000>;
+			regulator-max-microvolt = <3300000>;
+			enable-active-high;
+			gpio = <&gpio TEGRA_GPIO(D, 6) GPIO_ACTIVE_HIGH>;
+		};
+
+		pex_hvdd_3v3_reg: regulator at 5 {
+			compatible = "regulator-fixed";
+			reg = <5>;
+			regulator-name = "pex_hvdd_3v3";
+			regulator-min-microvolt = <3300000>;
+			regulator-max-microvolt = <3300000>;
+			enable-active-high;
+			gpio = <&gpio TEGRA_GPIO(L, 7) GPIO_ACTIVE_HIGH>;
+			vin-supply = <&sys_3v3_reg>;
+		};
+
+		vdd_cam1_ldo_reg: regulator at 6 {
+			compatible = "regulator-fixed";
+			reg = <6>;
+			regulator-name = "vdd_cam1_ldo";
+			regulator-min-microvolt = <2800000>;
+			regulator-max-microvolt = <2800000>;
+			enable-active-high;
+			gpio = <&gpio TEGRA_GPIO(R, 6) GPIO_ACTIVE_HIGH>;
+			vin-supply = <&sys_3v3_reg>;
+		};
+
+		vdd_cam2_ldo_reg: regulator at 7 {
+			compatible = "regulator-fixed";
+			reg = <7>;
+			regulator-name = "vdd_cam2_ldo";
+			regulator-min-microvolt = <2800000>;
+			regulator-max-microvolt = <2800000>;
+			enable-active-high;
+			gpio = <&gpio TEGRA_GPIO(R, 7) GPIO_ACTIVE_HIGH>;
+			vin-supply = <&sys_3v3_reg>;
+		};
+
+		vdd_cam3_ldo_reg: regulator at 8 {
+			compatible = "regulator-fixed";
+			reg = <8>;
+			regulator-name = "vdd_cam3_ldo";
+			regulator-min-microvolt = <3300000>;
+			regulator-max-microvolt = <3300000>;
+			enable-active-high;
+			gpio = <&gpio TEGRA_GPIO(S, 0) GPIO_ACTIVE_HIGH>;
+			vin-supply = <&sys_3v3_reg>;
+		};
+
+		vdd_com_reg: regulator at 9 {
+			compatible = "regulator-fixed";
+			reg = <9>;
+			regulator-name = "vdd_com";
+			regulator-min-microvolt = <3300000>;
+			regulator-max-microvolt = <3300000>;
+			regulator-always-on;
+			regulator-boot-on;
+			enable-active-high;
+			gpio = <&gpio TEGRA_GPIO(D, 0) GPIO_ACTIVE_HIGH>;
+			vin-supply = <&sys_3v3_reg>;
+		};
+
+		vdd_fuse_3v3_reg: regulator at 10 {
+			compatible = "regulator-fixed";
+			reg = <10>;
+			regulator-name = "vdd_fuse_3v3";
+			regulator-min-microvolt = <3300000>;
+			regulator-max-microvolt = <3300000>;
+			enable-active-high;
+			gpio = <&gpio TEGRA_GPIO(L, 6) GPIO_ACTIVE_HIGH>;
+			vin-supply = <&sys_3v3_reg>;
+		};
+
+		vdd_pnl1_reg: regulator at 11 {
+			compatible = "regulator-fixed";
+			reg = <11>;
+			regulator-name = "vdd_pnl1";
+			regulator-min-microvolt = <3300000>;
+			regulator-max-microvolt = <3300000>;
+			regulator-always-on;
+			regulator-boot-on;
+			enable-active-high;
+			gpio = <&gpio TEGRA_GPIO(L, 4) GPIO_ACTIVE_HIGH>;
+			vin-supply = <&sys_3v3_reg>;
+		};
+
+		vdd_vid_reg: regulator at 12 {
+			compatible = "regulator-fixed";
+			reg = <12>;
+			regulator-name = "vddio_vid";
+			regulator-min-microvolt = <5000000>;
+			regulator-max-microvolt = <5000000>;
+			enable-active-high;
+			gpio = <&gpio TEGRA_GPIO(T, 0) GPIO_ACTIVE_HIGH>;
+			gpio-open-drain;
+			vin-supply = <&vdd_5v0_reg>;
+		};
+
+		ddr_reg: regulator at 100 {
+			compatible = "regulator-fixed";
+			regulator-name = "ddr";
+			reg = <100>;
+			regulator-min-microvolt = <1500000>;
+			regulator-max-microvolt = <1500000>;
+			regulator-always-on;
+			regulator-boot-on;
+			enable-active-high;
+			gpio = <&pmic 7 GPIO_ACTIVE_HIGH>;
+		};
+
+		sys_3v3_reg: regulator at 101 {
+			compatible = "regulator-fixed";
+			reg = <101>;
+			regulator-name = "sys_3v3";
+			regulator-min-microvolt = <3300000>;
+			regulator-max-microvolt = <3300000>;
+			regulator-always-on;
+			regulator-boot-on;
+			enable-active-high;
+			gpio = <&pmic 6 GPIO_ACTIVE_HIGH>;
+		};
+
+		usb1_vbus_reg: regulator at 102 {
+			compatible = "regulator-fixed";
+			reg = <102>;
+			regulator-name = "usb1_vbus";
+			regulator-min-microvolt = <5000000>;
+			regulator-max-microvolt = <5000000>;
+			enable-active-high;
+			gpio = <&gpio TEGRA_GPIO(DD, 6) GPIO_ACTIVE_HIGH>;
+			gpio-open-drain;
+			vin-supply = <&vdd_5v0_reg>;
+		};
+
+		usb3_vbus_reg: regulator at 103 {
+			compatible = "regulator-fixed";
+			reg = <103>;
+			regulator-name = "usb3_vbus";
+			regulator-min-microvolt = <5000000>;
+			regulator-max-microvolt = <5000000>;
+			enable-active-high;
+			gpio = <&gpio TEGRA_GPIO(DD, 4) GPIO_ACTIVE_HIGH>;
+			gpio-open-drain;
+			vin-supply = <&vdd_5v0_reg>;
+		};
+
+		vdd_5v0_reg: regulator at 104 {
+			compatible = "regulator-fixed";
+			reg = <104>;
+			regulator-name = "5v0";
+			regulator-min-microvolt = <5000000>;
+			regulator-max-microvolt = <5000000>;
+			enable-active-high;
+			gpio = <&pmic 8 GPIO_ACTIVE_HIGH>;
+		};
+
+		vdd_bl_reg: regulator at 105 {
+			compatible = "regulator-fixed";
+			reg = <105>;
+			regulator-name = "vdd_bl";
+			regulator-min-microvolt = <5000000>;
+			regulator-max-microvolt = <5000000>;
+			regulator-always-on;
+			regulator-boot-on;
+			enable-active-high;
+			gpio = <&gpio TEGRA_GPIO(DD, 2) GPIO_ACTIVE_HIGH>;
+		};
+
+		vdd_bl2_reg: regulator at 106 {
+			compatible = "regulator-fixed";
+			reg = <106>;
+			regulator-name = "vdd_bl2";
+			regulator-min-microvolt = <5000000>;
+			regulator-max-microvolt = <5000000>;
+			regulator-always-on;
+			regulator-boot-on;
+			enable-active-high;
+			gpio = <&gpio TEGRA_GPIO(DD, 0) GPIO_ACTIVE_HIGH>;
+		};
+	};
 };
board/nvidia/cardhu/cardhu.c +56 -0

67 lines not on this page · raw message

include/configs/cardhu.h +10 -0
index 59f429cf5784..f5f4a860f6a9 100644
@@ -88,6 +88,16 @@
 #define CONFIG_USB_HOST_ETHER
 #define CONFIG_USB_ETHER_ASIX
 
+/* PCI host support */
+#define CONFIG_PCI
+#define CONFIG_PCI_TEGRA
+#define CONFIG_PCI_PNP
+#define CONFIG_CMD_PCI
+#define CONFIG_CMD_PCI_ENUM
+
+/* PCI networking support */
+#define CONFIG_RTL8169
+
 /* General networking support */
 #define CONFIG_CMD_NET
 #define CONFIG_CMD_DHCP
Signature · 1 line
2.0.4
#66 lore raw

PATCH v2 28/40 ARM: tegra: Enable PCIe on Beaver

In reply to Thierry Reding

From: Thierry Reding <[email protected]>

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

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

---
Changes in v2:
- move after Cardhu PCIe patch and move most code into that patch
- use proper set of PCIe power supplies
- use unit address in node name

 arch/arm/dts/tegra30-beaver.dts | 245 ++++++++++++++++++++++++++++++++++++++++
 include/configs/beaver.h        |  10 ++
 2 files changed, 255 insertions(+)
arch/arm/dts/tegra30-beaver.dts +245 -0
index 85e62e9db32e..4a4c07851202 100644
@@ -23,6 +23,33 @@
 		reg = <0x80000000 0x7ff00000>;
 	};
 
+	pcie-controller at 00003000 {
+		status = "okay";
+
+		avdd-pexa-supply = <&ldo1_reg>;
+		vdd-pexa-supply = <&ldo1_reg>;
+		avdd-pexb-supply = <&ldo1_reg>;
+		vdd-pexb-supply = <&ldo1_reg>;
+		avdd-pex-pll-supply = <&ldo1_reg>;
+		avdd-plle-supply = <&ldo1_reg>;
+		vddio-pex-ctl-supply = <&sys_3v3_reg>;
+		hvdd-pex-supply = <&sys_3v3_pexs_reg>;
+
+		pci at 1,0 {
+			status = "okay";
+			nvidia,num-lanes = <2>;
+		};
+
+		pci at 2,0 {
+			nvidia,num-lanes = <2>;
+		};
+
+		pci at 3,0 {
+			status = "okay";
+			nvidia,num-lanes = <2>;
+		};
+	};
+
 	i2c at 7000c000 {
 		status = "okay";
 		clock-frequency = <100000>;
@@ -46,6 +73,110 @@
 	i2c at 7000d000 {
 		status = "okay";
 		clock-frequency = <100000>;
+
+		pmic: tps65911 at 2d {
+			compatible = "ti,tps65911";
+			reg = <0x2d>;
+
+			interrupts = <GIC_SPI 86 IRQ_TYPE_LEVEL_HIGH>;
+			#interrupt-cells = <2>;
+			interrupt-controller;
+
+			ti,system-power-controller;
+
+			#gpio-cells = <2>;
+			gpio-controller;
+
+			vcc1-supply = <&vdd_5v_in_reg>;
+			vcc2-supply = <&vdd_5v_in_reg>;
+			vcc3-supply = <&vio_reg>;
+			vcc4-supply = <&vdd_5v_in_reg>;
+			vcc5-supply = <&vdd_5v_in_reg>;
+			vcc6-supply = <&vdd2_reg>;
+			vcc7-supply = <&vdd_5v_in_reg>;
+			vccio-supply = <&vdd_5v_in_reg>;
+
+			regulators {
+				#address-cells = <1>;
+				#size-cells = <0>;
+
+				vdd1_reg: vdd1 {
+					regulator-name = "vddio_ddr_1v2";
+					regulator-min-microvolt = <1200000>;
+					regulator-max-microvolt = <1200000>;
+					regulator-always-on;
+				};
+
+				vdd2_reg: vdd2 {
+					regulator-name = "vdd_1v5_gen";
+					regulator-min-microvolt = <1500000>;
+					regulator-max-microvolt = <1500000>;
+					regulator-always-on;
+				};
+
+				vddctrl_reg: vddctrl {
+					regulator-name = "vdd_cpu,vdd_sys";
+					regulator-min-microvolt = <1000000>;
+					regulator-max-microvolt = <1000000>;
+					regulator-always-on;
+				};
+
+				vio_reg: vio {
+					regulator-name = "vdd_1v8_gen";
+					regulator-min-microvolt = <1800000>;
+					regulator-max-microvolt = <1800000>;
+					regulator-always-on;
+				};
+
+				ldo1_reg: ldo1 {
+					regulator-name = "vdd_pexa,vdd_pexb";
+					regulator-min-microvolt = <1050000>;
+					regulator-max-microvolt = <1050000>;
+				};
+
+				ldo2_reg: ldo2 {
+					regulator-name = "vdd_sata,avdd_plle";
+					regulator-min-microvolt = <1050000>;
+					regulator-max-microvolt = <1050000>;
+				};
+
+				/* LDO3 is not connected to anything */
+
+				ldo4_reg: ldo4 {
+					regulator-name = "vdd_rtc";
+					regulator-min-microvolt = <1200000>;
+					regulator-max-microvolt = <1200000>;
+					regulator-always-on;
+				};
+
+				ldo5_reg: ldo5 {
+					regulator-name = "vddio_sdmmc,avdd_vdac";
+					regulator-min-microvolt = <3300000>;
+					regulator-max-microvolt = <3300000>;
+					regulator-always-on;
+				};
+
+				ldo6_reg: ldo6 {
+					regulator-name = "avdd_dsi_csi,pwrdet_mipi";
+					regulator-min-microvolt = <1200000>;
+					regulator-max-microvolt = <1200000>;
+				};
+
+				ldo7_reg: ldo7 {
+					regulator-name = "vdd_pllm,x,u,a_p_c_s";
+					regulator-min-microvolt = <1200000>;
+					regulator-max-microvolt = <1200000>;
+					regulator-always-on;
+				};
+
+				ldo8_reg: ldo8 {
+					regulator-name = "vdd_ddr_hs";
+					regulator-min-microvolt = <1000000>;
+					regulator-max-microvolt = <1000000>;
+					regulator-always-on;
+				};
+			};
+		};
 	};
 
 	spi at 7000da00 {
@@ -81,4 +212,118 @@
 		nvidia,vbus-gpio = <&gpio 236 0>; /* PDD4 */
 		status = "okay";
 	};
+
+	regulators {
+		compatible = "simple-bus";
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		vdd_5v_in_reg: regulator at 0 {
+			compatible = "regulator-fixed";
+			reg = <0>;
+			regulator-name = "vdd_5v_in";
+			regulator-min-microvolt = <5000000>;
+			regulator-max-microvolt = <5000000>;
+			regulator-always-on;
+		};
+
+		chargepump_5v_reg: regulator at 1 {
+			compatible = "regulator-fixed";
+			reg = <1>;
+			regulator-name = "chargepump_5v";
+			regulator-min-microvolt = <5000000>;
+			regulator-max-microvolt = <5000000>;
+			regulator-boot-on;
+			regulator-always-on;
+			enable-active-high;
+			gpio = <&pmic 0 GPIO_ACTIVE_HIGH>;
+		};
+
+		ddr_reg: regulator at 2 {
+			compatible = "regulator-fixed";
+			reg = <2>;
+			regulator-name = "vdd_ddr";
+			regulator-min-microvolt = <1500000>;
+			regulator-max-microvolt = <1500000>;
+			regulator-always-on;
+			regulator-boot-on;
+			enable-active-high;
+			gpio = <&pmic 7 GPIO_ACTIVE_HIGH>;
+			vin-supply = <&vdd_5v_in_reg>;
+		};
+
+		vdd_5v_sata_reg: regulator at 3 {
+			compatible = "regulator-fixed";
+			reg = <3>;
+			regulator-name = "vdd_5v_sata";
+			regulator-min-microvolt = <5000000>;
+			regulator-max-microvolt = <5000000>;
+			regulator-always-on;
+			regulator-boot-on;
+			enable-active-high;
+			gpio = <&gpio TEGRA_GPIO(D, 6) GPIO_ACTIVE_HIGH>;
+			vin-supply = <&vdd_5v_in_reg>;
+		};
+
+		usb1_vbus_reg: regulator at 4 {
+			compatible = "regulator-fixed";
+			reg = <4>;
+			regulator-name = "usb1_vbus";
+			regulator-min-microvolt = <5000000>;
+			regulator-max-microvolt = <5000000>;
+			enable-active-high;
+			gpio = <&gpio TEGRA_GPIO(DD, 6) GPIO_ACTIVE_HIGH>;
+			gpio-open-drain;
+			vin-supply = <&vdd_5v_in_reg>;
+		};
+
+		usb3_vbus_reg: regulator at 5 {
+			compatible = "regulator-fixed";
+			reg = <5>;
+			regulator-name = "usb3_vbus";
+			regulator-min-microvolt = <5000000>;
+			regulator-max-microvolt = <5000000>;
+			enable-active-high;
+			gpio = <&gpio TEGRA_GPIO(DD, 4) GPIO_ACTIVE_HIGH>;
+			gpio-open-drain;
+			vin-supply = <&vdd_5v_in_reg>;
+		};
+
+		sys_3v3_reg: regulator at 6 {
+			compatible = "regulator-fixed";
+			reg = <6>;
+			regulator-name = "sys_3v3,vdd_3v3_alw";
+			regulator-min-microvolt = <3300000>;
+			regulator-max-microvolt = <3300000>;
+			regulator-always-on;
+			regulator-boot-on;
+			enable-active-high;
+			gpio = <&pmic 6 GPIO_ACTIVE_HIGH>;
+			vin-supply = <&vdd_5v_in_reg>;
+		};
+
+		sys_3v3_pexs_reg: regulator at 7 {
+			compatible = "regulator-fixed";
+			reg = <7>;
+			regulator-name = "sys_3v3_pexs";
+			regulator-min-microvolt = <3300000>;
+			regulator-max-microvolt = <3300000>;
+			regulator-always-on;
+			regulator-boot-on;
+			enable-active-high;
+			gpio = <&gpio TEGRA_GPIO(L, 7) GPIO_ACTIVE_HIGH>;
+			vin-supply = <&sys_3v3_reg>;
+		};
+
+		vdd_5v0_hdmi: regulator at 8 {
+			compatible = "regulator-fixed";
+			reg = <8>;
+			regulator-name = "+VDD_5V_HDMI";
+			regulator-min-microvolt = <5000000>;
+			regulator-max-microvolt = <5000000>;
+			regulator-always-on;
+			regulator-boot-on;
+			vin-supply = <&sys_3v3_reg>;
+		};
+	};
 };
include/configs/beaver.h +10 -0
index ae831127985f..bc96f6438d3c 100644
@@ -84,6 +84,16 @@
 #define CONFIG_USB_HOST_ETHER
 #define CONFIG_USB_ETHER_ASIX
 
+/* PCI host support */
+#define CONFIG_PCI
+#define CONFIG_PCI_TEGRA
+#define CONFIG_PCI_PNP
+#define CONFIG_CMD_PCI
+#define CONFIG_CMD_PCI_ENUM
+
+/* PCI networking support */
+#define CONFIG_RTL8169
+
 /* General networking support */
 #define CONFIG_CMD_NET
 #define CONFIG_CMD_DHCP
Signature · 1 line
2.0.4
#67 lore raw

PATCH v2 29/40 ARM: tegra: Add GIC for Tegra124

In reply to Thierry Reding

From: Thierry Reding <[email protected]>

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

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

PATCH v2 30/40 ARM: tegra: Add Tegra124 PCIe device tree node

In reply to Thierry Reding

From: Thierry Reding <[email protected]>

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

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

341 lines not on this page · raw message

Signature · 1 line
2.0.4
#69 lore raw

PATCH v2 31/40 ARM: tegra: Enable PCIe on Jetson TK1

In reply to Thierry Reding

From: Thierry Reding <[email protected]>

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

---
Changes in v2:
- move AS3722 PMIC code into separate driver
- use revised list of supplies in DTS

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

65 lines not on this page · raw message

include/configs/jetson-tk1.h +13 -0
index 0b9e5b699fa6..255f0f0a823e 100644
@@ -10,6 +10,9 @@
 
 #include <linux/sizes.h>
 
+/* enable PMIC */
+#define CONFIG_AS3722_POWER
+
 #include "tegra124-common.h"
 
 /* Enable fdt support for Jetson TK1. Flash the image in u-boot-dtb.bin */
@@ -71,6 +74,16 @@
 #define CONFIG_USB_HOST_ETHER
 #define CONFIG_USB_ETHER_ASIX
 
+/* PCI host support */
+#define CONFIG_PCI
+#define CONFIG_PCI_TEGRA
+#define CONFIG_PCI_PNP
+#define CONFIG_CMD_PCI
+#define CONFIG_CMD_PCI_ENUM
+
+/* PCI networking support */
+#define CONFIG_RTL8169
+
 /* General networking support */
 #define CONFIG_CMD_NET
 #define CONFIG_CMD_DHCP
Signature · 1 line
2.0.4
#70 lore raw

PATCH v2 32/40 ARM: cache_v7: Various minor cleanups

In reply to Thierry Reding

From: Thierry Reding <[email protected]>

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.

---
 arch/arm/cpu/armv7/cache_v7.c | 14 +++++++-------
 1 file changed, 7 insertions(+), 7 deletions(-)
arch/arm/cpu/armv7/cache_v7.c +7 -7
index a2c4032fed8c..0f9d8377ed5a 100644
@@ -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);
Signature · 1 line
2.0.4
#71 lore raw

PATCH v2 32/40 ARM: cache_v7: Various minor cleanups

Quoted 9 lines · Thierry Reding

From: Thierry Reding <[email protected]>

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.

#72 lore raw

PATCH v2 32/40 ARM: cache_v7: Various minor cleanups

In reply to Thierry Reding

Hello Thierry,

Quoted 76 lines · Thierry Reding

From: Thierry Reding <[email protected]>

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.

---
 arch/arm/cpu/armv7/cache_v7.c | 14 +++++++-------
 1 file changed, 7 insertions(+), 7 deletions(-)
arch/arm/cpu/armv7/cache_v7.c +7 -7
index a2c4032fed8c..0f9d8377ed5a 100644
@@ -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);
Signature · 1 line
2.0.4

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

Amicalement,

Signature · 1 line
Albert.
#73 lore raw

PATCH v2 33/40 ARM: cache-cp15: Use more accurate types

In reply to Thierry Reding

From: Thierry Reding <[email protected]>

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.

---
 arch/arm/include/asm/system.h | 2 +-
 arch/arm/lib/cache-cp15.c     | 6 +++---
 2 files changed, 4 insertions(+), 4 deletions(-)
arch/arm/include/asm/system.h +1 -1
index d51ba668f323..fb31a8faf2b1 100644
@@ -200,7 +200,7 @@ enum {
  * \param size		size of memory region to change
  * \param option	dcache option to select
  */
-void mmu_set_region_dcache_behaviour(u32 start, int size,
+void mmu_set_region_dcache_behaviour(phys_addr_t start, size_t size,
 				     enum dcache_option option);
 
 /**
arch/arm/lib/cache-cp15.c +3 -3
index 5fdfdbfca541..e6c1c83e5758 100644
@@ -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);
Signature · 1 line
2.0.4
#74 lore raw

PATCH v2 33/40 ARM: cache-cp15: Use more accurate types

Hi Thierry,

Quoted 39 lines · Thierry Reding

From: Thierry Reding <[email protected]>

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.

---
 arch/arm/include/asm/system.h | 2 +-
 arch/arm/lib/cache-cp15.c     | 6 +++---
 2 files changed, 4 insertions(+), 4 deletions(-)
arch/arm/include/asm/system.h +1 -1
index d51ba668f323..fb31a8faf2b1 100644
@@ -200,7 +200,7 @@ enum {
  * \param size         size of memory region to change
  * \param option       dcache option to select
  */
-void mmu_set_region_dcache_behaviour(u32 start, int size,
+void mmu_set_region_dcache_behaviour(phys_addr_t start, size_t size,
                                     enum dcache_option option);
 
 /**
arch/arm/lib/cache-cp15.c +1 -1
index 5fdfdbfca541..e6c1c83e5758 100644
@@ -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,

arch/arm/lib/cache-cp15.c __weak void mmu_page_table_flush(unsigned long start, unsigned long stop) · line 58

Quoted 10 lines
arch/arm/lib/cache-cp15.c +2 -2
                                     enum dcache_option option)
 {
        u32 *page_table = (u32 *)gd->arch.tlb_addr;
-       u32 upto, end;
+       unsigned long upto, end;
 
        end = ALIGN(start + size, MMU_SECTION_SIZE) >> MMU_SECTION_SHIFT;
        start = start >> MMU_SECTION_SHIFT;
-       debug("%s: start=%x, size=%x, option=%d\n", __func__, start, size,
+       debug("%s: start=%pa, size=%zu, option=%d\n", __func__, &start, size,

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

Quoted 6 lines
arch/arm/lib/cache-cp15.c +0 -1
              option);
        for (upto = start; upto < end; upto++)
                set_section_dcache(upto, option);
--

2.0.4

Regards,
Simon

#75 lore raw

PATCH v2 33/40 ARM: cache-cp15: Use more accurate types

In reply to Thierry Reding

Hello Thierry,

Quoted 55 lines · Thierry Reding

From: Thierry Reding <[email protected]>

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.

---
 arch/arm/include/asm/system.h | 2 +-
 arch/arm/lib/cache-cp15.c     | 6 +++---
 2 files changed, 4 insertions(+), 4 deletions(-)
arch/arm/include/asm/system.h +1 -1
index d51ba668f323..fb31a8faf2b1 100644
@@ -200,7 +200,7 @@ enum {
  * \param size		size of memory region to change
  * \param option	dcache option to select
  */
-void mmu_set_region_dcache_behaviour(u32 start, int size,
+void mmu_set_region_dcache_behaviour(phys_addr_t start, size_t size,
 				     enum dcache_option option);
 
 /**
arch/arm/lib/cache-cp15.c +3 -3
index 5fdfdbfca541..e6c1c83e5758 100644
@@ -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);
Signature · 1 line
2.0.4

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

Amicalement,

Signature · 1 line
Albert.
#76 lore raw

PATCH v2 34/40 malloc: Output region when debugging

In reply to Thierry Reding

From: Thierry Reding <[email protected]>

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

---
 common/dlmalloc.c | 3 +++
 1 file changed, 3 insertions(+)
common/dlmalloc.c +3 -0
index f9873393c183..3d6391e60acf 100644
@@ -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();
Signature · 1 line
2.0.4
#77 lore raw

PATCH v2 34/40 malloc: Output region when debugging

Quoted 14 lines · Thierry Reding

From: Thierry Reding <[email protected]>

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

---
 common/dlmalloc.c | 3 +++
 1 file changed, 3 insertions(+)
common/dlmalloc.c +0 -0
index f9873393c183..3d6391e60acf 100644

common/dlmalloc.c void mem_malloc_init(ulong start, ulong size) · line 1537

Quoted 5 lines
common/dlmalloc.c +2 -0
@@ -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);
Quoted 7 lines
common/dlmalloc.c +1 -1
+
        memset((void *)mem_malloc_start, 0, size);
 
        malloc_bin_reloc();
--

2.0.4

#78 lore raw

PATCH v2 34/40 malloc: Output region when debugging

In reply to Thierry Reding

Hello Thierry,

Quoted 26 lines · Thierry Reding

From: Thierry Reding <[email protected]>

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

---
 common/dlmalloc.c | 3 +++
 1 file changed, 3 insertions(+)
common/dlmalloc.c +3 -0
index f9873393c183..3d6391e60acf 100644
@@ -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();
Signature · 1 line
2.0.4

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

Amicalement,

Signature · 1 line
Albert.
#79 lore raw

PATCH v2 35/40 ARM: Implement non-cached memory support

In reply to Thierry Reding

From: Thierry Reding <[email protected]>

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.

---
Changes in v2:
- avoid overflow when checking for available space

 README                        | 19 +++++++++++++++++++
 arch/arm/include/asm/system.h |  5 +++++
 arch/arm/lib/cache.c          | 42 ++++++++++++++++++++++++++++++++++++++++++
 common/board_r.c              | 11 +++++++++++
 4 files changed, 77 insertions(+)
README +19 -0
index 1d713596ec6f..526e06edb52c 100644
@@ -3759,6 +3759,25 @@ Configuration Settings:
 		Pre-relocation malloc() is only supported on ARM at present
 		but is fairly easy to enable for other archs.
 
+- CONFIG_SYS_NONCACHED_MEMORY:
+		Size of non-cached memory area. This area of memory will be
+		typically located right below the malloc() area and mapped
+		uncached in the MMU. This is useful for drivers that would
+		otherwise require a lot of explicit cache maintenance. For
+		some drivers it's also impossible to properly maintain the
+		cache. For example if the regions that need to be flushed
+		are not a multiple of the cache-line size, *and* padding
+		cannot be allocated between the regions to align them (i.e.
+		if the HW requires a contiguous array of regions, and the
+		size of each region is not cache-aligned), then a flush of
+		one region may result in overwriting data that hardware has
+		written to another region in the same cache-line. This can
+		happen for example in network drivers where descriptors for
+		buffers are typically smaller than the CPU cache-line (e.g.
+		16 bytes vs. 32 or 64 bytes).
+
+		Non-cached memory is only supported on 32-bit ARM at present.
+
 - CONFIG_SYS_BOOTM_LEN:
 		Normally compressed uImages are limited to an
 		uncompressed size of 8 MBytes. If this is not enough,
arch/arm/include/asm/system.h +5 -0
index fb31a8faf2b1..fb1bc0699a56 100644
@@ -211,6 +211,11 @@ void mmu_set_region_dcache_behaviour(phys_addr_t start, size_t size,
  */
 void mmu_page_table_flush(unsigned long start, unsigned long stop);
 
+#ifdef CONFIG_SYS_NONCACHED_MEMORY
+void noncached_init(void);
+phys_addr_t noncached_alloc(size_t size, size_t align);
+#endif /* CONFIG_SYS_NONCACHED_MEMORY */
+
 #endif /* __ASSEMBLY__ */
 
 #define arch_align_stack(x) (x)
arch/arm/lib/cache.c +42 -0

51 lines not on this page · raw message

common/board_r.c +11 -0
index ba9a68dc6691..6b8e62bf032b 100644
@@ -270,6 +270,14 @@ static int initr_malloc(void)
 	return 0;
 }
 
+#ifdef CONFIG_SYS_NONCACHED_MEMORY
+static int initr_noncached(void)
+{
+	noncached_init();
+	return 0;
+}
+#endif
+
 #ifdef CONFIG_DM
 static int initr_dm(void)
 {
@@ -765,6 +773,9 @@ init_fnc_t init_sequence_r[] = {
 #endif
 	initr_barrier,
 	initr_malloc,
+#ifdef CONFIG_SYS_NONCACHED_MEMORY
+	initr_noncached,
+#endif
 	bootstage_relocate,
 #ifdef CONFIG_DM
 	initr_dm,
Signature · 1 line
2.0.4
#80 lore raw

PATCH v2 35/40 ARM: Implement non-cached memory support

Hi Thierry,

Quoted 45 lines · Thierry Reding

From: Thierry Reding <[email protected]>

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.

---
Changes in v2:
- avoid overflow when checking for available space

 README                        | 19 +++++++++++++++++++
 arch/arm/include/asm/system.h |  5 +++++
 arch/arm/lib/cache.c          | 42 ++++++++++++++++++++++++++++++++++++++++++
 common/board_r.c              | 11 +++++++++++
 4 files changed, 77 insertions(+)
README +8 -0
index 1d713596ec6f..526e06edb52c 100644
@@ -3759,6 +3759,25 @@ Configuration Settings:
                Pre-relocation malloc() is only supported on ARM at present
                but is fairly easy to enable for other archs.
 
+- CONFIG_SYS_NONCACHED_MEMORY:
+               Size of non-cached memory area. This area of memory will be
+               typically located right below the malloc() area and mapped
+               uncached in the MMU. This is useful for drivers that would
+               otherwise require a lot of explicit cache maintenance. For
+               some drivers it's also impossible to properly maintain the
+               cache. For example if the regions that need to be flushed
+               are not a multiple of the cache-line size, *and* padding

README Configuration Settings: · line 3779

Quoted 10 lines
README +10 -0
+               cannot be allocated between the regions to align them (i.e.
+               if the HW requires a contiguous array of regions, and the
+               size of each region is not cache-aligned), then a flush of
+               one region may result in overwriting data that hardware has
+               written to another region in the same cache-line. This can
+               happen for example in network drivers where descriptors for
+               buffers are typically smaller than the CPU cache-line (e.g.
+               16 bytes vs. 32 or 64 bytes).
+
+               Non-cached memory is only supported on 32-bit ARM at present.

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

Quoted 33 lines
README +1 -0
+
 - CONFIG_SYS_BOOTM_LEN:
                Normally compressed uImages are limited to an
                uncompressed size of 8 MBytes. If this is not enough,
arch/arm/include/asm/system.h +5 -0
index fb31a8faf2b1..fb1bc0699a56 100644
@@ -211,6 +211,11 @@ void mmu_set_region_dcache_behaviour(phys_addr_t start, size_t size,
  */
 void mmu_page_table_flush(unsigned long start, unsigned long stop);
 
+#ifdef CONFIG_SYS_NONCACHED_MEMORY
+void noncached_init(void);
+phys_addr_t noncached_alloc(size_t size, size_t align);
+#endif /* CONFIG_SYS_NONCACHED_MEMORY */
+
 #endif /* __ASSEMBLY__ */
 
 #define arch_align_stack(x) (x)
arch/arm/lib/cache.c +1 -0
index 4e597a4c1d16..b2aa7740d4f8 100644
@@ -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)
 {

arch/arm/lib/cache.c __weak void enable_caches(void) · line 57

Quoted 8 lines
arch/arm/lib/cache.c +5 -0
@@ -49,3 +50,44 @@ __weak void enable_caches(void)
 {
        puts("WARNING: Caches not enabled\n");
 }
+
+#ifdef CONFIG_SYS_NONCACHED_MEMORY
+/*
+ * Reserve one MMU section worth of address space below the malloc() area that
+ * will be mapped uncached.

It looks like it can be >1 section.

arch/arm/lib/cache.c __weak void enable_caches(void) · line 61

Quoted 4 lines
arch/arm/lib/cache.c +4 -0
+ */
+static unsigned long noncached_start;
+static unsigned long noncached_end;
+static unsigned long noncached_next;

You can use ulong if you like.

Quoted 18 lines
arch/arm/lib/cache.c +18 -0
+
+void noncached_init(void)
+{
+       phys_addr_t start, end;
+       size_t size;
+
+       end = ALIGN(mem_malloc_start, MMU_SECTION_SIZE) - MMU_SECTION_SIZE;
+       size = ALIGN(CONFIG_SYS_NONCACHED_MEMORY, MMU_SECTION_SIZE);
+       start = end - size;
+
+       debug("mapping memory %pa-%pa non-cached\n", &start, &end);
+
+       noncached_start = start;
+       noncached_end = end;
+       noncached_next = start;
+
+       mmu_set_region_dcache_behaviour(noncached_start, size, DCACHE_OFF);
+}

arch/arm/lib/cache.c __weak void enable_caches(void) · line 89

Quoted 10 lines
arch/arm/lib/cache.c +10 -0
+
+phys_addr_t noncached_alloc(size_t size, size_t align)
+{
+       phys_addr_t next = ALIGN(noncached_next, align);
+
+       if (next >= noncached_end || (noncached_end - next) < size)
+               return 0;
+
+       debug("allocated %zu bytes of uncached memory @%pa\n", size, &next);
+       noncached_next = next + size;

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

Quoted 9 lines
arch/arm/lib/cache.c +4 -0
+
+       return next;
+}
+#endif /* CONFIG_SYS_NONCACHED_MEMORY */
common/board_r.c +0 -0
index ba9a68dc6691..6b8e62bf032b 100644

common/board_r.c static int initr_malloc(void) · line 276

Quoted 7 lines
common/board_r.c +4 -0
@@ -270,6 +270,14 @@ static int initr_malloc(void)
        return 0;
 }
 
+#ifdef CONFIG_SYS_NONCACHED_MEMORY
+static int initr_noncached(void)
+{
+       noncached_init();

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

Quoted 18 lines
common/board_r.c +7 -1
+       return 0;
+}
+#endif
+
 #ifdef CONFIG_DM
 static int initr_dm(void)
 {
@@ -765,6 +773,9 @@ init_fnc_t init_sequence_r[] = {
 #endif
        initr_barrier,
        initr_malloc,
+#ifdef CONFIG_SYS_NONCACHED_MEMORY
+       initr_noncached,
+#endif
        bootstage_relocate,
 #ifdef CONFIG_DM
        initr_dm,
--
Quoted 2 lines

2.0.4

Regards,
Simon

#81 lore raw

PATCH v2 35/40 ARM: Implement non-cached memory support

In reply to Thierry Reding
Quoted 21 lines · Thierry Reding

From: Thierry Reding <[email protected]>

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.

arch/arm/lib/cache.c +1 -0
 
+void noncached_init(void)

...

arch/arm/lib/cache.c

Quoted 2 lines
arch/arm/lib/cache.c +2 -0
+	mmu_set_region_dcache_behaviour(noncached_start, size, DCACHE_OFF);
+}

If I build with:

#define CONFIG_SYS_DCACHE_OFF
#define CONFIG_SYS_ICACHE_OFF

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

#82 lore raw

PATCH v2 35/40 ARM: Implement non-cached memory support

Hi Stephen,

Quoted 33 lines · Stephen Warren
Quoted 24 lines · Thierry Reding

From: Thierry Reding <[email protected]>

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.

arch/arm/lib/cache.c +1 -0
 
 
+void noncached_init(void)

...

Quoted 4 lines

+ mmu_set_region_dcache_behaviour(noncached_start, size,
DCACHE_OFF);
+}

Quoted 7 lines

If I build with:

#define CONFIG_SYS_DCACHE_OFF
#define CONFIG_SYS_ICACHE_OFF

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

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

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

Regards
Simon

#83 lore raw

PATCH v2 36/40 ARM: tegra: Enable non-cached memory

In reply to Thierry Reding

From: Thierry Reding <[email protected]>

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.

---
 include/configs/tegra-common.h | 1 +
 1 file changed, 1 insertion(+)
include/configs/tegra-common.h +1 -0
index 717cd61bd69a..16f45f5def9b 100644
@@ -41,6 +41,7 @@
  * Size of malloc() pool
  */
 #define CONFIG_SYS_MALLOC_LEN		(4 << 20)	/* 4MB  */
+#define CONFIG_SYS_NONCACHED_MEMORY	(1 << 20)	/* 1 MiB */
 
 /*
  * NS16550 Configuration
Signature · 1 line
2.0.4
#84 lore raw

PATCH v2 37/40 net: rtl8169: Honor CONFIG_SYS_RX_ETH_BUFFER

In reply to Thierry Reding

From: Thierry Reding <[email protected]>

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.

---
 drivers/net/rtl8169.c | 6 +++++-
 1 file changed, 5 insertions(+), 1 deletion(-)
drivers/net/rtl8169.c +5 -1
index d040ab171bf5..c3eb474f0fba 100644
@@ -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
 
Signature · 1 line
2.0.4
#85 lore raw

PATCH v2 38/40 net: rtl8169: Properly align buffers

In reply to Thierry Reding

From: Thierry Reding <[email protected]>

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.

---
Changes in v2:
- make cache-line vs. descriptor size a compile-time warning

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

PATCH v2 38/40 net: rtl8169: Properly align buffers

Hi,

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

2014-08-27 0:34 GMT+09:00 Thierry Reding <[email protected]>:

Quoted 8 lines

From: Thierry Reding <[email protected]>

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.

Quoted 8 lines

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.

---
Changes in v2:
- make cache-line vs. descriptor size a compile-time warning

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

2.0.4

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

Signature · 1 line
Nobuhiro Iwamatsu
#87 lore raw

PATCH v2 39/40 net: rtl8169: Use non-cached memory if available

In reply to Thierry Reding

From: Thierry Reding <[email protected]>

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.

---
Changes in v2:
- if non-cached memory is not available, use memalign() for more consistent descriptor allocations
- allow rtl_init() to fail

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

PATCH v2 40/40 net: rtl8169: Add support for RTL-8168/8111g

In reply to Thierry Reding

From: Thierry Reding <[email protected]>

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

---
 drivers/net/rtl8169.c | 1 +
 1 file changed, 1 insertion(+)
drivers/net/rtl8169.c +1 -0
index 22ad70719937..8183df39e77a 100644
@@ -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,},
 };
Signature · 1 line
2.0.4
#89 lore raw

v2 cover ARM: tegra: Add PCIe support

In reply to Thierry Reding

Hi Thierry,

Quoted 1 line · Thierry Reding

From: Thierry Reding <[email protected]>

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

Amicalement,

Signature · 1 line
Albert.
#90 lore raw

v2 cover ARM: tegra: Add PCIe support

Quoted 11 lines · Albert ARIBAUD

Hi Thierry,

Quoted 1 line · Thierry Reding

From: Thierry Reding <[email protected]>

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

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

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

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

#91 lore raw

v2 cover ARM: tegra: Add PCIe support

Hi,

Quoted 16 lines · Stephen Warren
Quoted 6 lines · Albert ARIBAUD

Hi Thierry,

On Tue, 26 Aug 2014 17:33:48 +0200, Thierry Reding <[email protected]> wrote:

Quoted 7 lines
Quoted 1 line

From: Thierry Reding <[email protected]>

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

Quoted 4 lines

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

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

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

Quoted 2 lines

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

Regards,
Simon

#92 lore raw

v2 cover ARM: tegra: Add PCIe support

Hi Simon,

Quoted 19 lines · Simon Glass

Hi,

Quoted 16 lines · Stephen Warren
Quoted 13 lines · Albert ARIBAUD

Hi Thierry,

Quoted 1 line · Thierry Reding

From: Thierry Reding <[email protected]>

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

Quoted 7 lines
Quoted 4 lines

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

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

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

Well, the idea was applying it all in one place :) and I don't like the idea of pulling the fdt tree into the arm tree, so I'll pick them up, but please give your Acked-by to them, so that PW sees it and puts it in when I apply the patches.

Quoted 4 lines
Quoted 1 line

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

Regards,
Simon

Amicalement,

Signature · 1 line
Albert.
#93 lore raw

v2 cover ARM: tegra: Add PCIe support

HI Albert,

Quoted 31 lines · Albert ARIBAUD

Hi Simon,

Quoted 3 lines · Simon Glass

Hi,

On 11 September 2014 10:17, Stephen Warren <[email protected]>

Quoted 11 lines · wrote:
Quoted 11 lines · Albert ARIBAUD
Quoted 10 lines

Hi Thierry,

Quoted 1 line · Thierry Reding

From: Thierry Reding <[email protected]>

Note: this series was split over several custodians (including

myself).

Quoted 10 lines
Quoted 9 lines
Quoted 3 lines

It might thus get applied piecewise... Shouldn't it rather be assigned a single custodian -with others giving their Ack) and be applied as a whole? And yes, I'm ok with getting all the pieces.

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

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

Quoted 8 lines
Quoted 2 lines

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

Well, the idea was applying it all in one place :) and I don't like the idea of pulling the fdt tree into the arm tree, so I'll pick them up, but please give your Acked-by to them, so that PW sees it and puts it in when I apply the patches.

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

Regards,
Simon

#94 lore raw

v2 cover ARM: tegra: Add PCIe support

In reply to Albert ARIBAUD

Hi,

Quoted 11 lines · Albert ARIBAUD

Hi Thierry,

Quoted 1 line · Thierry Reding

From: Thierry Reding <[email protected]>

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

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

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

Regards,
Simon

#95 lore raw

v2 cover ARM: tegra: Add PCIe support

Quoted 15 lines · Simon Glass

Hi,

Quoted 11 lines · Albert ARIBAUD

Hi Thierry,

Quoted 1 line · Thierry Reding

From: Thierry Reding <[email protected]>

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

Quoted 6 lines

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

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

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

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

#96 lore raw

v2 cover ARM: tegra: Add PCIe support

Hi Thierry,

Quoted 20 lines · Thierry Reding
Quoted 19 lines · Simon Glass

Hi,

Quoted 11 lines · Albert ARIBAUD

Hi Thierry,

Quoted 1 line · Thierry Reding

From: Thierry Reding <[email protected]>

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

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

Quoted 6 lines
Quoted 2 lines

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

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

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

Let me know what you think.

Regards,
Simon

#97 lore raw

v2 cover ARM: tegra: Add PCIe support

In reply to Thierry Reding

Hi Thierry,

Quoted 16 lines · Thierry Reding

From: Thierry Reding <[email protected]>

This series adds PCIe support for Tegra20, Tegra30 and Tegra124. The size is
mostly due to the large number of infrastructure that's added (libfdt, Tegra
specific drivers required by the PCIe driver). In this version I've included
all patches that were previously split into three separate series. Spreading
them over multiple series is probably not worth it since there might be some
dependencies between them and only the end result gives a completely working
setup.

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

Are you going to respin it?

Regards,
Simon

#98 lore raw

v2 cover ARM: tegra: Add PCIe support

Quoted 21 lines · Simon Glass

Hi Thierry,

Quoted 16 lines · Thierry Reding

From: Thierry Reding <[email protected]>

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

Quoted 6 lines

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

Are you going to respin it?

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

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

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

#99 lore raw

v2 cover ARM: tegra: Add PCIe support

Hi Thierry,

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

Hi Thierry,

On 26 August 2014 09:33, Thierry Reding <[email protected]>

Quoted 4 lines · wrote:
Quoted 4 lines

From: Thierry Reding <[email protected]>

This series adds PCIe support for Tegra20, Tegra30 and Tegra124. The

size

Quoted 19 lines
Quoted 4 lines

is
mostly due to the large number of infrastructure that's added (libfdt, Tegra
specific drivers required by the PCIe driver). In this version I've

Quoted 9 lines

included
all patches that were previously split into three separate series. Spreading
them over multiple series is probably not worth it since there might be some
dependencies between them and only the end result gives a completely working
setup.

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

Quoted 6 lines
Quoted 1 line

Are you going to respin it?

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

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

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

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

Quoted 4 lines

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

Yes I think that would be useful.

Regards,
Simon

#100 lore raw

v2 cover ARM: tegra: Add PCIe support

In reply to Thierry Reding

Hello Thierry,

Am 29.09.2014 10:11, schrieb Thierry Reding:

Quoted 29 lines · Simon Glass
Quoted 21 lines

Hi Thierry,

Quoted 16 lines · Thierry Reding

From: Thierry Reding<[email protected]>

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

Quoted 6 lines

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

Are you going to respin it?

Quoted 7 lines

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

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

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

bye,
Heiko

Signature · 2 lines
DENX Software Engineering GmbH,     MD: Wolfgang Denk & Detlev Zundel
HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
#101 lore raw

v2 cover ARM: tegra: Add PCIe support

In reply to Thierry Reding

Le Tue, 26 Aug 2014 17:33:48 +0200,
Thierry Reding <[email protected]> a ?crit :

Quoted 178 lines

From: Thierry Reding <[email protected]>

This series adds PCIe support for Tegra20, Tegra30 and Tegra124. The size is mostly due to the large number of infrastructure that's added (libfdt, Tegra specific drivers required by the PCIe driver). In this version I've included all patches that were previously split into three separate series. Spreading them over multiple series is probably not worth it since there might be some dependencies between them and only the end result gives a completely working setup.

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

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

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

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

Patches 11-14 are some cleanup and refactoring of I2C core code, the addition of a higher level API that makes it easier for I2C client drivers to talk to devices. The Tegra I2C driver now implements i2c_get_bus_num_fdt() to obtain bus numbers corresponding to a DT node.

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

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

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

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

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

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

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

Thierry Reding (40):
vsprintf: Add modifier for phys_addr_t
fdt: Add a function to count strings
fdt: Add a function to get the index of a string
fdt: Add functions to retrieve strings
fdt: Add resource parsing functions
fdt: Add a function to return PCI BDF triplet
fdt: Add a subnodes iterator macro
pci: Abort early if bus does not exist
pci: Honour pci_skip_dev()
Add pr_fmt() macro
i2c: Initialize the correct bus
i2c: Refactor adapter initialization
i2c: Add high-level API
i2c: tegra: Implement i2c_get_bus_num_fdt()
power: Add AMS AS3722 PMIC support
ARM: tegra: Implement tegra_plle_enable()
ARM: tegra: Provide PCIEXCLK reset ID
ARM: tegra: Implement powergate support
ARM: tegra: Implement XUSB pad controller
ARM: tegra: Add XUSB pad controller on Tegra124
ARM: tegra: Enable XUSB pad controller on Jetson TK1
pci: tegra: Add Tegra PCIe driver
ARM: tegra: Add Tegra20 PCIe device tree node
ARM: tegra: Enable PCIe on TrimSlice
ARM: tegra: Add GIC for Tegra30
ARM: tegra: Add Tegra30 PCIe device tree node
ARM: tegra: Enable PCIe on Cardhu
ARM: tegra: Enable PCIe on Beaver
ARM: tegra: Add GIC for Tegra124
ARM: tegra: Add Tegra124 PCIe device tree node
ARM: tegra: Enable PCIe on Jetson TK1
ARM: cache_v7: Various minor cleanups
ARM: cache-cp15: Use more accurate types
malloc: Output region when debugging
ARM: Implement non-cached memory support
ARM: tegra: Enable non-cached memory
net: rtl8169: Honor CONFIG_SYS_RX_ETH_BUFFER
net: rtl8169: Properly align buffers
net: rtl8169: Use non-cached memory if available
net: rtl8169: Add support for RTL-8168/8111g

 README                                           |   19 +
 arch/arm/cpu/armv7/cache_v7.c                    |   14 +-
 arch/arm/cpu/tegra-common/Makefile               |    2 +
 arch/arm/cpu/tegra-common/powergate.c            |  102 ++
 arch/arm/cpu/tegra-common/xusb-padctl.c          |   39 +
 arch/arm/cpu/tegra124-common/Makefile            |    1 +
 arch/arm/cpu/tegra124-common/clock.c             |  109 +++
 arch/arm/cpu/tegra124-common/xusb-padctl.c       |  716
++++++++++++++ arch/arm/cpu/tegra20-common/clock.c              |
141 ++- arch/arm/cpu/tegra30-common/clock.c              |  155 +++
 arch/arm/dts/tegra124-jetson-tk1.dts             |  373 +++++++
 arch/arm/dts/tegra124.dtsi                       |   90 ++
 arch/arm/dts/tegra20-trimslice.dts               |   69 ++
 arch/arm/dts/tegra20.dtsi                        |   60 ++
 arch/arm/dts/tegra30-beaver.dts                  |  245 +++++
 arch/arm/dts/tegra30-cardhu.dts                  |  362 +++++++
 arch/arm/dts/tegra30.dtsi                        |   84 ++
 arch/arm/include/asm/arch-tegra/powergate.h      |   38 +
 arch/arm/include/asm/arch-tegra/xusb-padctl.h    |   24 +
 arch/arm/include/asm/arch-tegra114/powergate.h   |    6 +
 arch/arm/include/asm/arch-tegra124/clock.h       |    2 +
 arch/arm/include/asm/arch-tegra124/powergate.h   |    6 +
 arch/arm/include/asm/arch-tegra20/clock-tables.h |    2 +-
 arch/arm/include/asm/arch-tegra20/clock.h        |    2 +
 arch/arm/include/asm/arch-tegra20/powergate.h    |    6 +
 arch/arm/include/asm/arch-tegra30/clock.h        |    2 +
 arch/arm/include/asm/arch-tegra30/powergate.h    |    6 +
 arch/arm/include/asm/system.h                    |    7 +-
 arch/arm/lib/cache-cp15.c                        |    6 +-
 arch/arm/lib/cache.c                             |   42 +
 board/compulab/trimslice/trimslice.c             |    8 +
 board/nvidia/cardhu/cardhu.c                     |   56 ++
 board/nvidia/common/board.c                      |    3 +
 board/nvidia/jetson-tk1/jetson-tk1.c             |   52 +
 common/board_r.c                                 |   11 +
 common/cmd_pci.c                                 |    7 +
 common/dlmalloc.c                                |    3 +
 drivers/i2c/i2c_core.c                           |   80 +-
 drivers/i2c/tegra_i2c.c                          |   13 +
 drivers/net/rtl8169.c                            |  127 ++-
 drivers/pci/Makefile                             |    1 +
 drivers/pci/pci.c                                |    3 +
 drivers/pci/pci_tegra.c                          | 1143
++++++++++++++++++++++
drivers/power/Makefile                           |    1 +
drivers/power/as3722.c                           |  300 ++++++
include/common.h                                 |   14 +-
include/configs/beaver.h                         |   10 +
include/configs/cardhu.h                         |   10 +
include/configs/jetson-tk1.h                     |   13 +
include/configs/tegra-common.h                   |    1 +
include/configs/trimslice.h                      |   10 +
include/dt-bindings/clock/tegra124-car.h         |  341 +++++++
include/dt-bindings/clock/tegra20-car.h          |  158 +++
include/dt-bindings/clock/tegra30-car.h          |  265 +++++
include/dt-bindings/pinctrl/pinctrl-tegra-xusb.h |    7 +
include/fdtdec.h                                 |   69 ++
include/i2c.h                                    |   96 ++
include/libfdt.h                                 |   72 ++
include/pci.h                                    |    1 +
include/power/as3722.h                           |   27 +
lib/fdtdec.c                                     |   76 ++
lib/libfdt/fdt_ro.c                              |   76 ++
lib/vsprintf.c                                   |   16 +- 63 files

changed, 5736 insertions(+), 64 deletions(-) create mode 100644 arch/arm/cpu/tegra-common/powergate.c create mode 100644 arch/arm/cpu/tegra-common/xusb-padctl.c create mode 100644 arch/arm/cpu/tegra124-common/xusb-padctl.c create mode 100644 arch/arm/include/asm/arch-tegra/powergate.h create mode 100644 arch/arm/include/asm/arch-tegra/xusb-padctl.h create mode 100644 arch/arm/include/asm/arch-tegra114/powergate.h create mode 100644 arch/arm/include/asm/arch-tegra124/powergate.h create mode 100644 arch/arm/include/asm/arch-tegra20/powergate.h create mode 100644 arch/arm/include/asm/arch-tegra30/powergate.h create mode 100644 drivers/pci/pci_tegra.c create mode 100644 drivers/power/as3722.c

Quoted 5 lines
 create mode 100644 include/dt-bindings/clock/tegra124-car.h
 create mode 100644 include/dt-bindings/clock/tegra20-car.h
 create mode 100644 include/dt-bindings/clock/tegra30-car.h
 create mode 100644 include/dt-bindings/pinctrl/pinctrl-tegra-xusb.h
 create mode 100644 include/power/as3722.h

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

Amicalement,

Signature · 1 line
Albert.
#102 lore raw

v2 cover ARM: tegra: Add PCIe support

On Sun, 26 Oct 2014 20:07:10 +0100,
Albert ARIBAUD <[email protected]> a ?crit :

Quoted 2 lines

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

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

Amicalement,

Signature · 1 line
Albert.
#103 lore raw

v2 cover ARM: tegra: Add PCIe support

In reply to Albert ARIBAUD

Hi Albert,

Quoted 187 lines · Albert ARIBAUD

Le Tue, 26 Aug 2014 17:33:48 +0200,
Thierry Reding <[email protected]> a ?crit :

Quoted 178 lines

From: Thierry Reding <[email protected]>

This series adds PCIe support for Tegra20, Tegra30 and Tegra124. The size is mostly due to the large number of infrastructure that's added (libfdt, Tegra specific drivers required by the PCIe driver). In this version I've included all patches that were previously split into three separate series. Spreading them over multiple series is probably not worth it since there might be some dependencies between them and only the end result gives a completely working setup.

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

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

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

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

Patches 11-14 are some cleanup and refactoring of I2C core code, the addition of a higher level API that makes it easier for I2C client drivers to talk to devices. The Tegra I2C driver now implements i2c_get_bus_num_fdt() to obtain bus numbers corresponding to a DT node.

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

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

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

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

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

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

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

Thierry Reding (40):
vsprintf: Add modifier for phys_addr_t
fdt: Add a function to count strings
fdt: Add a function to get the index of a string
fdt: Add functions to retrieve strings
fdt: Add resource parsing functions
fdt: Add a function to return PCI BDF triplet
fdt: Add a subnodes iterator macro
pci: Abort early if bus does not exist
pci: Honour pci_skip_dev()
Add pr_fmt() macro
i2c: Initialize the correct bus
i2c: Refactor adapter initialization
i2c: Add high-level API
i2c: tegra: Implement i2c_get_bus_num_fdt()
power: Add AMS AS3722 PMIC support
ARM: tegra: Implement tegra_plle_enable()
ARM: tegra: Provide PCIEXCLK reset ID
ARM: tegra: Implement powergate support
ARM: tegra: Implement XUSB pad controller
ARM: tegra: Add XUSB pad controller on Tegra124
ARM: tegra: Enable XUSB pad controller on Jetson TK1
pci: tegra: Add Tegra PCIe driver
ARM: tegra: Add Tegra20 PCIe device tree node
ARM: tegra: Enable PCIe on TrimSlice
ARM: tegra: Add GIC for Tegra30
ARM: tegra: Add Tegra30 PCIe device tree node
ARM: tegra: Enable PCIe on Cardhu
ARM: tegra: Enable PCIe on Beaver
ARM: tegra: Add GIC for Tegra124
ARM: tegra: Add Tegra124 PCIe device tree node
ARM: tegra: Enable PCIe on Jetson TK1
ARM: cache_v7: Various minor cleanups
ARM: cache-cp15: Use more accurate types
malloc: Output region when debugging
ARM: Implement non-cached memory support
ARM: tegra: Enable non-cached memory
net: rtl8169: Honor CONFIG_SYS_RX_ETH_BUFFER
net: rtl8169: Properly align buffers
net: rtl8169: Use non-cached memory if available
net: rtl8169: Add support for RTL-8168/8111g

 README                                           |   19 +
 arch/arm/cpu/armv7/cache_v7.c                    |   14 +-
 arch/arm/cpu/tegra-common/Makefile               |    2 +
 arch/arm/cpu/tegra-common/powergate.c            |  102 ++
 arch/arm/cpu/tegra-common/xusb-padctl.c          |   39 +
 arch/arm/cpu/tegra124-common/Makefile            |    1 +
 arch/arm/cpu/tegra124-common/clock.c             |  109 +++
 arch/arm/cpu/tegra124-common/xusb-padctl.c       |  716
++++++++++++++ arch/arm/cpu/tegra20-common/clock.c              |
141 ++- arch/arm/cpu/tegra30-common/clock.c              |  155 +++
 arch/arm/dts/tegra124-jetson-tk1.dts             |  373 +++++++
 arch/arm/dts/tegra124.dtsi                       |   90 ++
 arch/arm/dts/tegra20-trimslice.dts               |   69 ++
 arch/arm/dts/tegra20.dtsi                        |   60 ++
 arch/arm/dts/tegra30-beaver.dts                  |  245 +++++
 arch/arm/dts/tegra30-cardhu.dts                  |  362 +++++++
 arch/arm/dts/tegra30.dtsi                        |   84 ++
 arch/arm/include/asm/arch-tegra/powergate.h      |   38 +
 arch/arm/include/asm/arch-tegra/xusb-padctl.h    |   24 +
 arch/arm/include/asm/arch-tegra114/powergate.h   |    6 +
 arch/arm/include/asm/arch-tegra124/clock.h       |    2 +
 arch/arm/include/asm/arch-tegra124/powergate.h   |    6 +
 arch/arm/include/asm/arch-tegra20/clock-tables.h |    2 +-
 arch/arm/include/asm/arch-tegra20/clock.h        |    2 +
 arch/arm/include/asm/arch-tegra20/powergate.h    |    6 +
 arch/arm/include/asm/arch-tegra30/clock.h        |    2 +
 arch/arm/include/asm/arch-tegra30/powergate.h    |    6 +
 arch/arm/include/asm/system.h                    |    7 +-
 arch/arm/lib/cache-cp15.c                        |    6 +-
 arch/arm/lib/cache.c                             |   42 +
 board/compulab/trimslice/trimslice.c             |    8 +
 board/nvidia/cardhu/cardhu.c                     |   56 ++
 board/nvidia/common/board.c                      |    3 +
 board/nvidia/jetson-tk1/jetson-tk1.c             |   52 +
 common/board_r.c                                 |   11 +
 common/cmd_pci.c                                 |    7 +
 common/dlmalloc.c                                |    3 +
 drivers/i2c/i2c_core.c                           |   80 +-
 drivers/i2c/tegra_i2c.c                          |   13 +
 drivers/net/rtl8169.c                            |  127 ++-
 drivers/pci/Makefile                             |    1 +
 drivers/pci/pci.c                                |    3 +
 drivers/pci/pci_tegra.c                          | 1143
++++++++++++++++++++++
drivers/power/Makefile                           |    1 +
drivers/power/as3722.c                           |  300 ++++++
include/common.h                                 |   14 +-
include/configs/beaver.h                         |   10 +
include/configs/cardhu.h                         |   10 +
include/configs/jetson-tk1.h                     |   13 +
include/configs/tegra-common.h                   |    1 +
include/configs/trimslice.h                      |   10 +
include/dt-bindings/clock/tegra124-car.h         |  341 +++++++
include/dt-bindings/clock/tegra20-car.h          |  158 +++
include/dt-bindings/clock/tegra30-car.h          |  265 +++++
include/dt-bindings/pinctrl/pinctrl-tegra-xusb.h |    7 +
include/fdtdec.h                                 |   69 ++
include/i2c.h                                    |   96 ++
include/libfdt.h                                 |   72 ++
include/pci.h                                    |    1 +
include/power/as3722.h                           |   27 +
lib/fdtdec.c                                     |   76 ++
lib/libfdt/fdt_ro.c                              |   76 ++
lib/vsprintf.c                                   |   16 +- 63 files

changed, 5736 insertions(+), 64 deletions(-) create mode 100644 arch/arm/cpu/tegra-common/powergate.c create mode 100644 arch/arm/cpu/tegra-common/xusb-padctl.c create mode 100644 arch/arm/cpu/tegra124-common/xusb-padctl.c create mode 100644 arch/arm/include/asm/arch-tegra/powergate.h create mode 100644 arch/arm/include/asm/arch-tegra/xusb-padctl.h create mode 100644 arch/arm/include/asm/arch-tegra114/powergate.h create mode 100644 arch/arm/include/asm/arch-tegra124/powergate.h create mode 100644 arch/arm/include/asm/arch-tegra20/powergate.h create mode 100644 arch/arm/include/asm/arch-tegra30/powergate.h create mode 100644 drivers/pci/pci_tegra.c create mode 100644 drivers/power/as3722.c

Quoted 5 lines
 create mode 100644 include/dt-bindings/clock/tegra124-car.h
 create mode 100644 include/dt-bindings/clock/tegra20-car.h
 create mode 100644 include/dt-bindings/clock/tegra30-car.h
 create mode 100644 include/dt-bindings/pinctrl/pinctrl-tegra-xusb.h
 create mode 100644 include/power/as3722.h
Quoted 5 lines

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

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

Regards,
Simon