[U-Boot] [PATCH 00/26] dm: tegra: Move nyan-big to livetree

This moves an entire board to use a live device tree as an example of the impact.
Nyan-big was chosen because I can easily and boot U-Boot without any media swapping, etc.
Total code size impact on this board is approximately 9KB on U-Boot and 64 bytes on SPL:
27: dm: tegra: nyan-big: Move to livetree arm: (for 1/1 boards) all +9264.0 bss -16.0 data +44.0 rodata +92.0 spl/u-boot-spl:all +326.0 spl/u-boot-spl:rodata +262.0 spl/u-boot-spl:text +64.0 text +9144.0
Tegra does not use Thumb2, which would likely reduce the code size by about 25%, indicating a code-size impact of perhaps 7KB.
I have not yet collected reliable detailed timing information. I will do that with the next version of this series, after comments are received. I expect that building the live tree will take a little time, and that using it will be very slightly faster.
The use of livetree is controlled by a the CONFIG_OF_LIVE option. When enabled, U-Boot builds a livetree immediately after relocation and uses it from then on.
This series is available at u-boot-dm/livet-working
(note that some work remains for apalis-tk1, jetson-tk1, cei-tk1-som)
Simon Glass (26): dm: video: Sync display on backspace dm: video: Update pwm_backlight to support livetree video: simple-panel: Add a little more debugging tegra: Fix up include file ordering tegra: spl: Enable debug UART tegra: nyan: Add a PMC syscon driver dm: tegra: Convert USB setup to livetree dm: tegra: Convert clock_decode_periph_id() to support livetree dm: video: tegra124: Convert to livetree tegra: dts: Move stdout-path to /chosen tegra: Don't set up the UART clocks again in U-Boot dm: tegra: gpio: Convert to support livetree dm: tegra: usb: Convert to livetree dm: tegra: spi: Convert to livetree dm: tegra: i2c: Convert to livetree dm: tegra: pwm: Convert to livetree dm: tegra: mmc: Convert to livetree power: Add a regulator driver for the as3722 PMIC power: Add a GPIO driver for the as3722 PMIC dm: power: Convert as3722 to driver model dm: serial: ns16550: Convert to livetree dm: serial: Separate out the core serial-device finding code dm: serial: Add livetree support tegra: Show a debug message if the LCD PMIC fails to start fdtdec: Drop old compatible values dm: tegra: nyan-big: Move to livetree
arch/arm/dts/tegra124-nyan-big.dts | 5 +- arch/arm/include/asm/arch-tegra/clock.h | 2 +- arch/arm/include/asm/arch-tegra/tegra.h | 5 + arch/arm/include/asm/arch-tegra/xusb-padctl.h | 2 +- arch/arm/mach-tegra/board.c | 2 + arch/arm/mach-tegra/board2.c | 34 ++- arch/arm/mach-tegra/clock.c | 9 +- arch/arm/mach-tegra/spl.c | 4 + arch/arm/mach-tegra/tegra124/Makefile | 1 + arch/arm/mach-tegra/tegra124/pmc.c | 19 ++ arch/arm/mach-tegra/tegra124/xusb-padctl.c | 36 +++- arch/arm/mach-tegra/tegra210/xusb-padctl.c | 40 +++- arch/arm/mach-tegra/xusb-padctl-common.c | 84 ++++---- arch/arm/mach-tegra/xusb-padctl-common.h | 11 +- arch/arm/mach-tegra/xusb-padctl-dummy.c | 2 +- board/nvidia/nyan-big/nyan-big.c | 22 +- configs/nyan-big_defconfig | 4 + drivers/gpio/tegra_gpio.c | 10 +- drivers/i2c/tegra_i2c.c | 6 +- drivers/mmc/tegra_mmc.c | 17 +- drivers/power/pmic/Makefile | 2 +- drivers/power/pmic/as3722.c | 292 +++++++++----------------- drivers/power/pmic/as3722_gpio.c | 120 +++++++++++ drivers/power/regulator/Kconfig | 9 + drivers/power/regulator/Makefile | 1 + drivers/power/regulator/as3722_regulator.c | 149 +++++++++++++ drivers/pwm/tegra_pwm.c | 2 +- drivers/serial/ns16550.c | 15 +- drivers/serial/serial-uclass.c | 92 ++++---- drivers/spi/tegra114_spi.c | 15 +- drivers/spi/tegra20_sflash.c | 2 +- drivers/spi/tegra20_slink.c | 2 +- drivers/spi/tegra210_qspi.c | 2 +- drivers/usb/host/ehci-tegra.c | 36 ++-- drivers/video/pwm_backlight.c | 23 +- drivers/video/simple_panel.c | 2 + drivers/video/tegra124/display.c | 8 +- drivers/video/tegra124/dp.c | 3 +- drivers/video/tegra124/sor.c | 25 +-- drivers/video/vidconsole-uclass.c | 1 + include/fdtdec.h | 6 - include/power/as3722.h | 27 ++- lib/fdtdec.c | 6 - 43 files changed, 699 insertions(+), 456 deletions(-) create mode 100644 arch/arm/mach-tegra/tegra124/pmc.c create mode 100644 drivers/power/pmic/as3722_gpio.c create mode 100644 drivers/power/regulator/as3722_regulator.c

We should sync the display (e.g. flush cache) when backspace is pressed to ensure that the character is erased correctly.
Signed-off-by: Simon Glass sjg@chromium.org ---
drivers/video/vidconsole-uclass.c | 1 + 1 file changed, 1 insertion(+)
diff --git a/drivers/video/vidconsole-uclass.c b/drivers/video/vidconsole-uclass.c index e9a90b1b9b..b5afd72227 100644 --- a/drivers/video/vidconsole-uclass.c +++ b/drivers/video/vidconsole-uclass.c @@ -77,6 +77,7 @@ static int vidconsole_back(struct udevice *dev) if (priv->ycur < 0) priv->ycur = 0; } + video_sync(dev->parent);
return 0; }

On Fri, 19 May 2017 08:30:44 -0600 Simon Glass sjg@chromium.org wrote:
We should sync the display (e.g. flush cache) when backspace is pressed to ensure that the character is erased correctly.
Signed-off-by: Simon Glass sjg@chromium.org
drivers/video/vidconsole-uclass.c | 1 + 1 file changed, 1 insertion(+)
Acked-by: Anatolij Gustschin agust@denx.de

Update this driver to support a live device tree.
Signed-off-by: Simon Glass sjg@chromium.org ---
drivers/video/pwm_backlight.c | 23 +++++++++++++---------- 1 file changed, 13 insertions(+), 10 deletions(-)
diff --git a/drivers/video/pwm_backlight.c b/drivers/video/pwm_backlight.c index 3697f4905c..359f8fa186 100644 --- a/drivers/video/pwm_backlight.c +++ b/drivers/video/pwm_backlight.c @@ -28,11 +28,13 @@ struct pwm_backlight_priv { static int pwm_backlight_enable(struct udevice *dev) { struct pwm_backlight_priv *priv = dev_get_priv(dev); + struct dm_regulator_uclass_platdata *plat; uint duty_cycle; int ret;
- debug("%s: Enable '%s', regulator '%s'\n", __func__, dev->name, - priv->reg->name); + plat = dev_get_uclass_platdata(priv->reg); + debug("%s: Enable '%s', regulator '%s'/'%s'\n", __func__, dev->name, + priv->reg->name, plat->name); ret = regulator_set_enable(priv->reg, true); if (ret) { debug("%s: Cannot enable regulator for PWM '%s'\n", __func__, @@ -59,12 +61,11 @@ static int pwm_backlight_enable(struct udevice *dev) static int pwm_backlight_ofdata_to_platdata(struct udevice *dev) { struct pwm_backlight_priv *priv = dev_get_priv(dev); - struct fdtdec_phandle_args args; - const void *blob = gd->fdt_blob; - int node = dev_of_offset(dev); + struct ofnode_phandle_args args; int index, ret, count, len; const u32 *cell;
+ debug("%s: start\n", __func__); ret = uclass_get_device_by_phandle(UCLASS_REGULATOR, dev, "power-supply", &priv->reg); if (ret) { @@ -79,14 +80,15 @@ static int pwm_backlight_ofdata_to_platdata(struct udevice *dev) if (ret != -ENOENT) return ret; } - ret = fdtdec_parse_phandle_with_args(blob, node, "pwms", "#pwm-cells", - 0, 0, &args); + ret = dev_read_phandle_with_args(dev, "pwms", "#pwm-cells", 0, 0, + &args); if (ret) { debug("%s: Cannot get PWM phandle: ret=%d\n", __func__, ret); return ret; }
- ret = uclass_get_device_by_of_offset(UCLASS_PWM, args.node, &priv->pwm); + ret = uclass_get_device_by_ofnode(UCLASS_PWM, args.node, + &priv->pwm); if (ret) { debug("%s: Cannot get PWM: ret=%d\n", __func__, ret); return ret; @@ -94,8 +96,8 @@ static int pwm_backlight_ofdata_to_platdata(struct udevice *dev) priv->channel = args.args[0]; priv->period_ns = args.args[1];
- index = fdtdec_get_int(blob, node, "default-brightness-level", 255); - cell = fdt_getprop(blob, node, "brightness-levels", &len); + index = dev_read_u32_default(dev, "default-brightness-level", 255); + cell = dev_read_prop(dev, "brightness-levels", &len); count = len / sizeof(u32); if (cell && count > index) { priv->default_level = fdt32_to_cpu(cell[index]); @@ -104,6 +106,7 @@ static int pwm_backlight_ofdata_to_platdata(struct udevice *dev) priv->default_level = index; priv->max_level = 255; } + debug("%s: done\n", __func__);
return 0;

On Fri, 19 May 2017 08:30:45 -0600 Simon Glass sjg@chromium.org wrote:
Update this driver to support a live device tree.
Signed-off-by: Simon Glass sjg@chromium.org
drivers/video/pwm_backlight.c | 23 +++++++++++++---------- 1 file changed, 13 insertions(+), 10 deletions(-)
Acked-by: Anatolij Gustschin agust@denx.de

Add some debugging to show when the backlight is enabled.
Signed-off-by: Simon Glass sjg@chromium.org ---
drivers/video/simple_panel.c | 2 ++ 1 file changed, 2 insertions(+)
diff --git a/drivers/video/simple_panel.c b/drivers/video/simple_panel.c index baa95f6a12..c0ce199c6a 100644 --- a/drivers/video/simple_panel.c +++ b/drivers/video/simple_panel.c @@ -25,8 +25,10 @@ static int simple_panel_enable_backlight(struct udevice *dev) struct simple_panel_priv *priv = dev_get_priv(dev); int ret;
+ debug("%s: start, backlight = '%s'\n", __func__, priv->backlight->name); dm_gpio_set_value(&priv->enable, 1); ret = backlight_enable(priv->backlight); + debug("%s: done, ret = %d\n", __func__, ret); if (ret) return ret;

On Fri, 19 May 2017 08:30:46 -0600 Simon Glass sjg@chromium.org wrote:
Add some debugging to show when the backlight is enabled.
Signed-off-by: Simon Glass sjg@chromium.org
drivers/video/simple_panel.c | 2 ++ 1 file changed, 2 insertions(+)
Acked-by: Anatolij Gustschin agust@denx.de

Update these two files so include files in the right order.
Signed-off-by: Simon Glass sjg@chromium.org ---
arch/arm/mach-tegra/board2.c | 22 ++++++++-------------- arch/arm/mach-tegra/clock.c | 4 ++-- 2 files changed, 10 insertions(+), 16 deletions(-)
diff --git a/arch/arm/mach-tegra/board2.c b/arch/arm/mach-tegra/board2.c index 84f1ee5035..943ee24e59 100644 --- a/arch/arm/mach-tegra/board2.c +++ b/arch/arm/mach-tegra/board2.c @@ -9,14 +9,8 @@ #include <dm.h> #include <errno.h> #include <ns16550.h> -#include <linux/compiler.h> -#include <linux/sizes.h> +#include <usb.h> #include <asm/io.h> -#include <asm/arch/clock.h> -#include <asm/arch/funcmux.h> -#include <asm/arch/pinmux.h> -#include <asm/arch/pmu.h> -#include <asm/arch/tegra.h> #include <asm/arch-tegra/ap.h> #include <asm/arch-tegra/board.h> #include <asm/arch-tegra/clk_rst.h> @@ -25,17 +19,17 @@ #include <asm/arch-tegra/uart.h> #include <asm/arch-tegra/warmboot.h> #include <asm/arch-tegra/gpu.h> +#include <asm/arch-tegra/usb.h> +#include <asm/arch-tegra/xusb-padctl.h> +#include <asm/arch/clock.h> +#include <asm/arch/funcmux.h> +#include <asm/arch/pinmux.h> +#include <asm/arch/pmu.h> +#include <asm/arch/tegra.h> #ifdef CONFIG_TEGRA_CLOCK_SCALING #include <asm/arch/emc.h> #endif -#include <asm/arch-tegra/usb.h> -#ifdef CONFIG_USB_EHCI_TEGRA -#include <usb.h> -#endif -#include <asm/arch-tegra/xusb-padctl.h> #include <power/as3722.h> -#include <i2c.h> -#include <spi.h> #include "emc.h"
DECLARE_GLOBAL_DATA_PTR; diff --git a/arch/arm/mach-tegra/clock.c b/arch/arm/mach-tegra/clock.c index 3bb72331a4..f547942022 100644 --- a/arch/arm/mach-tegra/clock.c +++ b/arch/arm/mach-tegra/clock.c @@ -7,6 +7,8 @@ /* Tegra SoC common clock control functions */
#include <common.h> +#include <div64.h> +#include <dm.h> #include <errno.h> #include <asm/io.h> #include <asm/arch/clock.h> @@ -15,8 +17,6 @@ #include <asm/arch-tegra/clk_rst.h> #include <asm/arch-tegra/pmc.h> #include <asm/arch-tegra/timer.h> -#include <div64.h> -#include <fdtdec.h>
/* * This is our record of the current clock rate of each clock. We don't

Enable the debug UART in SPL to allow early serial output even if the standard UART does not work (e.g. due to driver model problem).
Signed-off-by: Simon Glass sjg@chromium.org ---
arch/arm/mach-tegra/spl.c | 4 ++++ 1 file changed, 4 insertions(+)
diff --git a/arch/arm/mach-tegra/spl.c b/arch/arm/mach-tegra/spl.c index 41c88cb2b4..189b3da026 100644 --- a/arch/arm/mach-tegra/spl.c +++ b/arch/arm/mach-tegra/spl.c @@ -7,6 +7,7 @@ * SPDX-License-Identifier: GPL-2.0+ */ #include <common.h> +#include <debug_uart.h> #include <spl.h>
#include <asm/io.h> @@ -32,6 +33,9 @@ void spl_board_init(void) gpio_early_init_uart();
clock_early_init(); +#ifdef CONFIG_DEBUG_UART + debug_uart_init(); +#endif preloader_console_init(); }

The PMC can be modelled as a syscon peripheral. Add a driver for this so that it can be accessed by drivers when needed.
Signed-off-by: Simon Glass sjg@chromium.org ---
arch/arm/include/asm/arch-tegra/tegra.h | 5 +++++ arch/arm/mach-tegra/tegra124/Makefile | 1 + arch/arm/mach-tegra/tegra124/pmc.c | 19 +++++++++++++++++++ configs/nyan-big_defconfig | 2 ++ 4 files changed, 27 insertions(+) create mode 100644 arch/arm/mach-tegra/tegra124/pmc.c
diff --git a/arch/arm/include/asm/arch-tegra/tegra.h b/arch/arm/include/asm/arch-tegra/tegra.h index 3add1b3c09..3b9711d28e 100644 --- a/arch/arm/include/asm/arch-tegra/tegra.h +++ b/arch/arm/include/asm/arch-tegra/tegra.h @@ -97,6 +97,11 @@ enum { TEGRA_SOC_UNKNOWN = -1, };
+/* Tegra system controller (SYSCON) devices */ +enum { + TEGRA_SYSCON_PMC, +}; + #else /* __ASSEMBLY__ */ #define PRM_RSTCTRL NV_PA_PMC_BASE #endif diff --git a/arch/arm/mach-tegra/tegra124/Makefile b/arch/arm/mach-tegra/tegra124/Makefile index c00de6151e..d275dafdc4 100644 --- a/arch/arm/mach-tegra/tegra124/Makefile +++ b/arch/arm/mach-tegra/tegra124/Makefile @@ -10,6 +10,7 @@ obj-$(CONFIG_SPL_BUILD) += cpu.o obj-y += clock.o obj-y += funcmux.o obj-y += pinmux.o +obj-y += pmc.o obj-y += xusb-padctl.o obj-y += ../xusb-padctl-common.o
diff --git a/arch/arm/mach-tegra/tegra124/pmc.c b/arch/arm/mach-tegra/tegra124/pmc.c new file mode 100644 index 0000000000..be82acf11e --- /dev/null +++ b/arch/arm/mach-tegra/tegra124/pmc.c @@ -0,0 +1,19 @@ +/* + * Copyright (C) 2017 Google, Inc + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <common.h> +#include <dm.h> +#include <syscon.h> + +static const struct udevice_id tegra124_syscon_ids[] = { + { .compatible = "nvidia,tegra124-pmc", .data = TEGRA_SYSCON_PMC }, +}; + +U_BOOT_DRIVER(syscon_tegra124) = { + .name = "tegra124_syscon", + .id = UCLASS_SYSCON, + .of_match = tegra124_syscon_ids, +}; diff --git a/configs/nyan-big_defconfig b/configs/nyan-big_defconfig index 8345aea27b..22769bdc93 100644 --- a/configs/nyan-big_defconfig +++ b/configs/nyan-big_defconfig @@ -34,6 +34,8 @@ CONFIG_CMD_EXT4_WRITE=y # CONFIG_SPL_ISO_PARTITION is not set # CONFIG_SPL_EFI_PARTITION is not set CONFIG_SPL_DM=y +CONFIG_REGMAP=y +CONFIG_SYSCON=y CONFIG_DFU_MMC=y CONFIG_DFU_RAM=y CONFIG_DFU_SF=y

Adjust this code to support a live device tree. This should be implemented as a PHY driver but that is left as an exercise for the maintainer.
Signed-off-by: Simon Glass sjg@chromium.org ---
arch/arm/include/asm/arch-tegra/xusb-padctl.h | 2 +- arch/arm/mach-tegra/board2.c | 2 +- arch/arm/mach-tegra/tegra124/xusb-padctl.c | 36 +++++++++--- arch/arm/mach-tegra/tegra210/xusb-padctl.c | 40 +++++++++---- arch/arm/mach-tegra/xusb-padctl-common.c | 84 ++++++++++++++------------- arch/arm/mach-tegra/xusb-padctl-common.h | 11 ++-- arch/arm/mach-tegra/xusb-padctl-dummy.c | 2 +- 7 files changed, 112 insertions(+), 65 deletions(-)
diff --git a/arch/arm/include/asm/arch-tegra/xusb-padctl.h b/arch/arm/include/asm/arch-tegra/xusb-padctl.h index b4b4c8ba4d..deccdf455d 100644 --- a/arch/arm/include/asm/arch-tegra/xusb-padctl.h +++ b/arch/arm/include/asm/arch-tegra/xusb-padctl.h @@ -15,7 +15,7 @@ struct tegra_xusb_phy; */ struct tegra_xusb_phy *tegra_xusb_phy_get(unsigned int type);
-void tegra_xusb_padctl_init(const void *fdt); +void tegra_xusb_padctl_init(void); 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); diff --git a/arch/arm/mach-tegra/board2.c b/arch/arm/mach-tegra/board2.c index 943ee24e59..5aedd3ef9d 100644 --- a/arch/arm/mach-tegra/board2.c +++ b/arch/arm/mach-tegra/board2.c @@ -164,7 +164,7 @@ int board_init(void) pin_mux_nand(); #endif
- tegra_xusb_padctl_init(gd->fdt_blob); + tegra_xusb_padctl_init();
#ifdef CONFIG_TEGRA_LP0 /* save Sdram params to PMC 2, 4, and 24 for WB0 */ diff --git a/arch/arm/mach-tegra/tegra124/xusb-padctl.c b/arch/arm/mach-tegra/tegra124/xusb-padctl.c index 76af924b94..d326a6ae57 100644 --- a/arch/arm/mach-tegra/tegra124/xusb-padctl.c +++ b/arch/arm/mach-tegra/tegra124/xusb-padctl.c @@ -8,6 +8,8 @@
#include <common.h> #include <errno.h> +#include <dm/of_access.h> +#include <dm/ofnode.h>
#include "../xusb-padctl-common.h"
@@ -317,13 +319,33 @@ static const struct tegra_xusb_padctl_soc tegra124_socdata = { .num_phys = ARRAY_SIZE(tegra124_phys), };
-void tegra_xusb_padctl_init(const void *fdt) +void tegra_xusb_padctl_init(void) { - int count, nodes[1]; + ofnode nodes[1]; + int count = 0; + int ret; + + debug("%s: start\n", __func__); + if (of_live_active()) { + struct device_node *np = of_find_compatible_node(NULL, NULL, + "nvidia,tegra124-xusb-padctl"); + + debug("np=%p\n", np); + if (np) { + nodes[0] = np_to_ofnode(np); + count = 1; + } + } else { + int node_offsets[1]; + int i; + + count = fdtdec_find_aliases_for_id(gd->fdt_blob, "padctl", + COMPAT_NVIDIA_TEGRA124_XUSB_PADCTL, + node_offsets, ARRAY_SIZE(node_offsets)); + for (i = 0; i < count; i++) + nodes[i] = offset_to_ofnode(node_offsets[i]); + }
- count = fdtdec_find_aliases_for_id(fdt, "padctl", - COMPAT_NVIDIA_TEGRA124_XUSB_PADCTL, - nodes, ARRAY_SIZE(nodes)); - if (tegra_xusb_process_nodes(fdt, nodes, count, &tegra124_socdata)) - return; + ret = tegra_xusb_process_nodes(nodes, count, &tegra124_socdata); + debug("%s: done, ret=%d\n", __func__, ret); } diff --git a/arch/arm/mach-tegra/tegra210/xusb-padctl.c b/arch/arm/mach-tegra/tegra210/xusb-padctl.c index 9ec93e7c4c..fde76dda01 100644 --- a/arch/arm/mach-tegra/tegra210/xusb-padctl.c +++ b/arch/arm/mach-tegra/tegra210/xusb-padctl.c @@ -8,6 +8,8 @@
#include <common.h> #include <errno.h> +#include <dm/of_access.h> +#include <dm/ofnode.h>
#include "../xusb-padctl-common.h"
@@ -421,17 +423,33 @@ static const struct tegra_xusb_padctl_soc tegra210_socdata = { .num_phys = ARRAY_SIZE(tegra210_phys), };
-void tegra_xusb_padctl_init(const void *fdt) +void tegra_xusb_padctl_init(void) { - int count, nodes[1]; - - debug("> %s(fdt=%p)\n", __func__, fdt); - - count = fdtdec_find_aliases_for_id(fdt, "padctl", - COMPAT_NVIDIA_TEGRA210_XUSB_PADCTL, - nodes, ARRAY_SIZE(nodes)); - if (tegra_xusb_process_nodes(fdt, nodes, count, &tegra210_socdata)) - return; + ofnode nodes[1]; + int count = 0; + int ret; + + debug("%s: start\n", __func__); + if (of_live_active()) { + struct device_node *np = of_find_compatible_node(NULL, NULL, + "nvidia,tegra210-xusb-padctl"); + + debug("np=%p\n", np); + if (np) { + nodes[0] = np_to_ofnode(np); + count = 1; + } + } else { + int node_offsets[1]; + int i; + + count = fdtdec_find_aliases_for_id(gd->fdt_blob, "padctl", + COMPAT_NVIDIA_TEGRA210_XUSB_PADCTL, + node_offsets, ARRAY_SIZE(node_offsets)); + for (i = 0; i < count; i++) + nodes[i] = offset_to_ofnode(node_offsets[i]); + }
- debug("< %s()\n", __func__); + ret = tegra_xusb_process_nodes(nodes, count, &tegra210_socdata); + debug("%s: done, ret=%d\n", __func__, ret); } diff --git a/arch/arm/mach-tegra/xusb-padctl-common.c b/arch/arm/mach-tegra/xusb-padctl-common.c index 43f5bb7da6..4114273b6d 100644 --- a/arch/arm/mach-tegra/xusb-padctl-common.c +++ b/arch/arm/mach-tegra/xusb-padctl-common.c @@ -75,39 +75,35 @@ tegra_xusb_padctl_find_lane(struct tegra_xusb_padctl *padctl, const char *name) static int tegra_xusb_padctl_group_parse_dt(struct tegra_xusb_padctl *padctl, struct tegra_xusb_padctl_group *group, - const void *fdt, int node) + ofnode node) { unsigned int i; - int len; - - group->name = fdt_get_name(fdt, node, &len); - - len = fdt_stringlist_count(fdt, node, "nvidia,lanes"); - if (len < 0) { - error("failed to parse "nvidia,lanes" property"); - return -EINVAL; - } - - group->num_pins = len; - - for (i = 0; i < group->num_pins; i++) { - group->pins[i] = fdt_stringlist_get(fdt, node, "nvidia,lanes", - i, NULL); - if (!group->pins[i]) { - error("failed to read string from "nvidia,lanes" property"); - return -EINVAL; + int ret; + + group->name = ofnode_get_name(node); + + for (i = 0; ; i++) { + ret = ofnode_read_string_index(node, "nvidia,lanes", i, + &group->pins[i]); + if (ret) { + if (!i) { + error("failed to read string from "nvidia,lanes" property"); + return -EINVAL; + } + break; } }
- group->num_pins = len; + group->num_pins = i;
- group->func = fdt_stringlist_get(fdt, node, "nvidia,function", 0, NULL); - if (!group->func) { + ret = ofnode_read_string_index(node, "nvidia,function", 0, + &group->func); + if (ret) { error("failed to parse "nvidia,func" property"); return -EINVAL; }
- group->iddq = fdtdec_get_int(fdt, node, "nvidia,iddq", -1); + group->iddq = ofnode_read_u32_default(node, "nvidia,iddq", -1);
return 0; } @@ -217,20 +213,21 @@ tegra_xusb_padctl_config_apply(struct tegra_xusb_padctl *padctl, static int tegra_xusb_padctl_config_parse_dt(struct tegra_xusb_padctl *padctl, struct tegra_xusb_padctl_config *config, - const void *fdt, int node) + ofnode node) { - int subnode; + ofnode subnode;
- config->name = fdt_get_name(fdt, node, NULL); + config->name = ofnode_get_name(node);
- fdt_for_each_subnode(subnode, fdt, node) { + for (subnode = ofnode_first_subnode(node); + ofnode_valid(node); + subnode = ofnode_next_subnode(subnode)) { struct tegra_xusb_padctl_group *group; int err;
group = &config->groups[config->num_groups];
- err = tegra_xusb_padctl_group_parse_dt(padctl, group, fdt, - subnode); + err = tegra_xusb_padctl_group_parse_dt(padctl, group, subnode); if (err < 0) { error("failed to parse group %s", group->name); return err; @@ -243,20 +240,25 @@ tegra_xusb_padctl_config_parse_dt(struct tegra_xusb_padctl *padctl, }
static int tegra_xusb_padctl_parse_dt(struct tegra_xusb_padctl *padctl, - const void *fdt, int node) + ofnode node) { - int subnode, err; + ofnode subnode; + int err;
- err = fdt_get_resource(fdt, node, "reg", 0, &padctl->regs); - if (err < 0) { + debug("%s: start %s\n", __func__, node.np->name); + padctl->regs = ofnode_get_addr(node); + if (padctl->regs == FDT_ADDR_T_NONE) { error("registers not found"); return err; }
- fdt_for_each_subnode(subnode, fdt, node) { + for (subnode = ofnode_first_subnode(node); + ofnode_valid(subnode); + subnode = ofnode_next_subnode(subnode)) { struct tegra_xusb_padctl_config *config = &padctl->config;
- err = tegra_xusb_padctl_config_parse_dt(padctl, config, fdt, + debug("%s: subnode=%s\n", __func__, subnode.np->name); + err = tegra_xusb_padctl_config_parse_dt(padctl, config, subnode); if (err < 0) { error("failed to parse entry %s: %d", @@ -264,25 +266,28 @@ static int tegra_xusb_padctl_parse_dt(struct tegra_xusb_padctl *padctl, continue; } } + debug("%s: done\n", __func__);
return 0; }
struct tegra_xusb_padctl padctl;
-int tegra_xusb_process_nodes(const void *fdt, int nodes[], unsigned int count, - const struct tegra_xusb_padctl_soc *socdata) +int tegra_xusb_process_nodes(ofnode nodes[], unsigned int count, + const struct tegra_xusb_padctl_soc *socdata) { unsigned int i; int err;
+ debug("%s: count=%d\n", __func__, count); for (i = 0; i < count; i++) { - if (!fdtdec_get_is_enabled(fdt, nodes[i])) + debug("%s: i=%d, node=%p\n", __func__, i, nodes[i].np); + if (!ofnode_is_available(nodes[i])) continue;
padctl.socdata = socdata;
- err = tegra_xusb_padctl_parse_dt(&padctl, fdt, nodes[i]); + err = tegra_xusb_padctl_parse_dt(&padctl, nodes[i]); if (err < 0) { error("failed to parse DT: %d", err); continue; @@ -300,6 +305,7 @@ int tegra_xusb_process_nodes(const void *fdt, int nodes[], unsigned int count, /* only a single instance is supported */ break; } + debug("%s: done\n", __func__);
return 0; } diff --git a/arch/arm/mach-tegra/xusb-padctl-common.h b/arch/arm/mach-tegra/xusb-padctl-common.h index f44790a650..afb62a9adc 100644 --- a/arch/arm/mach-tegra/xusb-padctl-common.h +++ b/arch/arm/mach-tegra/xusb-padctl-common.h @@ -9,6 +9,7 @@
#include <common.h> #include <fdtdec.h> +#include <dm/ofnode.h>
#include <asm/io.h> #include <asm/arch-tegra/xusb-padctl.h> @@ -77,7 +78,7 @@ struct tegra_xusb_padctl_config { struct tegra_xusb_padctl { const struct tegra_xusb_padctl_soc *socdata; struct tegra_xusb_padctl_config config; - struct fdt_resource regs; + ulong regs; unsigned int enable;
}; @@ -86,16 +87,16 @@ extern struct tegra_xusb_padctl padctl; static inline u32 padctl_readl(struct tegra_xusb_padctl *padctl, unsigned long offset) { - return readl(padctl->regs.start + offset); + return readl(padctl->regs + offset); }
static inline void padctl_writel(struct tegra_xusb_padctl *padctl, u32 value, unsigned long offset) { - writel(value, padctl->regs.start + offset); + writel(value, padctl->regs + offset); }
-int tegra_xusb_process_nodes(const void *fdt, int nodes[], unsigned int count, - const struct tegra_xusb_padctl_soc *socdata); +int tegra_xusb_process_nodes(ofnode nodes[], unsigned int count, + const struct tegra_xusb_padctl_soc *socdata);
#endif diff --git a/arch/arm/mach-tegra/xusb-padctl-dummy.c b/arch/arm/mach-tegra/xusb-padctl-dummy.c index 65f8d2ea96..856d712512 100644 --- a/arch/arm/mach-tegra/xusb-padctl-dummy.c +++ b/arch/arm/mach-tegra/xusb-padctl-dummy.c @@ -34,6 +34,6 @@ int __weak tegra_xusb_phy_unprepare(struct tegra_xusb_phy *phy) return -ENOSYS; }
-void __weak tegra_xusb_padctl_init(const void *fdt) +void __weak tegra_xusb_padctl_init(void) { }

Adjust this to take a device as a parameter instead of a node.
Signed-off-by: Simon Glass sjg@chromium.org ---
arch/arm/include/asm/arch-tegra/clock.h | 2 +- arch/arm/mach-tegra/clock.c | 5 ++--- drivers/spi/tegra114_spi.c | 2 +- drivers/spi/tegra20_sflash.c | 2 +- drivers/spi/tegra20_slink.c | 2 +- drivers/spi/tegra210_qspi.c | 2 +- drivers/usb/host/ehci-tegra.c | 2 +- 7 files changed, 8 insertions(+), 9 deletions(-)
diff --git a/arch/arm/include/asm/arch-tegra/clock.h b/arch/arm/include/asm/arch-tegra/clock.h index 388afcb723..301de4a899 100644 --- a/arch/arm/include/asm/arch-tegra/clock.h +++ b/arch/arm/include/asm/arch-tegra/clock.h @@ -266,7 +266,7 @@ void clock_ll_start_uart(enum periph_id periph_id); * @param node Node to look at * @return peripheral ID, or PERIPH_ID_NONE if none */ -enum periph_id clock_decode_periph_id(const void *blob, int node); +int clock_decode_periph_id(struct udevice *dev);
/** * Checks if the oscillator bypass is enabled (XOBP bit) diff --git a/arch/arm/mach-tegra/clock.c b/arch/arm/mach-tegra/clock.c index f547942022..090dba629c 100644 --- a/arch/arm/mach-tegra/clock.c +++ b/arch/arm/mach-tegra/clock.c @@ -652,14 +652,13 @@ void clock_ll_start_uart(enum periph_id periph_id) }
#if CONFIG_IS_ENABLED(OF_CONTROL) -int clock_decode_periph_id(const void *blob, int node) +int clock_decode_periph_id(struct udevice *dev) { enum periph_id id; u32 cell[2]; int err;
- err = fdtdec_get_int_array(blob, node, "clocks", cell, - ARRAY_SIZE(cell)); + err = dev_read_u32_array(dev, "clocks", cell, ARRAY_SIZE(cell)); if (err) return -1; id = clk_id_to_periph_id(cell[1]); diff --git a/drivers/spi/tegra114_spi.c b/drivers/spi/tegra114_spi.c index 802117eb49..86b1019585 100644 --- a/drivers/spi/tegra114_spi.c +++ b/drivers/spi/tegra114_spi.c @@ -104,7 +104,7 @@ static int tegra114_spi_ofdata_to_platdata(struct udevice *bus) int node = dev_of_offset(bus);
plat->base = devfdt_get_addr(bus); - plat->periph_id = clock_decode_periph_id(blob, node); + plat->periph_id = clock_decode_periph_id(bus);
if (plat->periph_id == PERIPH_ID_NONE) { debug("%s: could not decode periph id %d\n", __func__, diff --git a/drivers/spi/tegra20_sflash.c b/drivers/spi/tegra20_sflash.c index 299e1b44fa..e70210d7ab 100644 --- a/drivers/spi/tegra20_sflash.c +++ b/drivers/spi/tegra20_sflash.c @@ -91,7 +91,7 @@ static int tegra20_sflash_ofdata_to_platdata(struct udevice *bus) int node = dev_of_offset(bus);
plat->base = devfdt_get_addr(bus); - plat->periph_id = clock_decode_periph_id(blob, node); + plat->periph_id = clock_decode_periph_id(bus);
if (plat->periph_id == PERIPH_ID_NONE) { debug("%s: could not decode periph id %d\n", __func__, diff --git a/drivers/spi/tegra20_slink.c b/drivers/spi/tegra20_slink.c index 4cbde7b22f..f242574760 100644 --- a/drivers/spi/tegra20_slink.c +++ b/drivers/spi/tegra20_slink.c @@ -97,7 +97,7 @@ static int tegra30_spi_ofdata_to_platdata(struct udevice *bus) int node = dev_of_offset(bus);
plat->base = devfdt_get_addr(bus); - plat->periph_id = clock_decode_periph_id(blob, node); + plat->periph_id = clock_decode_periph_id(bus);
if (plat->periph_id == PERIPH_ID_NONE) { debug("%s: could not decode periph id %d\n", __func__, diff --git a/drivers/spi/tegra210_qspi.c b/drivers/spi/tegra210_qspi.c index 6d0b5da261..2a35a583f5 100644 --- a/drivers/spi/tegra210_qspi.c +++ b/drivers/spi/tegra210_qspi.c @@ -100,7 +100,7 @@ static int tegra210_qspi_ofdata_to_platdata(struct udevice *bus) int node = dev_of_offset(bus);
plat->base = devfdt_get_addr(bus); - plat->periph_id = clock_decode_periph_id(blob, node); + plat->periph_id = clock_decode_periph_id(bus);
if (plat->periph_id == PERIPH_ID_NONE) { debug("%s: could not decode periph id %d\n", __func__, diff --git a/drivers/usb/host/ehci-tegra.c b/drivers/usb/host/ehci-tegra.c index 7dc37f045d..873bf8ecfd 100644 --- a/drivers/usb/host/ehci-tegra.c +++ b/drivers/usb/host/ehci-tegra.c @@ -723,7 +723,7 @@ static int fdt_decode_usb(struct udevice *dev, struct fdt_usb *config) config->enabled = fdtdec_get_is_enabled(blob, node); config->has_legacy_mode = fdtdec_get_bool(blob, node, "nvidia,has-legacy-mode"); - config->periph_id = clock_decode_periph_id(blob, node); + config->periph_id = clock_decode_periph_id(dev); if (config->periph_id == PERIPH_ID_NONE) { debug("%s: Missing/invalid peripheral ID\n", __func__); return -EINVAL;

Update these drivers to support a live device tree.
Signed-off-by: Simon Glass sjg@chromium.org ---
drivers/video/tegra124/display.c | 8 +++----- drivers/video/tegra124/dp.c | 3 +-- drivers/video/tegra124/sor.c | 25 +++++++------------------ 3 files changed, 11 insertions(+), 25 deletions(-)
diff --git a/drivers/video/tegra124/display.c b/drivers/video/tegra124/display.c index 47752b27f1..4164fa1bd9 100644 --- a/drivers/video/tegra124/display.c +++ b/drivers/video/tegra124/display.c @@ -12,7 +12,6 @@ #include <errno.h> #include <display.h> #include <edid.h> -#include <fdtdec.h> #include <lcd.h> #include <video.h> #include <asm/gpio.h> @@ -334,7 +333,6 @@ static int display_init(struct udevice *dev, void *lcdbase, { struct display_plat *disp_uc_plat; struct dc_ctlr *dc_ctlr; - const void *blob = gd->fdt_blob; struct udevice *dp_dev; const int href_to_sync = 1, vref_to_sync = 1; int panel_bpp = 18; /* default 18 bits per pixel */ @@ -363,9 +361,8 @@ static int display_init(struct udevice *dev, void *lcdbase, return ret; }
- dc_ctlr = (struct dc_ctlr *)fdtdec_get_addr(blob, dev_of_offset(dev), - "reg"); - if (fdtdec_decode_display_timing(blob, dev_of_offset(dev), 0, timing)) { + dc_ctlr = (struct dc_ctlr *)dev_read_addr(dev); + if (ofnode_decode_display_timing(dev_ofnode(dev), 0, timing)) { debug("%s: Failed to decode display timing\n", __func__); return -EINVAL; } @@ -416,6 +413,7 @@ static int display_init(struct udevice *dev, void *lcdbase, debug("dc: failed to update window\n"); return ret; } + debug("%s: ready\n", __func__);
return 0; } diff --git a/drivers/video/tegra124/dp.c b/drivers/video/tegra124/dp.c index c38b3e5335..95d743d0f4 100644 --- a/drivers/video/tegra124/dp.c +++ b/drivers/video/tegra124/dp.c @@ -10,7 +10,6 @@ #include <dm.h> #include <div64.h> #include <errno.h> -#include <fdtdec.h> #include <video_bridge.h> #include <asm/io.h> #include <asm/arch-tegra/dc.h> @@ -1572,7 +1571,7 @@ static int tegra_dp_ofdata_to_platdata(struct udevice *dev) { struct tegra_dp_plat *plat = dev_get_platdata(dev);
- plat->base = devfdt_get_addr(dev); + plat->base = dev_read_addr(dev);
return 0; } diff --git a/drivers/video/tegra124/sor.c b/drivers/video/tegra124/sor.c index 5e4140ff53..1f5e572bda 100644 --- a/drivers/video/tegra124/sor.c +++ b/drivers/video/tegra124/sor.c @@ -7,9 +7,9 @@ #include <common.h> #include <dm.h> #include <errno.h> -#include <fdtdec.h> #include <malloc.h> #include <panel.h> +#include <syscon.h> #include <video_bridge.h> #include <asm/io.h> #include <asm/arch/clock.h> @@ -750,15 +750,12 @@ int tegra_dc_sor_attach(struct udevice *dc_dev, struct udevice *dev, const struct display_timing *timing) { struct tegra_dc_sor_data *sor = dev_get_priv(dev); - const void *blob = gd->fdt_blob; struct dc_ctlr *disp_ctrl; u32 reg_val; - int node;
/* Use the first display controller */ debug("%s\n", __func__); - node = dev_of_offset(dc_dev); - disp_ctrl = (struct dc_ctlr *)fdtdec_get_addr(blob, node, "reg"); + disp_ctrl = (struct dc_ctlr *)dev_read_addr(dc_dev);
tegra_dc_sor_enable_dc(disp_ctrl); tegra_dc_sor_config_panel(sor, 0, link_cfg, timing); @@ -965,16 +962,13 @@ int tegra_dc_sor_detach(struct udevice *dc_dev, struct udevice *dev) { struct tegra_dc_sor_data *sor = dev_get_priv(dev); int dc_reg_ctx[DC_REG_SAVE_SPACE]; - const void *blob = gd->fdt_blob; struct dc_ctlr *disp_ctrl; unsigned long dc_int_mask; - int node; int ret;
debug("%s\n", __func__); /* Use the first display controller */ - node = dev_of_offset(dc_dev); - disp_ctrl = (struct dc_ctlr *)fdtdec_get_addr(blob, node, "reg"); + disp_ctrl = (struct dc_ctlr *)dev_read_addr(dev);
/* Sleep mode */ tegra_sor_writel(sor, SUPER_STATE1, SUPER_STATE1_ASY_HEAD_OP_SLEEP | @@ -1041,18 +1035,13 @@ static int tegra_sor_set_backlight(struct udevice *dev, int percent) static int tegra_sor_ofdata_to_platdata(struct udevice *dev) { struct tegra_dc_sor_data *priv = dev_get_priv(dev); - const void *blob = gd->fdt_blob; - int node; int ret;
- priv->base = (void *)fdtdec_get_addr(blob, dev_of_offset(dev), "reg"); + priv->base = (void *)dev_read_addr(dev);
- node = fdtdec_next_compatible(blob, 0, COMPAT_NVIDIA_TEGRA124_PMC); - if (node < 0) { - debug("%s: Cannot find PMC\n", __func__); - return -ENOENT; - } - priv->pmc_base = (void *)fdtdec_get_addr(blob, node, "reg"); + priv->pmc_base = (void *)syscon_get_first_range(TEGRA_SYSCON_PMC); + if (IS_ERR(priv->pmc_base)) + return PTR_ERR(priv->pmc_base);
ret = uclass_get_device_by_phandle(UCLASS_PANEL, dev, "nvidia,panel", &priv->panel);

On Fri, 19 May 2017 08:30:52 -0600 Simon Glass sjg@chromium.org wrote:
Update these drivers to support a live device tree.
Signed-off-by: Simon Glass sjg@chromium.org
drivers/video/tegra124/display.c | 8 +++----- drivers/video/tegra124/dp.c | 3 +-- drivers/video/tegra124/sor.c | 25 +++++++------------------ 3 files changed, 11 insertions(+), 25 deletions(-)
Acked-by: Anatolij Gustschin agust@denx.de

This property should be in the /chosen node, not /aliases.
Signed-off-by: Simon Glass sjg@chromium.org ---
arch/arm/dts/tegra124-nyan-big.dts | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-)
diff --git a/arch/arm/dts/tegra124-nyan-big.dts b/arch/arm/dts/tegra124-nyan-big.dts index 62f89d0f1a..f1c97052a8 100644 --- a/arch/arm/dts/tegra124-nyan-big.dts +++ b/arch/arm/dts/tegra124-nyan-big.dts @@ -8,7 +8,6 @@
aliases { console = &uarta; - stdout-path = &uarta; i2c0 = "/i2c@7000d000"; i2c1 = "/i2c@7000c000"; i2c2 = "/i2c@7000c400"; @@ -26,6 +25,10 @@ usb2 = "/usb@7d004000"; };
+ chosen { + stdout-path = &uarta; + }; + host1x@50000000 { dc@54200000 { display-timings {

The UART clocks are already set up in SPL so we don't need to do it again in U-Boot. This seems to cause a hang on Nyan.
Signed-off-by: Simon Glass sjg@chromium.org ---
arch/arm/mach-tegra/board.c | 2 ++ 1 file changed, 2 insertions(+)
diff --git a/arch/arm/mach-tegra/board.c b/arch/arm/mach-tegra/board.c index b3a041b539..c478420655 100644 --- a/arch/arm/mach-tegra/board.c +++ b/arch/arm/mach-tegra/board.c @@ -187,7 +187,9 @@ static void setup_uarts(int uart_ids) enum periph_id id = id_for_uart[i];
funcmux_select(id, uart_configs[i]); +#ifdef CONFIG_SPL_BUILD clock_ll_start_uart(id); +#endif } } }

Update the GPIO driver to support a live device tree.
Signed-off-by: Simon Glass sjg@chromium.org ---
drivers/gpio/tegra_gpio.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-)
diff --git a/drivers/gpio/tegra_gpio.c b/drivers/gpio/tegra_gpio.c index 687cd74fee..4965583158 100644 --- a/drivers/gpio/tegra_gpio.c +++ b/drivers/gpio/tegra_gpio.c @@ -337,11 +337,13 @@ static int gpio_tegra_bind(struct udevice *parent) * This driver does not make use of interrupts, other than to figure * out the number of GPIO banks */ - if (!fdt_getprop(gd->fdt_blob, dev_of_offset(parent), "interrupts", - &len)) - return -EINVAL; + len = dev_read_size(parent, "interrupts"); + if (len < 0) + return len; bank_count = len / 3 / sizeof(u32); - ctlr = (struct gpio_ctlr *)devfdt_get_addr(parent); + ctlr = (struct gpio_ctlr *)dev_read_addr(parent); + if ((ulong)ctlr == FDT_ADDR_T_NONE) + return -EINVAL; } #endif for (bank = 0; bank < bank_count; bank++) {

Update the Tegra EHCI driver to support a live device tree.
Signed-off-by: Simon Glass sjg@chromium.org ---
drivers/usb/host/ehci-tegra.c | 34 ++++++++++++++-------------------- 1 file changed, 14 insertions(+), 20 deletions(-)
diff --git a/drivers/usb/host/ehci-tegra.c b/drivers/usb/host/ehci-tegra.c index 873bf8ecfd..1c72330b0c 100644 --- a/drivers/usb/host/ehci-tegra.c +++ b/drivers/usb/host/ehci-tegra.c @@ -17,7 +17,6 @@ #include <usb.h> #include <usb/ulpi.h> #include <libfdt.h> -#include <fdtdec.h>
#include "ehci.h"
@@ -695,12 +694,11 @@ static void config_clock(const u32 timing[])
static int fdt_decode_usb(struct udevice *dev, struct fdt_usb *config) { - const void *blob = gd->fdt_blob; - int node = dev_of_offset(dev); const char *phy, *mode;
- config->reg = (struct usb_ctlr *)devfdt_get_addr(dev); - mode = fdt_getprop(blob, node, "dr_mode", NULL); + config->reg = (struct usb_ctlr *)dev_read_addr(dev); + debug("reg=%p\n", config->reg); + mode = dev_read_string(dev, "dr_mode"); if (mode) { if (0 == strcmp(mode, "host")) config->dr_mode = DR_MODE_HOST; @@ -717,28 +715,24 @@ static int fdt_decode_usb(struct udevice *dev, struct fdt_usb *config) config->dr_mode = DR_MODE_HOST; }
- phy = fdt_getprop(blob, node, "phy_type", NULL); + phy = dev_read_string(dev, "phy_type"); config->utmi = phy && 0 == strcmp("utmi", phy); config->ulpi = phy && 0 == strcmp("ulpi", phy); - config->enabled = fdtdec_get_is_enabled(blob, node); - config->has_legacy_mode = fdtdec_get_bool(blob, node, - "nvidia,has-legacy-mode"); + config->has_legacy_mode = dev_read_bool(dev, "nvidia,has-legacy-mode"); config->periph_id = clock_decode_periph_id(dev); if (config->periph_id == PERIPH_ID_NONE) { debug("%s: Missing/invalid peripheral ID\n", __func__); return -EINVAL; } - gpio_request_by_name_nodev(offset_to_ofnode(node), "nvidia,vbus-gpio", - 0, &config->vbus_gpio, GPIOD_IS_OUT); - gpio_request_by_name_nodev(offset_to_ofnode(node), - "nvidia,phy-reset-gpio", 0, - &config->phy_reset_gpio, GPIOD_IS_OUT); - debug("enabled=%d, legacy_mode=%d, utmi=%d, ulpi=%d, periph_id=%d, " - "vbus=%d, phy_reset=%d, dr_mode=%d\n", - config->enabled, config->has_legacy_mode, config->utmi, - config->ulpi, config->periph_id, - gpio_get_number(&config->vbus_gpio), - gpio_get_number(&config->phy_reset_gpio), config->dr_mode); + gpio_request_by_name(dev, "nvidia,vbus-gpio", 0, &config->vbus_gpio, + GPIOD_IS_OUT); + gpio_request_by_name(dev, "nvidia,phy-reset-gpio", 0, + &config->phy_reset_gpio, GPIOD_IS_OUT); + debug("legacy_mode=%d, utmi=%d, ulpi=%d, periph_id=%d, vbus=%d, phy_reset=%d, dr_mode=%d, reg=%p\n", + config->has_legacy_mode, config->utmi, config->ulpi, + config->periph_id, gpio_get_number(&config->vbus_gpio), + gpio_get_number(&config->phy_reset_gpio), config->dr_mode, + config->reg);
return 0; }

Update the tegra114 spi driver to support a live device tree.
Signed-off-by: Simon Glass sjg@chromium.org ---
drivers/spi/tegra114_spi.c | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-)
diff --git a/drivers/spi/tegra114_spi.c b/drivers/spi/tegra114_spi.c index 86b1019585..013bc82380 100644 --- a/drivers/spi/tegra114_spi.c +++ b/drivers/spi/tegra114_spi.c @@ -12,7 +12,6 @@ #include <asm/arch/clock.h> #include <asm/arch-tegra/clk_rst.h> #include <spi.h> -#include <fdtdec.h> #include "tegra_spi.h"
DECLARE_GLOBAL_DATA_PTR; @@ -100,10 +99,8 @@ struct tegra114_spi_priv { static int tegra114_spi_ofdata_to_platdata(struct udevice *bus) { struct tegra_spi_platdata *plat = bus->platdata; - const void *blob = gd->fdt_blob; - int node = dev_of_offset(bus);
- plat->base = devfdt_get_addr(bus); + plat->base = dev_read_addr(bus); plat->periph_id = clock_decode_periph_id(bus);
if (plat->periph_id == PERIPH_ID_NONE) { @@ -113,10 +110,10 @@ static int tegra114_spi_ofdata_to_platdata(struct udevice *bus) }
/* Use 500KHz as a suitable default */ - plat->frequency = fdtdec_get_int(blob, node, "spi-max-frequency", - 500000); - plat->deactivate_delay_us = fdtdec_get_int(blob, node, - "spi-deactivate-delay", 0); + plat->frequency = dev_read_u32_default(bus, "spi-max-frequency", + 500000); + plat->deactivate_delay_us = dev_read_u32_default(bus, + "spi-deactivate-delay", 0); debug("%s: base=%#08lx, periph_id=%d, max-frequency=%d, deactivate_delay=%d\n", __func__, plat->base, plat->periph_id, plat->frequency, plat->deactivate_delay_us);

Update the tegra i2c driver to support a live device tree.
Signed-off-by: Simon Glass sjg@chromium.org ---
drivers/i2c/tegra_i2c.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-)
diff --git a/drivers/i2c/tegra_i2c.c b/drivers/i2c/tegra_i2c.c index 055f48153a..4163d798d5 100644 --- a/drivers/i2c/tegra_i2c.c +++ b/drivers/i2c/tegra_i2c.c @@ -365,7 +365,11 @@ static int tegra_i2c_probe(struct udevice *dev)
i2c_bus->id = dev->seq; i2c_bus->type = dev_get_driver_data(dev); - i2c_bus->regs = (struct i2c_ctlr *)devfdt_get_addr(dev); + i2c_bus->regs = (struct i2c_ctlr *)dev_read_addr(dev); + if ((ulong)i2c_bus->regs == FDT_ADDR_T_NONE) { + debug("%s: Cannot get regs address\n", __func__); + return -EINVAL; + }
ret = reset_get_by_name(dev, "i2c", &i2c_bus->reset_ctl); if (ret) {

Update the tegra pwm driver to support a live device tree.
Signed-off-by: Simon Glass sjg@chromium.org ---
drivers/pwm/tegra_pwm.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/pwm/tegra_pwm.c b/drivers/pwm/tegra_pwm.c index d93ac28c31..b8acc1583f 100644 --- a/drivers/pwm/tegra_pwm.c +++ b/drivers/pwm/tegra_pwm.c @@ -59,7 +59,7 @@ static int tegra_pwm_ofdata_to_platdata(struct udevice *dev) { struct tegra_pwm_priv *priv = dev_get_priv(dev);
- priv->regs = (struct pwm_ctlr *)devfdt_get_addr(dev); + priv->regs = (struct pwm_ctlr *)dev_read_addr(dev);
return 0; }

Update the tegra mmc driver to support a live device tree.
Signed-off-by: Simon Glass sjg@chromium.org ---
drivers/mmc/tegra_mmc.c | 17 +++++++---------- 1 file changed, 7 insertions(+), 10 deletions(-)
diff --git a/drivers/mmc/tegra_mmc.c b/drivers/mmc/tegra_mmc.c index 338e42b528..9f7e7195f1 100644 --- a/drivers/mmc/tegra_mmc.c +++ b/drivers/mmc/tegra_mmc.c @@ -11,10 +11,10 @@ #include <common.h> #include <dm.h> #include <errno.h> +#include <mmc.h> #include <asm/gpio.h> #include <asm/io.h> #include <asm/arch-tegra/tegra_mmc.h> -#include <mmc.h>
DECLARE_GLOBAL_DATA_PTR;
@@ -599,8 +599,7 @@ static int tegra_mmc_probe(struct udevice *dev)
cfg->name = dev->name;
- bus_width = fdtdec_get_int(gd->fdt_blob, dev_of_offset(dev), - "bus-width", 1); + bus_width = dev_read_u32_default(dev, "bus-width", 1);
cfg->voltages = MMC_VDD_32_33 | MMC_VDD_33_34 | MMC_VDD_165_195; cfg->host_caps = 0; @@ -621,7 +620,7 @@ static int tegra_mmc_probe(struct udevice *dev)
cfg->b_max = CONFIG_SYS_MMC_MAX_BLK_COUNT;
- priv->reg = (void *)devfdt_get_addr(dev); + priv->reg = (void *)dev_read_addr(dev);
ret = reset_get_by_name(dev, "sdhci", &priv->reset_ctl); if (ret) { @@ -648,12 +647,10 @@ static int tegra_mmc_probe(struct udevice *dev) return ret;
/* These GPIOs are optional */ - gpio_request_by_name(dev, "cd-gpios", 0, &priv->cd_gpio, - GPIOD_IS_IN); - gpio_request_by_name(dev, "wp-gpios", 0, &priv->wp_gpio, - GPIOD_IS_IN); - gpio_request_by_name(dev, "power-gpios", 0, - &priv->pwr_gpio, GPIOD_IS_OUT); + gpio_request_by_name(dev, "cd-gpios", 0, &priv->cd_gpio, GPIOD_IS_IN); + gpio_request_by_name(dev, "wp-gpios", 0, &priv->wp_gpio, GPIOD_IS_IN); + gpio_request_by_name(dev, "power-gpios", 0, &priv->pwr_gpio, + GPIOD_IS_OUT); if (dm_gpio_is_valid(&priv->pwr_gpio)) dm_gpio_set_value(&priv->pwr_gpio, 1);

This pmic includes regulators which should have their own driver. Add a driver to support these.
Signed-off-by: Simon Glass sjg@chromium.org ---
drivers/power/regulator/Kconfig | 9 ++ drivers/power/regulator/Makefile | 1 + drivers/power/regulator/as3722_regulator.c | 149 +++++++++++++++++++++++++++++ include/power/as3722.h | 8 ++ 4 files changed, 167 insertions(+) create mode 100644 drivers/power/regulator/as3722_regulator.c
diff --git a/drivers/power/regulator/Kconfig b/drivers/power/regulator/Kconfig index ef057e0e2f..2583a19910 100644 --- a/drivers/power/regulator/Kconfig +++ b/drivers/power/regulator/Kconfig @@ -34,6 +34,15 @@ config REGULATOR_ACT8846 by the PMIC device. This driver is controlled by a device tree node which includes voltage limits.
+config REGULATOR_AS3722 + bool "Enable driver for AS7322 regulator" + depends on DM_REGULATOR && PMIC_AS3722 + help + Enable support for the regulator functions of the AS3722. The + driver implements enable/disable for step-down bucks and LDOs, + but does not yet support change voltages. Currently this must be + done using direct register writes to the PMIC. + config DM_REGULATOR_PFUZE100 bool "Enable Driver Model for REGULATOR PFUZE100" depends on DM_REGULATOR && DM_PMIC_PFUZE100 diff --git a/drivers/power/regulator/Makefile b/drivers/power/regulator/Makefile index 3e01021b76..48d3735d6c 100644 --- a/drivers/power/regulator/Makefile +++ b/drivers/power/regulator/Makefile @@ -7,6 +7,7 @@
obj-$(CONFIG_$(SPL_)DM_REGULATOR) += regulator-uclass.o obj-$(CONFIG_REGULATOR_ACT8846) += act8846.o +obj-$(CONFIG_REGULATOR_AS3722) += as3722_regulator.o obj-$(CONFIG_DM_REGULATOR_MAX77686) += max77686.o obj-$(CONFIG_DM_REGULATOR_PFUZE100) += pfuze100.o obj-$(CONFIG_REGULATOR_PWM) += pwm_regulator.o diff --git a/drivers/power/regulator/as3722_regulator.c b/drivers/power/regulator/as3722_regulator.c new file mode 100644 index 0000000000..0122e1e389 --- /dev/null +++ b/drivers/power/regulator/as3722_regulator.c @@ -0,0 +1,149 @@ +/* + * Copyright (C) 2017 Google, Inc + * Written by Simon Glass sjg@chromium.org + * + * Placeholder regulator driver for as3722. + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <common.h> +#include <dm.h> +#include <errno.h> +#include <power/as3722.h> +#include <power/pmic.h> +#include <power/regulator.h> + +static int stepdown_get_value(struct udevice *dev) +{ + return -ENOSYS; +} + +static int stepdown_set_value(struct udevice *dev, int uvolt) +{ + return -ENOSYS; +} + +static int stepdown_set_enable(struct udevice *dev, bool enable) +{ + struct udevice *pmic = dev_get_parent(dev); + int sd = dev->driver_data; + int ret; + + ret = pmic_clrsetbits(pmic, AS3722_SD_CONTROL, 0, 1 << sd); + if (ret < 0) { + debug("%s: failed to write SD control register: %d", __func__, + ret); + return ret; + } + + return 0; +} + +static bool stepdown_get_enable(struct udevice *dev) +{ + struct udevice *pmic = dev_get_parent(dev); + int sd = dev->driver_data; + int ret; + + ret = pmic_reg_read(pmic, AS3722_SD_CONTROL); + if (ret < 0) { + debug("%s: failed to read SD control register: %d", __func__, + ret); + return false; + } + + return ret & (1 << sd) ? true : false; +} + +static int ldo_get_value(struct udevice *dev) +{ + return -ENOSYS; +} + +static int ldo_set_value(struct udevice *dev, int uvolt) +{ + return -ENOSYS; +} + +static int ldo_set_enable(struct udevice *dev, bool enable) +{ + struct udevice *pmic = dev_get_parent(dev); + int ldo = dev->driver_data; + int ret; + + ret = pmic_clrsetbits(pmic, AS3722_LDO_CONTROL, 0, 1 << ldo); + if (ret < 0) { + debug("%s: failed to write LDO control register: %d", __func__, + ret); + return ret; + } + + return 0; +} + +static bool ldo_get_enable(struct udevice *dev) +{ + struct udevice *pmic = dev_get_parent(dev); + int ldo = dev->driver_data; + int ret; + + ret = pmic_reg_read(pmic, AS3722_LDO_CONTROL); + if (ret < 0) { + debug("%s: failed to read SD control register: %d", __func__, + ret); + return false; + } + + return ret & (1 << ldo) ? true : false; +} + +static int as3722_stepdown_probe(struct udevice *dev) +{ + struct dm_regulator_uclass_platdata *uc_pdata; + + uc_pdata = dev_get_uclass_platdata(dev); + + uc_pdata->type = REGULATOR_TYPE_BUCK; + + return 0; +} + +static int as3722_ldo_probe(struct udevice *dev) +{ + struct dm_regulator_uclass_platdata *uc_pdata; + + uc_pdata = dev_get_uclass_platdata(dev); + + uc_pdata->type = REGULATOR_TYPE_LDO; + + return 0; +} + +static const struct dm_regulator_ops as3722_stepdown_ops = { + .get_value = stepdown_get_value, + .set_value = stepdown_set_value, + .get_enable = stepdown_get_enable, + .set_enable = stepdown_set_enable, +}; + +static const struct dm_regulator_ops as3722_ldo_ops = { + .get_value = ldo_get_value, + .set_value = ldo_set_value, + .get_enable = ldo_get_enable, + .set_enable = ldo_set_enable, +}; + +U_BOOT_DRIVER(as3722_stepdown) = { + .name = "as3722_stepdown", + .id = UCLASS_REGULATOR, + .ops = &as3722_stepdown_ops, + .probe = as3722_stepdown_probe, +}; + +U_BOOT_DRIVER(as3722_ldo) = { + .name = "as3722_ldo", + .id = UCLASS_REGULATOR, + .ops = &as3722_ldo_ops, + .probe = as3722_ldo_probe, +}; diff --git a/include/power/as3722.h b/include/power/as3722.h index 0f22482ff7..14afa0c81a 100644 --- a/include/power/as3722.h +++ b/include/power/as3722.h @@ -12,6 +12,14 @@ #define AS3722_GPIO_OUTPUT_VDDH (1 << 0) #define AS3722_GPIO_INVERT (1 << 1)
+#define AS3722_DEVICE_ID 0x0c +#define AS3722_SD_VOLTAGE(n) (0x00 + (n)) +#define AS3722_LDO_VOLTAGE(n) (0x10 + (n)) +#define AS3722_SD_CONTROL 0x4d +#define AS3722_LDO_CONTROL 0x4e +#define AS3722_ASIC_ID1 0x90 +#define AS3722_ASIC_ID2 0x91 + struct udevice;
int as3722_init(struct udevice **devp);

On Fri, 19 May 2017 08:31:01 -0600 Simon Glass sjg@chromium.org wrote:
This pmic includes regulators which should have their own driver. Add a driver to support these.
Reviewed-by: Lukasz Majewski lukma@denx.de
Signed-off-by: Simon Glass sjg@chromium.org
drivers/power/regulator/Kconfig | 9 ++ drivers/power/regulator/Makefile | 1 + drivers/power/regulator/as3722_regulator.c | 149 +++++++++++++++++++++++++++++ include/power/as3722.h | 8 ++ 4 files changed, 167 insertions(+) create mode 100644 drivers/power/regulator/as3722_regulator.c
diff --git a/drivers/power/regulator/Kconfig b/drivers/power/regulator/Kconfig index ef057e0e2f..2583a19910 100644 --- a/drivers/power/regulator/Kconfig +++ b/drivers/power/regulator/Kconfig @@ -34,6 +34,15 @@ config REGULATOR_ACT8846 by the PMIC device. This driver is controlled by a device tree node which includes voltage limits.
+config REGULATOR_AS3722
- bool "Enable driver for AS7322 regulator"
- depends on DM_REGULATOR && PMIC_AS3722
- help
Enable support for the regulator functions of the AS3722.
The
driver implements enable/disable for step-down bucks and
LDOs,
but does not yet support change voltages. Currently this
must be
done using direct register writes to the PMIC.
config DM_REGULATOR_PFUZE100 bool "Enable Driver Model for REGULATOR PFUZE100" depends on DM_REGULATOR && DM_PMIC_PFUZE100 diff --git a/drivers/power/regulator/Makefile b/drivers/power/regulator/Makefile index 3e01021b76..48d3735d6c 100644 --- a/drivers/power/regulator/Makefile +++ b/drivers/power/regulator/Makefile @@ -7,6 +7,7 @@
obj-$(CONFIG_$(SPL_)DM_REGULATOR) += regulator-uclass.o obj-$(CONFIG_REGULATOR_ACT8846) += act8846.o +obj-$(CONFIG_REGULATOR_AS3722) += as3722_regulator.o obj-$(CONFIG_DM_REGULATOR_MAX77686) += max77686.o obj-$(CONFIG_DM_REGULATOR_PFUZE100) += pfuze100.o obj-$(CONFIG_REGULATOR_PWM) += pwm_regulator.o diff --git a/drivers/power/regulator/as3722_regulator.c b/drivers/power/regulator/as3722_regulator.c new file mode 100644 index 0000000000..0122e1e389 --- /dev/null +++ b/drivers/power/regulator/as3722_regulator.c @@ -0,0 +1,149 @@ +/*
- Copyright (C) 2017 Google, Inc
- Written by Simon Glass sjg@chromium.org
- Placeholder regulator driver for as3722.
- SPDX-License-Identifier: GPL-2.0+
- */
+#include <common.h> +#include <dm.h> +#include <errno.h> +#include <power/as3722.h> +#include <power/pmic.h> +#include <power/regulator.h>
+static int stepdown_get_value(struct udevice *dev) +{
- return -ENOSYS;
+}
+static int stepdown_set_value(struct udevice *dev, int uvolt) +{
- return -ENOSYS;
+}
+static int stepdown_set_enable(struct udevice *dev, bool enable) +{
- struct udevice *pmic = dev_get_parent(dev);
- int sd = dev->driver_data;
- int ret;
- ret = pmic_clrsetbits(pmic, AS3722_SD_CONTROL, 0, 1 << sd);
- if (ret < 0) {
debug("%s: failed to write SD control register: %d",
__func__,
ret);
return ret;
- }
- return 0;
+}
+static bool stepdown_get_enable(struct udevice *dev) +{
- struct udevice *pmic = dev_get_parent(dev);
- int sd = dev->driver_data;
- int ret;
- ret = pmic_reg_read(pmic, AS3722_SD_CONTROL);
- if (ret < 0) {
debug("%s: failed to read SD control register: %d",
__func__,
ret);
return false;
- }
- return ret & (1 << sd) ? true : false;
+}
+static int ldo_get_value(struct udevice *dev) +{
- return -ENOSYS;
+}
+static int ldo_set_value(struct udevice *dev, int uvolt) +{
- return -ENOSYS;
+}
+static int ldo_set_enable(struct udevice *dev, bool enable) +{
- struct udevice *pmic = dev_get_parent(dev);
- int ldo = dev->driver_data;
- int ret;
- ret = pmic_clrsetbits(pmic, AS3722_LDO_CONTROL, 0, 1 << ldo);
- if (ret < 0) {
debug("%s: failed to write LDO control register:
%d", __func__,
ret);
return ret;
- }
- return 0;
+}
+static bool ldo_get_enable(struct udevice *dev) +{
- struct udevice *pmic = dev_get_parent(dev);
- int ldo = dev->driver_data;
- int ret;
- ret = pmic_reg_read(pmic, AS3722_LDO_CONTROL);
- if (ret < 0) {
debug("%s: failed to read SD control register: %d",
__func__,
ret);
return false;
- }
- return ret & (1 << ldo) ? true : false;
+}
+static int as3722_stepdown_probe(struct udevice *dev) +{
- struct dm_regulator_uclass_platdata *uc_pdata;
- uc_pdata = dev_get_uclass_platdata(dev);
- uc_pdata->type = REGULATOR_TYPE_BUCK;
- return 0;
+}
+static int as3722_ldo_probe(struct udevice *dev) +{
- struct dm_regulator_uclass_platdata *uc_pdata;
- uc_pdata = dev_get_uclass_platdata(dev);
- uc_pdata->type = REGULATOR_TYPE_LDO;
- return 0;
+}
+static const struct dm_regulator_ops as3722_stepdown_ops = {
- .get_value = stepdown_get_value,
- .set_value = stepdown_set_value,
- .get_enable = stepdown_get_enable,
- .set_enable = stepdown_set_enable,
+};
+static const struct dm_regulator_ops as3722_ldo_ops = {
- .get_value = ldo_get_value,
- .set_value = ldo_set_value,
- .get_enable = ldo_get_enable,
- .set_enable = ldo_set_enable,
+};
+U_BOOT_DRIVER(as3722_stepdown) = {
- .name = "as3722_stepdown",
- .id = UCLASS_REGULATOR,
- .ops = &as3722_stepdown_ops,
- .probe = as3722_stepdown_probe,
+};
+U_BOOT_DRIVER(as3722_ldo) = {
- .name = "as3722_ldo",
- .id = UCLASS_REGULATOR,
- .ops = &as3722_ldo_ops,
- .probe = as3722_ldo_probe,
+}; diff --git a/include/power/as3722.h b/include/power/as3722.h index 0f22482ff7..14afa0c81a 100644 --- a/include/power/as3722.h +++ b/include/power/as3722.h @@ -12,6 +12,14 @@ #define AS3722_GPIO_OUTPUT_VDDH (1 << 0) #define AS3722_GPIO_INVERT (1 << 1)
+#define AS3722_DEVICE_ID 0x0c +#define AS3722_SD_VOLTAGE(n) (0x00 + (n)) +#define AS3722_LDO_VOLTAGE(n) (0x10 + (n)) +#define AS3722_SD_CONTROL 0x4d +#define AS3722_LDO_CONTROL 0x4e +#define AS3722_ASIC_ID1 0x90 +#define AS3722_ASIC_ID2 0x91
struct udevice;
int as3722_init(struct udevice **devp);
Best regards,
Lukasz Majewski
--
DENX Software Engineering GmbH, Managing Director: Wolfgang Denk HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany Phone: (+49)-8142-66989-10 Fax: (+49)-8142-66989-80 Email: wd@denx.de

This pmic includes GPIOs which should have their own driver. Add a driver to support these.
Signed-off-by: Simon Glass sjg@chromium.org ---
drivers/power/pmic/as3722_gpio.c | 120 +++++++++++++++++++++++++++++++++++++++ include/power/as3722.h | 5 ++ 2 files changed, 125 insertions(+) create mode 100644 drivers/power/pmic/as3722_gpio.c
diff --git a/drivers/power/pmic/as3722_gpio.c b/drivers/power/pmic/as3722_gpio.c new file mode 100644 index 0000000000..d0b681ca4a --- /dev/null +++ b/drivers/power/pmic/as3722_gpio.c @@ -0,0 +1,120 @@ +/* + * Copyright (C) 2014 NVIDIA Corporation + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <common.h> +#include <dm.h> +#include <asm/gpio.h> +#include <power/as3722.h> +#include <power/pmic.h> + +#define NUM_GPIOS 8 + +int as3722_gpio_configure(struct udevice *pmic, unsigned int gpio, + unsigned long flags) +{ + u8 value = 0; + int err; + + if (flags & AS3722_GPIO_OUTPUT_VDDH) + value |= AS3722_GPIO_CONTROL_MODE_OUTPUT_VDDH; + + if (flags & AS3722_GPIO_INVERT) + value |= AS3722_GPIO_CONTROL_INVERT; + + err = pmic_reg_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_value(struct udevice *dev, unsigned int gpio, + int level) +{ + struct udevice *pmic = dev_get_parent(dev); + const char *l; + u8 value; + int err; + + if (gpio >= NUM_GPIOS) + return -EINVAL; + + err = pmic_reg_read(pmic, AS3722_GPIO_SIGNAL_OUT); + if (err < 0) { + error("failed to read GPIO signal out register: %d", err); + return err; + } + value = err; + + if (level == 0) { + value &= ~(1 << gpio); + l = "low"; + } else { + value |= 1 << gpio; + l = "high"; + } + + err = pmic_reg_write(pmic, AS3722_GPIO_SIGNAL_OUT, value); + if (err) { + error("failed to set GPIO#%u %s: %d", gpio, l, err); + return err; + } + + return 0; +} + +int as3722_gpio_direction_output(struct udevice *dev, unsigned int gpio, + int value) +{ + struct udevice *pmic = dev_get_parent(dev); + int err; + + if (gpio > 7) + return -EINVAL; + + if (value == 0) + value = AS3722_GPIO_CONTROL_MODE_OUTPUT_VDDL; + else + value = AS3722_GPIO_CONTROL_MODE_OUTPUT_VDDH; + + err = pmic_reg_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_value(pmic, gpio, value); + if (err < 0) { + error("failed to set GPIO#%u high: %d", gpio, err); + return err; + } + + return 0; +} + +static int as3722_gpio_probe(struct udevice *dev) +{ + struct gpio_dev_priv *uc_priv = dev_get_uclass_priv(dev); + + uc_priv->gpio_count = NUM_GPIOS; + uc_priv->bank_name = "as3722_"; + + return 0; +} + +static const struct dm_gpio_ops gpio_as3722_ops = { + .direction_output = as3722_gpio_direction_output, + .set_value = as3722_gpio_set_value, +}; + +U_BOOT_DRIVER(gpio_as3722) = { + .name = "gpio_as3722", + .id = UCLASS_GPIO, + .ops = &gpio_as3722_ops, + .probe = as3722_gpio_probe, +}; diff --git a/include/power/as3722.h b/include/power/as3722.h index 14afa0c81a..713e79840f 100644 --- a/include/power/as3722.h +++ b/include/power/as3722.h @@ -20,6 +20,11 @@ #define AS3722_ASIC_ID1 0x90 #define AS3722_ASIC_ID2 0x91
+#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) + struct udevice;
int as3722_init(struct udevice **devp);

On Fri, 19 May 2017 08:31:02 -0600 Simon Glass sjg@chromium.org wrote:
This pmic includes GPIOs which should have their own driver. Add a driver to support these.
Reviewed-by: Lukasz Majewski lukma@denx.de
Signed-off-by: Simon Glass sjg@chromium.org
drivers/power/pmic/as3722_gpio.c | 120 +++++++++++++++++++++++++++++++++++++++ include/power/as3722.h | 5 ++ 2 files changed, 125 insertions(+) create mode 100644 drivers/power/pmic/as3722_gpio.c
diff --git a/drivers/power/pmic/as3722_gpio.c b/drivers/power/pmic/as3722_gpio.c new file mode 100644 index 0000000000..d0b681ca4a --- /dev/null +++ b/drivers/power/pmic/as3722_gpio.c @@ -0,0 +1,120 @@ +/*
- Copyright (C) 2014 NVIDIA Corporation
- SPDX-License-Identifier: GPL-2.0+
- */
+#include <common.h> +#include <dm.h> +#include <asm/gpio.h> +#include <power/as3722.h> +#include <power/pmic.h>
+#define NUM_GPIOS 8
+int as3722_gpio_configure(struct udevice *pmic, unsigned int gpio,
unsigned long flags)
+{
- u8 value = 0;
- int err;
- if (flags & AS3722_GPIO_OUTPUT_VDDH)
value |= AS3722_GPIO_CONTROL_MODE_OUTPUT_VDDH;
- if (flags & AS3722_GPIO_INVERT)
value |= AS3722_GPIO_CONTROL_INVERT;
- err = pmic_reg_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_value(struct udevice *dev, unsigned int gpio,
int level)
+{
- struct udevice *pmic = dev_get_parent(dev);
- const char *l;
- u8 value;
- int err;
- if (gpio >= NUM_GPIOS)
return -EINVAL;
- err = pmic_reg_read(pmic, AS3722_GPIO_SIGNAL_OUT);
- if (err < 0) {
error("failed to read GPIO signal out register: %d",
err);
return err;
- }
- value = err;
- if (level == 0) {
value &= ~(1 << gpio);
l = "low";
- } else {
value |= 1 << gpio;
l = "high";
- }
- err = pmic_reg_write(pmic, AS3722_GPIO_SIGNAL_OUT, value);
- if (err) {
error("failed to set GPIO#%u %s: %d", gpio, l, err);
return err;
- }
- return 0;
+}
+int as3722_gpio_direction_output(struct udevice *dev, unsigned int gpio,
int value)
+{
- struct udevice *pmic = dev_get_parent(dev);
- int err;
- if (gpio > 7)
return -EINVAL;
- if (value == 0)
value = AS3722_GPIO_CONTROL_MODE_OUTPUT_VDDL;
- else
value = AS3722_GPIO_CONTROL_MODE_OUTPUT_VDDH;
- err = pmic_reg_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_value(pmic, gpio, value);
- if (err < 0) {
error("failed to set GPIO#%u high: %d", gpio, err);
return err;
- }
- return 0;
+}
+static int as3722_gpio_probe(struct udevice *dev) +{
- struct gpio_dev_priv *uc_priv = dev_get_uclass_priv(dev);
- uc_priv->gpio_count = NUM_GPIOS;
- uc_priv->bank_name = "as3722_";
- return 0;
+}
+static const struct dm_gpio_ops gpio_as3722_ops = {
- .direction_output = as3722_gpio_direction_output,
- .set_value = as3722_gpio_set_value,
+};
+U_BOOT_DRIVER(gpio_as3722) = {
- .name = "gpio_as3722",
- .id = UCLASS_GPIO,
- .ops = &gpio_as3722_ops,
- .probe = as3722_gpio_probe,
+}; diff --git a/include/power/as3722.h b/include/power/as3722.h index 14afa0c81a..713e79840f 100644 --- a/include/power/as3722.h +++ b/include/power/as3722.h @@ -20,6 +20,11 @@ #define AS3722_ASIC_ID1 0x90 #define AS3722_ASIC_ID2 0x91
+#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)
struct udevice;
int as3722_init(struct udevice **devp);
Best regards,
Lukasz Majewski
--
DENX Software Engineering GmbH, Managing Director: Wolfgang Denk HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany Phone: (+49)-8142-66989-10 Fax: (+49)-8142-66989-80 Email: wd@denx.de

Convert this PMIC driver to driver model and fix up other users. The regulator and GPIO functions are now handled by separate drivers.
Note that this currently breaks apalis-tk1, jetson-tk1 and cei-tk1-som. I have the middle one so will tidy that up in the next version, at least.
Signed-off-by: Simon Glass sjg@chromium.org ---
arch/arm/mach-tegra/board2.c | 6 - board/nvidia/nyan-big/nyan-big.c | 22 +-- configs/nyan-big_defconfig | 1 + drivers/power/pmic/Makefile | 2 +- drivers/power/pmic/as3722.c | 292 +++++++++++++-------------------------- include/power/as3722.h | 18 +-- 6 files changed, 114 insertions(+), 227 deletions(-)
diff --git a/arch/arm/mach-tegra/board2.c b/arch/arm/mach-tegra/board2.c index 5aedd3ef9d..0291c7fb33 100644 --- a/arch/arm/mach-tegra/board2.c +++ b/arch/arm/mach-tegra/board2.c @@ -29,7 +29,6 @@ #ifdef CONFIG_TEGRA_CLOCK_SCALING #include <asm/arch/emc.h> #endif -#include <power/as3722.h> #include "emc.h"
DECLARE_GLOBAL_DATA_PTR; @@ -142,11 +141,6 @@ int board_init(void) debug("Memory controller init failed: %d\n", err); # endif # endif /* CONFIG_TEGRA_PMU */ -#ifdef CONFIG_PMIC_AS3722 - err = as3722_init(NULL); - if (err && err != -ENODEV) - return err; -#endif #endif /* CONFIG_SYS_I2C_TEGRA */
#ifdef CONFIG_USB_EHCI_TEGRA diff --git a/board/nvidia/nyan-big/nyan-big.c b/board/nvidia/nyan-big/nyan-big.c index 8f68ae9fbe..54acf5418d 100644 --- a/board/nvidia/nyan-big/nyan-big.c +++ b/board/nvidia/nyan-big/nyan-big.c @@ -6,6 +6,7 @@ */
#include <common.h> +#include <dm.h> #include <errno.h> #include <asm/gpio.h> #include <asm/io.h> @@ -46,20 +47,23 @@ int tegra_board_id(void)
int tegra_lcd_pmic_init(int board_id) { - struct udevice *pmic; + struct udevice *dev; int ret;
- ret = as3722_get(&pmic); - if (ret) - return -ENOENT; + ret = uclass_get_device_by_driver(UCLASS_PMIC, + DM_GET_DRIVER(pmic_as3722), &dev); + if (ret) { + debug("%s: Failed to find PMIC\n", __func__); + return ret; + }
if (board_id == 0) - as3722_write(pmic, 0x00, 0x3c); + pmic_reg_write(dev, 0x00, 0x3c); else - as3722_write(pmic, 0x00, 0x50); - as3722_write(pmic, 0x12, 0x10); - as3722_write(pmic, 0x0c, 0x07); - as3722_write(pmic, 0x20, 0x10); + pmic_reg_write(dev, 0x00, 0x50); + pmic_reg_write(dev, 0x12, 0x10); + pmic_reg_write(dev, 0x0c, 0x07); + pmic_reg_write(dev, 0x20, 0x10);
return 0; } diff --git a/configs/nyan-big_defconfig b/configs/nyan-big_defconfig index 22769bdc93..a152ff6915 100644 --- a/configs/nyan-big_defconfig +++ b/configs/nyan-big_defconfig @@ -47,6 +47,7 @@ CONFIG_SPI_FLASH_WINBOND=y CONFIG_DM_PMIC=y CONFIG_PMIC_AS3722=y CONFIG_DM_REGULATOR=y +CONFIG_REGULATOR_AS3722=y CONFIG_DM_REGULATOR_FIXED=y CONFIG_PWM_TEGRA=y CONFIG_SYS_NS16550=y diff --git a/drivers/power/pmic/Makefile b/drivers/power/pmic/Makefile index f409e3a0b3..76dda2a070 100644 --- a/drivers/power/pmic/Makefile +++ b/drivers/power/pmic/Makefile @@ -12,7 +12,7 @@ obj-$(CONFIG_DM_PMIC_PFUZE100) += pfuze100.o obj-$(CONFIG_PMIC_S2MPS11) += s2mps11.o obj-$(CONFIG_DM_PMIC_SANDBOX) += sandbox.o i2c_pmic_emul.o obj-$(CONFIG_PMIC_ACT8846) += act8846.o -obj-$(CONFIG_PMIC_AS3722) += as3722.o +obj-$(CONFIG_PMIC_AS3722) += as3722.o as3722_gpio.o obj-$(CONFIG_PMIC_MAX8997) += max8997.o obj-$(CONFIG_PMIC_PM8916) += pm8916.o obj-$(CONFIG_PMIC_RK8XX) += rk8xx.o diff --git a/drivers/power/pmic/as3722.c b/drivers/power/pmic/as3722.c index c09e1de06f..4efe8ee183 100644 --- a/drivers/power/pmic/as3722.c +++ b/drivers/power/pmic/as3722.c @@ -11,264 +11,168 @@ #include <errno.h> #include <fdtdec.h> #include <i2c.h> - +#include <dm/lists.h> #include <power/as3722.h> +#include <power/pmic.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 - -int as3722_read(struct udevice *pmic, u8 reg, u8 *value) -{ - int err; - - err = dm_i2c_read(pmic, reg, value, 1); - if (err < 0) - return err; - - return 0; -} +#define AS3722_NUM_OF_REGS 0x92
-int as3722_write(struct udevice *pmic, u8 reg, u8 value) +static int as3722_read(struct udevice *dev, uint reg, uint8_t *buff, int len) { - int err; + int ret;
- err = dm_i2c_write(pmic, reg, &value, 1); - if (err < 0) - return err; + ret = dm_i2c_read(dev, reg, buff, len); + if (ret < 0) + return ret;
return 0; }
-static int as3722_read_id(struct udevice *pmic, u8 *id, u8 *revision) +static int as3722_write(struct udevice *dev, uint reg, const uint8_t *buff, + int len) { - int err; + int ret;
- 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; - } + ret = dm_i2c_write(dev, reg, buff, len); + if (ret < 0) + return ret;
return 0; }
-int as3722_sd_enable(struct udevice *pmic, unsigned int sd) +static int as3722_read_id(struct udevice *dev, uint *idp, uint *revisionp) { - u8 value; - int err; - - if (sd > 6) - return -EINVAL; + int ret;
- err = as3722_read(pmic, AS3722_SD_CONTROL, &value); - if (err) { - error("failed to read SD control register: %d", err); - return err; + ret = pmic_reg_read(dev, AS3722_ASIC_ID1); + if (ret < 0) { + error("failed to read ID1 register: %d", ret); + return ret; } + *idp = ret;
- 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; + ret = pmic_reg_read(dev, AS3722_ASIC_ID2); + if (ret < 0) { + error("failed to read ID2 register: %d", ret); + return ret; } + *revisionp = ret;
return 0; }
-int as3722_sd_set_voltage(struct udevice *pmic, unsigned int sd, u8 value) +/* TODO(treding@nvidia.com): Add proper regulator support to avoid this */ +int as3722_sd_set_voltage(struct udevice *dev, unsigned int sd, u8 value) { - int err; + int ret;
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; + ret = pmic_reg_write(dev, AS3722_SD_VOLTAGE(sd), value); + if (ret < 0) { + error("failed to write SD%u voltage register: %d", sd, ret); + return ret; }
return 0; }
-int as3722_ldo_enable(struct udevice *pmic, unsigned int ldo) +int as3722_ldo_set_voltage(struct udevice *dev, unsigned int ldo, u8 value) { - u8 value; - int err; + int ret;
if (ldo > 11) return -EINVAL;
- err = as3722_read(pmic, AS3722_LDO_CONTROL, &value); - if (err) { - error("failed to read LDO control register: %d", err); - return err; - } - - value |= 1 << ldo; - - err = as3722_write(pmic, AS3722_LDO_CONTROL, value); - if (err < 0) { - error("failed to write LDO control register: %d", err); - return err; - } - - return 0; -} - -int as3722_ldo_set_voltage(struct udevice *pmic, unsigned int ldo, u8 value) -{ - int err; - - if (ldo > 11) - return -EINVAL; - - err = as3722_write(pmic, AS3722_LDO_VOLTAGE(ldo), value); - if (err < 0) { + ret = pmic_reg_write(dev, AS3722_LDO_VOLTAGE(ldo), value); + if (ret < 0) { error("failed to write LDO%u voltage register: %d", ldo, - err); - return err; + ret); + return ret; }
return 0; }
-int as3722_gpio_configure(struct udevice *pmic, unsigned int gpio, - unsigned long flags) +static int as3722_probe(struct udevice *dev) { - u8 value = 0; - int err; + uint id, revision; + int ret;
- 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; + ret = as3722_read_id(dev, &id, &revision); + if (ret < 0) { + error("failed to read ID: %d", ret); + return ret; }
- return 0; -} - -static int as3722_gpio_set(struct udevice *pmic, unsigned int gpio, - unsigned int level) -{ - const char *l; - u8 value; - int err; - - if (gpio > 7) - return -EINVAL; - - err = as3722_read(pmic, AS3722_GPIO_SIGNAL_OUT, &value); - if (err < 0) { - error("failed to read GPIO signal out register: %d", err); - return err; - } - - if (level == 0) { - value &= ~(1 << gpio); - l = "low"; - } else { - value |= 1 << gpio; - l = "high"; + if (id != AS3722_DEVICE_ID) { + error("unknown device"); + return -ENOENT; }
- err = as3722_write(pmic, AS3722_GPIO_SIGNAL_OUT, value); - if (err) { - error("failed to set GPIO#%u %s: %d", gpio, l, err); - return err; - } + debug("AS3722 revision %#x found on I2C bus %s\n", revision, dev->name);
return 0; }
-int as3722_gpio_direction_output(struct udevice *pmic, unsigned int gpio, - unsigned int level) -{ - u8 value; - int err; - - if (gpio > 7) - return -EINVAL; +#if CONFIG_IS_ENABLED(PMIC_CHILDREN) +static const struct pmic_child_info pmic_children_info[] = { + { .prefix = "sd", .driver = "as3722_stepdown"}, + { .prefix = "ldo", .driver = "as3722_ldo"}, + { }, +};
- if (level == 0) - value = AS3722_GPIO_CONTROL_MODE_OUTPUT_VDDL; - else - value = AS3722_GPIO_CONTROL_MODE_OUTPUT_VDDH; +static int as3722_bind(struct udevice *dev) +{ + struct udevice *gpio_dev; + ofnode regulators_node; + int children; + int ret;
- err = as3722_write(pmic, AS3722_GPIO_CONTROL(gpio), value); - if (err) { - error("failed to configure GPIO#%u as output: %d", gpio, err); - return err; + regulators_node = dev_read_subnode(dev, "regulators"); + if (!ofnode_valid(regulators_node)) { + debug("%s: %s regulators subnode not found\n", __func__, + dev->name); + return -ENXIO; }
- err = as3722_gpio_set(pmic, gpio, level); - if (err < 0) { - error("failed to set GPIO#%u high: %d", gpio, err); - return err; + children = pmic_bind_children(dev, regulators_node, pmic_children_info); + if (!children) + debug("%s: %s - no child found\n", __func__, dev->name); + ret = device_bind_driver(dev, "gpio_as3722", "gpio_as3722", &gpio_dev); + if (ret) { + debug("%s: Cannot bind GPIOs (ret=%d)\n", __func__, ret); + return ret; }
return 0; } +#endif
-/* Temporary function until we get the pmic framework */ -int as3722_get(struct udevice **devp) +static int as3722_reg_count(struct udevice *dev) { - int bus = 0; - int address = 0x40; - - return i2c_get_chip_for_busnum(bus, address, 1, devp); + return AS3722_NUM_OF_REGS; }
-int as3722_init(struct udevice **devp) -{ - struct udevice *pmic; - u8 id, revision; - const unsigned int bus = 0; - const unsigned int address = 0x40; - int err; - - err = i2c_get_chip_for_busnum(bus, address, 1, &pmic); - if (err) - return err; - err = as3722_read_id(pmic, &id, &revision); - if (err < 0) { - error("failed to read ID: %d", err); - return err; - } - - if (id != AS3722_DEVICE_ID) { - error("unknown device"); - return -ENOENT; - } - - debug("AS3722 revision %#x found on I2C bus %u, address %#x\n", - revision, bus, address); - if (devp) - *devp = pmic; - - return 0; -} +static struct dm_pmic_ops as3722_ops = { + .reg_count = as3722_reg_count, + .read = as3722_read, + .write = as3722_write, +}; + +static const struct udevice_id as3722_ids[] = { + { .compatible = "ams,as3722" }, + { } +}; + +U_BOOT_DRIVER(pmic_as3722) = { + .name = "as3722_pmic", + .id = UCLASS_PMIC, + .of_match = as3722_ids, +#if CONFIG_IS_ENABLED(PMIC_CHILDREN) + .bind = as3722_bind, +#endif + .probe = as3722_probe, + .ops = &as3722_ops, +}; diff --git a/include/power/as3722.h b/include/power/as3722.h index 713e79840f..491f1b7ea7 100644 --- a/include/power/as3722.h +++ b/include/power/as3722.h @@ -7,8 +7,6 @@ #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)
@@ -21,23 +19,9 @@ #define AS3722_ASIC_ID2 0x91
#define AS3722_GPIO_CONTROL(n) (0x08 + (n)) +#define AS3722_GPIO_SIGNAL_OUT 0x20 #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)
-struct udevice; - -int as3722_init(struct udevice **devp); -int as3722_sd_enable(struct udevice *pmic, unsigned int sd); -int as3722_sd_set_voltage(struct udevice *pmic, unsigned int sd, u8 value); -int as3722_ldo_enable(struct udevice *pmic, unsigned int ldo); -int as3722_ldo_set_voltage(struct udevice *pmic, unsigned int ldo, u8 value); -int as3722_gpio_configure(struct udevice *pmic, unsigned int gpio, - unsigned long flags); -int as3722_gpio_direction_output(struct udevice *pmic, unsigned int gpio, - unsigned int level); -int as3722_read(struct udevice *pmic, u8 reg, u8 *value); -int as3722_write(struct udevice *pmic, u8 reg, u8 value); -int as3722_get(struct udevice **devp); - #endif /* __POWER_AS3722_H__ */

On Fri, 19 May 2017 08:31:03 -0600 Simon Glass sjg@chromium.org wrote:
Convert this PMIC driver to driver model and fix up other users. The regulator and GPIO functions are now handled by separate drivers.
Note that this currently breaks apalis-tk1, jetson-tk1 and cei-tk1-som. I have the middle one so will tidy that up in the next version, at least.
Reviewed-by: Lukasz Majewski lukma@denx.de
Signed-off-by: Simon Glass sjg@chromium.org
arch/arm/mach-tegra/board2.c | 6 - board/nvidia/nyan-big/nyan-big.c | 22 +-- configs/nyan-big_defconfig | 1 + drivers/power/pmic/Makefile | 2 +- drivers/power/pmic/as3722.c | 292 +++++++++++++-------------------------- include/power/as3722.h | 18 +-- 6 files changed, 114 insertions(+), 227 deletions(-)
diff --git a/arch/arm/mach-tegra/board2.c b/arch/arm/mach-tegra/board2.c index 5aedd3ef9d..0291c7fb33 100644 --- a/arch/arm/mach-tegra/board2.c +++ b/arch/arm/mach-tegra/board2.c @@ -29,7 +29,6 @@ #ifdef CONFIG_TEGRA_CLOCK_SCALING #include <asm/arch/emc.h> #endif -#include <power/as3722.h> #include "emc.h"
DECLARE_GLOBAL_DATA_PTR; @@ -142,11 +141,6 @@ int board_init(void) debug("Memory controller init failed: %d\n", err); # endif # endif /* CONFIG_TEGRA_PMU */ -#ifdef CONFIG_PMIC_AS3722
- err = as3722_init(NULL);
- if (err && err != -ENODEV)
return err;
-#endif #endif /* CONFIG_SYS_I2C_TEGRA */
#ifdef CONFIG_USB_EHCI_TEGRA diff --git a/board/nvidia/nyan-big/nyan-big.c b/board/nvidia/nyan-big/nyan-big.c index 8f68ae9fbe..54acf5418d 100644 --- a/board/nvidia/nyan-big/nyan-big.c +++ b/board/nvidia/nyan-big/nyan-big.c @@ -6,6 +6,7 @@ */
#include <common.h> +#include <dm.h> #include <errno.h> #include <asm/gpio.h> #include <asm/io.h> @@ -46,20 +47,23 @@ int tegra_board_id(void)
int tegra_lcd_pmic_init(int board_id) {
- struct udevice *pmic;
- struct udevice *dev; int ret;
- ret = as3722_get(&pmic);
- if (ret)
return -ENOENT;
- ret = uclass_get_device_by_driver(UCLASS_PMIC,
DM_GET_DRIVER(pmic_as3722), &dev);
if (ret) {
debug("%s: Failed to find PMIC\n", __func__);
return ret;
}
if (board_id == 0)
as3722_write(pmic, 0x00, 0x3c);
elsepmic_reg_write(dev, 0x00, 0x3c);
as3722_write(pmic, 0x00, 0x50);
- as3722_write(pmic, 0x12, 0x10);
- as3722_write(pmic, 0x0c, 0x07);
- as3722_write(pmic, 0x20, 0x10);
pmic_reg_write(dev, 0x00, 0x50);
pmic_reg_write(dev, 0x12, 0x10);
pmic_reg_write(dev, 0x0c, 0x07);
pmic_reg_write(dev, 0x20, 0x10);
return 0;
} diff --git a/configs/nyan-big_defconfig b/configs/nyan-big_defconfig index 22769bdc93..a152ff6915 100644 --- a/configs/nyan-big_defconfig +++ b/configs/nyan-big_defconfig @@ -47,6 +47,7 @@ CONFIG_SPI_FLASH_WINBOND=y CONFIG_DM_PMIC=y CONFIG_PMIC_AS3722=y CONFIG_DM_REGULATOR=y +CONFIG_REGULATOR_AS3722=y CONFIG_DM_REGULATOR_FIXED=y CONFIG_PWM_TEGRA=y CONFIG_SYS_NS16550=y diff --git a/drivers/power/pmic/Makefile b/drivers/power/pmic/Makefile index f409e3a0b3..76dda2a070 100644 --- a/drivers/power/pmic/Makefile +++ b/drivers/power/pmic/Makefile @@ -12,7 +12,7 @@ obj-$(CONFIG_DM_PMIC_PFUZE100) += pfuze100.o obj-$(CONFIG_PMIC_S2MPS11) += s2mps11.o obj-$(CONFIG_DM_PMIC_SANDBOX) += sandbox.o i2c_pmic_emul.o obj-$(CONFIG_PMIC_ACT8846) += act8846.o -obj-$(CONFIG_PMIC_AS3722) += as3722.o +obj-$(CONFIG_PMIC_AS3722) += as3722.o as3722_gpio.o obj-$(CONFIG_PMIC_MAX8997) += max8997.o obj-$(CONFIG_PMIC_PM8916) += pm8916.o obj-$(CONFIG_PMIC_RK8XX) += rk8xx.o diff --git a/drivers/power/pmic/as3722.c b/drivers/power/pmic/as3722.c index c09e1de06f..4efe8ee183 100644 --- a/drivers/power/pmic/as3722.c +++ b/drivers/power/pmic/as3722.c @@ -11,264 +11,168 @@ #include <errno.h> #include <fdtdec.h> #include <i2c.h>
+#include <dm/lists.h> #include <power/as3722.h> +#include <power/pmic.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
-int as3722_read(struct udevice *pmic, u8 reg, u8 *value) -{
- int err;
- err = dm_i2c_read(pmic, reg, value, 1);
- if (err < 0)
return err;
- return 0;
-} +#define AS3722_NUM_OF_REGS 0x92
-int as3722_write(struct udevice *pmic, u8 reg, u8 value) +static int as3722_read(struct udevice *dev, uint reg, uint8_t *buff, int len) {
- int err;
- int ret;
- err = dm_i2c_write(pmic, reg, &value, 1);
- if (err < 0)
return err;
ret = dm_i2c_read(dev, reg, buff, len);
if (ret < 0)
return ret;
return 0;
}
-static int as3722_read_id(struct udevice *pmic, u8 *id, u8 *revision) +static int as3722_write(struct udevice *dev, uint reg, const uint8_t *buff,
int len)
{
- int err;
- int ret;
- 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;
- }
ret = dm_i2c_write(dev, reg, buff, len);
if (ret < 0)
return ret;
return 0;
}
-int as3722_sd_enable(struct udevice *pmic, unsigned int sd) +static int as3722_read_id(struct udevice *dev, uint *idp, uint *revisionp) {
- u8 value;
- int err;
- if (sd > 6)
return -EINVAL;
- int ret;
- err = as3722_read(pmic, AS3722_SD_CONTROL, &value);
- if (err) {
error("failed to read SD control register: %d", err);
return err;
- ret = pmic_reg_read(dev, AS3722_ASIC_ID1);
- if (ret < 0) {
error("failed to read ID1 register: %d", ret);
}return ret;
- *idp = ret;
- 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;
ret = pmic_reg_read(dev, AS3722_ASIC_ID2);
if (ret < 0) {
error("failed to read ID2 register: %d", ret);
return ret;
}
*revisionp = ret;
return 0;
}
-int as3722_sd_set_voltage(struct udevice *pmic, unsigned int sd, u8 value) +/* TODO(treding@nvidia.com): Add proper regulator support to avoid this */ +int as3722_sd_set_voltage(struct udevice *dev, unsigned int sd, u8 value) {
- int err;
int ret;
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;
- ret = pmic_reg_write(dev, AS3722_SD_VOLTAGE(sd), value);
- if (ret < 0) {
error("failed to write SD%u voltage register: %d",
sd, ret);
return ret;
}
return 0;
}
-int as3722_ldo_enable(struct udevice *pmic, unsigned int ldo) +int as3722_ldo_set_voltage(struct udevice *dev, unsigned int ldo, u8 value) {
- u8 value;
- int err;
int ret;
if (ldo > 11) return -EINVAL;
- err = as3722_read(pmic, AS3722_LDO_CONTROL, &value);
- if (err) {
error("failed to read LDO control register: %d",
err);
return err;
- }
- value |= 1 << ldo;
- err = as3722_write(pmic, AS3722_LDO_CONTROL, value);
- if (err < 0) {
error("failed to write LDO control register: %d",
err);
return err;
- }
- return 0;
-}
-int as3722_ldo_set_voltage(struct udevice *pmic, unsigned int ldo, u8 value) -{
- int err;
- if (ldo > 11)
return -EINVAL;
- err = as3722_write(pmic, AS3722_LDO_VOLTAGE(ldo), value);
- if (err < 0) {
- ret = pmic_reg_write(dev, AS3722_LDO_VOLTAGE(ldo), value);
- if (ret < 0) { error("failed to write LDO%u voltage register: %d",
ldo,
err);
return err;
ret);
return ret;
}
return 0;
}
-int as3722_gpio_configure(struct udevice *pmic, unsigned int gpio,
unsigned long flags)
+static int as3722_probe(struct udevice *dev) {
- u8 value = 0;
- int err;
- uint id, revision;
- int ret;
- 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;
- ret = as3722_read_id(dev, &id, &revision);
- if (ret < 0) {
error("failed to read ID: %d", ret);
}return ret;
- return 0;
-}
-static int as3722_gpio_set(struct udevice *pmic, unsigned int gpio,
unsigned int level)
-{
- const char *l;
- u8 value;
- int err;
- if (gpio > 7)
return -EINVAL;
- err = as3722_read(pmic, AS3722_GPIO_SIGNAL_OUT, &value);
- if (err < 0) {
error("failed to read GPIO signal out register: %d",
err);
return err;
- }
- if (level == 0) {
value &= ~(1 << gpio);
l = "low";
- } else {
value |= 1 << gpio;
l = "high";
- if (id != AS3722_DEVICE_ID) {
error("unknown device");
}return -ENOENT;
- err = as3722_write(pmic, AS3722_GPIO_SIGNAL_OUT, value);
- if (err) {
error("failed to set GPIO#%u %s: %d", gpio, l, err);
return err;
- }
- debug("AS3722 revision %#x found on I2C bus %s\n", revision,
dev->name); return 0; }
-int as3722_gpio_direction_output(struct udevice *pmic, unsigned int gpio,
unsigned int level)
-{
- u8 value;
- int err;
- if (gpio > 7)
return -EINVAL;
+#if CONFIG_IS_ENABLED(PMIC_CHILDREN) +static const struct pmic_child_info pmic_children_info[] = {
- { .prefix = "sd", .driver = "as3722_stepdown"},
- { .prefix = "ldo", .driver = "as3722_ldo"},
- { },
+};
- if (level == 0)
value = AS3722_GPIO_CONTROL_MODE_OUTPUT_VDDL;
- else
value = AS3722_GPIO_CONTROL_MODE_OUTPUT_VDDH;
+static int as3722_bind(struct udevice *dev) +{
- struct udevice *gpio_dev;
- ofnode regulators_node;
- int children;
- int ret;
- err = as3722_write(pmic, AS3722_GPIO_CONTROL(gpio), value);
- if (err) {
error("failed to configure GPIO#%u as output: %d",
gpio, err);
return err;
- regulators_node = dev_read_subnode(dev, "regulators");
- if (!ofnode_valid(regulators_node)) {
debug("%s: %s regulators subnode not found\n",
__func__,
dev->name);
}return -ENXIO;
- err = as3722_gpio_set(pmic, gpio, level);
- if (err < 0) {
error("failed to set GPIO#%u high: %d", gpio, err);
return err;
- children = pmic_bind_children(dev, regulators_node,
pmic_children_info);
- if (!children)
debug("%s: %s - no child found\n", __func__,
dev->name);
- ret = device_bind_driver(dev, "gpio_as3722", "gpio_as3722",
&gpio_dev);
- if (ret) {
debug("%s: Cannot bind GPIOs (ret=%d)\n", __func__,
ret);
return ret;
}
return 0;
} +#endif
-/* Temporary function until we get the pmic framework */ -int as3722_get(struct udevice **devp) +static int as3722_reg_count(struct udevice *dev) {
- int bus = 0;
- int address = 0x40;
- return i2c_get_chip_for_busnum(bus, address, 1, devp);
- return AS3722_NUM_OF_REGS;
}
-int as3722_init(struct udevice **devp) -{
- struct udevice *pmic;
- u8 id, revision;
- const unsigned int bus = 0;
- const unsigned int address = 0x40;
- int err;
- err = i2c_get_chip_for_busnum(bus, address, 1, &pmic);
- if (err)
return err;
- err = as3722_read_id(pmic, &id, &revision);
- if (err < 0) {
error("failed to read ID: %d", err);
return err;
- }
- if (id != AS3722_DEVICE_ID) {
error("unknown device");
return -ENOENT;
- }
- debug("AS3722 revision %#x found on I2C bus %u, address
%#x\n",
revision, bus, address);
- if (devp)
*devp = pmic;
- return 0;
-} +static struct dm_pmic_ops as3722_ops = {
- .reg_count = as3722_reg_count,
- .read = as3722_read,
- .write = as3722_write,
+};
+static const struct udevice_id as3722_ids[] = {
- { .compatible = "ams,as3722" },
- { }
+};
+U_BOOT_DRIVER(pmic_as3722) = {
- .name = "as3722_pmic",
- .id = UCLASS_PMIC,
- .of_match = as3722_ids,
+#if CONFIG_IS_ENABLED(PMIC_CHILDREN)
- .bind = as3722_bind,
+#endif
- .probe = as3722_probe,
- .ops = &as3722_ops,
+}; diff --git a/include/power/as3722.h b/include/power/as3722.h index 713e79840f..491f1b7ea7 100644 --- a/include/power/as3722.h +++ b/include/power/as3722.h @@ -7,8 +7,6 @@ #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)
@@ -21,23 +19,9 @@ #define AS3722_ASIC_ID2 0x91
#define AS3722_GPIO_CONTROL(n) (0x08 + (n)) +#define AS3722_GPIO_SIGNAL_OUT 0x20 #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)
-struct udevice;
-int as3722_init(struct udevice **devp); -int as3722_sd_enable(struct udevice *pmic, unsigned int sd); -int as3722_sd_set_voltage(struct udevice *pmic, unsigned int sd, u8 value); -int as3722_ldo_enable(struct udevice *pmic, unsigned int ldo); -int as3722_ldo_set_voltage(struct udevice *pmic, unsigned int ldo, u8 value); -int as3722_gpio_configure(struct udevice *pmic, unsigned int gpio,
unsigned long flags);
-int as3722_gpio_direction_output(struct udevice *pmic, unsigned int gpio,
unsigned int level);
-int as3722_read(struct udevice *pmic, u8 reg, u8 *value); -int as3722_write(struct udevice *pmic, u8 reg, u8 value); -int as3722_get(struct udevice **devp);
#endif /* __POWER_AS3722_H__ */
Best regards,
Lukasz Majewski
--
DENX Software Engineering GmbH, Managing Director: Wolfgang Denk HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany Phone: (+49)-8142-66989-10 Fax: (+49)-8142-66989-80 Email: wd@denx.de

Update this driver to support a live device tree.
Signed-off-by: Simon Glass sjg@chromium.org ---
drivers/serial/ns16550.c | 15 +++++---------- 1 file changed, 5 insertions(+), 10 deletions(-)
diff --git a/drivers/serial/ns16550.c b/drivers/serial/ns16550.c index 52c52c1ad1..330c5e186a 100644 --- a/drivers/serial/ns16550.c +++ b/drivers/serial/ns16550.c @@ -8,7 +8,6 @@ #include <clk.h> #include <dm.h> #include <errno.h> -#include <fdtdec.h> #include <ns16550.h> #include <serial.h> #include <watchdog.h> @@ -395,7 +394,7 @@ int ns16550_serial_ofdata_to_platdata(struct udevice *dev) int err;
/* try Processor Local Bus device first */ - addr = devfdt_get_addr(dev); + addr = dev_read_addr(dev); #if defined(CONFIG_PCI) && defined(CONFIG_DM_PCI) if (addr == FDT_ADDR_T_NONE) { /* then try pci device */ @@ -434,11 +433,8 @@ int ns16550_serial_ofdata_to_platdata(struct udevice *dev) plat->base = (unsigned long)map_physmem(addr, 0, MAP_NOCACHE); #endif
- plat->reg_offset = fdtdec_get_int(gd->fdt_blob, dev_of_offset(dev), - "reg-offset", 0); - plat->reg_shift = fdtdec_get_int(gd->fdt_blob, dev_of_offset(dev), - "reg-shift", 0); - + plat->reg_offset = dev_read_u32_default(dev, "reg-offset", 0); + plat->reg_shift = dev_read_u32_default(dev, "reg-shift", 0); err = clk_get_by_index(dev, 0, &clk); if (!err) { err = clk_get_rate(&clk); @@ -450,9 +446,8 @@ int ns16550_serial_ofdata_to_platdata(struct udevice *dev) }
if (!plat->clock) - plat->clock = fdtdec_get_int(gd->fdt_blob, dev_of_offset(dev), - "clock-frequency", - CONFIG_SYS_NS16550_CLK); + plat->clock = dev_read_u32_default(dev, "clock-frequency", + CONFIG_SYS_NS16550_CLK); if (!plat->clock) { debug("ns16550 clock not defined\n"); return -EINVAL;

This function is quite long. Move the core code into a separate function in preparation for adding livetree support.
Signed-off-by: Simon Glass sjg@chromium.org ---
drivers/serial/serial-uclass.c | 84 ++++++++++++++++++++++-------------------- 1 file changed, 44 insertions(+), 40 deletions(-)
diff --git a/drivers/serial/serial-uclass.c b/drivers/serial/serial-uclass.c index a9c4f89e1a..ede5c2c0be 100644 --- a/drivers/serial/serial-uclass.c +++ b/drivers/serial/serial-uclass.c @@ -8,7 +8,6 @@ #include <dm.h> #include <environment.h> #include <errno.h> -#include <fdtdec.h> #include <os.h> #include <serial.h> #include <stdio_dev.h> @@ -27,11 +26,53 @@ static const unsigned long baudrate_table[] = CONFIG_SYS_BAUDRATE_TABLE; #error "Serial is required before relocation - define CONFIG_SYS_MALLOC_F_LEN to make this work" #endif
+static int serial_check_stdout(const void *blob, struct udevice **devp) +{ + int node; + + /* Check for a chosen console */ + node = fdtdec_get_chosen_node(blob, "stdout-path"); + if (node < 0) { + const char *str, *p, *name; + + /* + * Deal with things like + * stdout-path = "serial0:115200n8"; + * + * We need to look up the alias and then follow it to the + * correct node. + */ + str = fdtdec_get_chosen_prop(blob, "stdout-path"); + if (str) { + p = strchr(str, ':'); + name = fdt_get_alias_namelen(blob, str, + p ? p - str : strlen(str)); + if (name) + node = fdt_path_offset(blob, name); + } + } + if (node < 0) + node = fdt_path_offset(blob, "console"); + if (!uclass_get_device_by_of_offset(UCLASS_SERIAL, node, devp)) + return 0; + + /* + * If the console is not marked to be bound before relocation, bind it + * anyway. + */ + if (node > 0 && !lists_bind_fdt(gd->dm_root, offset_to_ofnode(node), + devp)) { + if (!device_probe(*devp)) + return 0; + } + + return -ENODEV; +} + static void serial_find_console_or_panic(void) { const void *blob = gd->fdt_blob; struct udevice *dev; - int node;
if (CONFIG_IS_ENABLED(OF_PLATDATA)) { uclass_first_device(UCLASS_SERIAL, &dev); @@ -40,47 +81,10 @@ static void serial_find_console_or_panic(void) return; } } else if (CONFIG_IS_ENABLED(OF_CONTROL) && blob) { - /* Check for a chosen console */ - node = fdtdec_get_chosen_node(blob, "stdout-path"); - if (node < 0) { - const char *str, *p, *name; - - /* - * Deal with things like - * stdout-path = "serial0:115200n8"; - * - * We need to look up the alias and then follow it to - * the correct node. - */ - str = fdtdec_get_chosen_prop(blob, "stdout-path"); - if (str) { - p = strchr(str, ':'); - name = fdt_get_alias_namelen(blob, str, - p ? p - str : strlen(str)); - if (name) - node = fdt_path_offset(blob, name); - } - } - if (node < 0) - node = fdt_path_offset(blob, "console"); - if (!uclass_get_device_by_of_offset(UCLASS_SERIAL, node, - &dev)) { + if (!serial_check_stdout(blob, &dev)) { gd->cur_serial_dev = dev; return; } - - /* - * If the console is not marked to be bound before relocation, - * bind it anyway. - */ - if (node > 0 && - !lists_bind_fdt(gd->dm_root, offset_to_ofnode(node), - &dev)) { - if (!device_probe(dev)) { - gd->cur_serial_dev = dev; - return; - } - } } if (!SPL_BUILD || !CONFIG_IS_ENABLED(OF_CONTROL) || !blob) { /*

Add support for a live device tree to the core serial uclass.
Signed-off-by: Simon Glass sjg@chromium.org ---
drivers/serial/serial-uclass.c | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-)
diff --git a/drivers/serial/serial-uclass.c b/drivers/serial/serial-uclass.c index ede5c2c0be..976b99ce7c 100644 --- a/drivers/serial/serial-uclass.c +++ b/drivers/serial/serial-uclass.c @@ -14,6 +14,7 @@ #include <watchdog.h> #include <dm/lists.h> #include <dm/device-internal.h> +#include <dm/of_access.h>
DECLARE_GLOBAL_DATA_PTR;
@@ -81,9 +82,20 @@ static void serial_find_console_or_panic(void) return; } } else if (CONFIG_IS_ENABLED(OF_CONTROL) && blob) { - if (!serial_check_stdout(blob, &dev)) { - gd->cur_serial_dev = dev; - return; + /* Live tree has support for stdout */ + if (of_live_active()) { + struct device_node *np = of_get_stdout(); + + if (np && !uclass_get_device_by_ofnode(UCLASS_SERIAL, + np_to_ofnode(np), &dev)) { + gd->cur_serial_dev = dev; + return; + } + } else { + if (!serial_check_stdout(blob, &dev)) { + gd->cur_serial_dev = dev; + return; + } } } if (!SPL_BUILD || !CONFIG_IS_ENABLED(OF_CONTROL) || !blob) {

This error condition should have a debug() message. Add it.
Signed-off-by: Simon Glass sjg@chromium.org ---
arch/arm/mach-tegra/board2.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/arch/arm/mach-tegra/board2.c b/arch/arm/mach-tegra/board2.c index 0291c7fb33..e0a39e1a32 100644 --- a/arch/arm/mach-tegra/board2.c +++ b/arch/arm/mach-tegra/board2.c @@ -150,8 +150,10 @@ int board_init(void) #if defined(CONFIG_DM_VIDEO) board_id = tegra_board_id(); err = tegra_lcd_pmic_init(board_id); - if (err) + if (err) { + debug("Failed to set up LCD PMIC\n"); return err; + } #endif
#ifdef CONFIG_TEGRA_NAND

These are not needed now since the drivers now use driver model. Drop them.
Signed-off-by: Simon Glass sjg@chromium.org ---
include/fdtdec.h | 6 ------ lib/fdtdec.c | 6 ------ 2 files changed, 12 deletions(-)
diff --git a/include/fdtdec.h b/include/fdtdec.h index eda2ffaf66..4a0947c626 100644 --- a/include/fdtdec.h +++ b/include/fdtdec.h @@ -119,12 +119,6 @@ enum fdt_compat_id { COMPAT_NVIDIA_TEGRA20_EMC, /* Tegra20 memory controller */ COMPAT_NVIDIA_TEGRA20_EMC_TABLE, /* Tegra20 memory timing table */ COMPAT_NVIDIA_TEGRA20_NAND, /* Tegra2 NAND controller */ - COMPAT_NVIDIA_TEGRA124_PMC, /* Tegra 124 power mgmt controller */ - COMPAT_NVIDIA_TEGRA186_SDMMC, /* Tegra186 SDMMC controller */ - COMPAT_NVIDIA_TEGRA210_SDMMC, /* Tegra210 SDMMC controller */ - COMPAT_NVIDIA_TEGRA124_SDMMC, /* Tegra124 SDMMC controller */ - COMPAT_NVIDIA_TEGRA30_SDMMC, /* Tegra30 SDMMC controller */ - COMPAT_NVIDIA_TEGRA20_SDMMC, /* Tegra20 SDMMC controller */ COMPAT_NVIDIA_TEGRA124_XUSB_PADCTL, /* Tegra124 XUSB pad controller */ COMPAT_NVIDIA_TEGRA210_XUSB_PADCTL, diff --git a/lib/fdtdec.c b/lib/fdtdec.c index 91503b8cb9..9818f78c51 100644 --- a/lib/fdtdec.c +++ b/lib/fdtdec.c @@ -33,12 +33,6 @@ static const char * const compat_names[COMPAT_COUNT] = { COMPAT(NVIDIA_TEGRA20_EMC, "nvidia,tegra20-emc"), COMPAT(NVIDIA_TEGRA20_EMC_TABLE, "nvidia,tegra20-emc-table"), COMPAT(NVIDIA_TEGRA20_NAND, "nvidia,tegra20-nand"), - COMPAT(NVIDIA_TEGRA124_PMC, "nvidia,tegra124-pmc"), - COMPAT(NVIDIA_TEGRA186_SDMMC, "nvidia,tegra186-sdhci"), - COMPAT(NVIDIA_TEGRA210_SDMMC, "nvidia,tegra210-sdhci"), - COMPAT(NVIDIA_TEGRA124_SDMMC, "nvidia,tegra124-sdhci"), - COMPAT(NVIDIA_TEGRA30_SDMMC, "nvidia,tegra30-sdhci"), - COMPAT(NVIDIA_TEGRA20_SDMMC, "nvidia,tegra20-sdhci"), COMPAT(NVIDIA_TEGRA124_XUSB_PADCTL, "nvidia,tegra124-xusb-padctl"), COMPAT(NVIDIA_TEGRA210_XUSB_PADCTL, "nvidia,tegra210-xusb-padctl"), COMPAT(SMSC_LAN9215, "smsc,lan9215"),

Change this board to use a live device tree after relocation.
Signed-off-by: Simon Glass sjg@chromium.org ---
configs/nyan-big_defconfig | 1 + 1 file changed, 1 insertion(+)
diff --git a/configs/nyan-big_defconfig b/configs/nyan-big_defconfig index a152ff6915..82be85a834 100644 --- a/configs/nyan-big_defconfig +++ b/configs/nyan-big_defconfig @@ -33,6 +33,7 @@ CONFIG_CMD_EXT4_WRITE=y # CONFIG_SPL_DOS_PARTITION is not set # CONFIG_SPL_ISO_PARTITION is not set # CONFIG_SPL_EFI_PARTITION is not set +CONFIG_OF_LIVE=y CONFIG_SPL_DM=y CONFIG_REGMAP=y CONFIG_SYSCON=y

Hi Simon
On Fri, 2017-05-19 at 08:31 -0600, Simon Glass wrote:
Change this board to use a live device tree after relocation.
Signed-off-by: Simon Glass sjg@chromium.org
configs/nyan-big_defconfig | 1 + 1 file changed, 1 insertion(+)
diff --git a/configs/nyan-big_defconfig b/configs/nyan-big_defconfig index a152ff6915..82be85a834 100644 --- a/configs/nyan-big_defconfig +++ b/configs/nyan-big_defconfig @@ -33,6 +33,7 @@ CONFIG_CMD_EXT4_WRITE=y # CONFIG_SPL_DOS_PARTITION is not set # CONFIG_SPL_ISO_PARTITION is not set # CONFIG_SPL_EFI_PARTITION is not set +CONFIG_OF_LIVE=y CONFIG_SPL_DM=y CONFIG_REGMAP=y CONFIG_SYSCON=y
Doing the same on dm/master for Apalis TK1 gives me the following:
U-Boot 2017.05-00795-g40fcab4-dirty (May 29 2017 - 16:52:17 +0200)
TEGRA124 DRAM: 2 GiB Error binding driver 'gpio_tegra': -22 Some drivers failed to bind initcall sequence fffad294 failed at call 80124360 (err=-22) ### ERROR ### Please RESET the board ###
Do you happen to know what may go wrong here?
I do actually even own a nyan-big but so far never run any mainline stuff on it as I am missing Servo and/or Yoshi et. al.
Is there any particular reason you did not do this on a more accessible platform like e.g. Jetson TK1?
BTW: The same happens on Jetson TK1 once I enable live tree:
U-Boot SPL 2017.05-00795-g40fcab4-dirty (May 29 2017 - 17:03:18) Trying to boot from RAM
U-Boot 2017.05-00795-g40fcab4-dirty (May 29 2017 - 17:03:18 +0200)
TEGRA124 Model: NVIDIA Jetson TK1 Board: NVIDIA Jetson TK1 DRAM: 2 GiB Error binding driver 'gpio_tegra': -22 Some drivers failed to bind initcall sequence fffa8ba4 failed at call 801235b8 (err=-22) ### ERROR ### Please RESET the board ###
Cheers
Marcel

Hi Marcel,
On 29 May 2017 at 09:08, Marcel Ziswiler marcel.ziswiler@toradex.com wrote:
Hi Simon
On Fri, 2017-05-19 at 08:31 -0600, Simon Glass wrote:
Change this board to use a live device tree after relocation.
Signed-off-by: Simon Glass sjg@chromium.org
configs/nyan-big_defconfig | 1 + 1 file changed, 1 insertion(+)
diff --git a/configs/nyan-big_defconfig b/configs/nyan-big_defconfig index a152ff6915..82be85a834 100644 --- a/configs/nyan-big_defconfig +++ b/configs/nyan-big_defconfig @@ -33,6 +33,7 @@ CONFIG_CMD_EXT4_WRITE=y # CONFIG_SPL_DOS_PARTITION is not set # CONFIG_SPL_ISO_PARTITION is not set # CONFIG_SPL_EFI_PARTITION is not set +CONFIG_OF_LIVE=y CONFIG_SPL_DM=y CONFIG_REGMAP=y CONFIG_SYSCON=y
Doing the same on dm/master for Apalis TK1 gives me the following:
U-Boot 2017.05-00795-g40fcab4-dirty (May 29 2017 - 16:52:17 +0200)
TEGRA124 DRAM: 2 GiB Error binding driver 'gpio_tegra': -22 Some drivers failed to bind initcall sequence fffad294 failed at call 80124360 (err=-22) ### ERROR ### Please RESET the board ###
Do you happen to know what may go wrong here?
Not really. Can you diagnose it? I suspect it is in gpio_tegra_bind().
I do actually even own a nyan-big but so far never run any mainline stuff on it as I am missing Servo and/or Yoshi et. al.
Sure. I did send a chain series (u-boot-dm/chain-working) which allows it to run without those.
Is there any particular reason you did not do this on a more accessible platform like e.g. Jetson TK1?
I do have one of those boards, but unfortunately I cannot find it. I'm hoping to track it down in the next month or so.
BTW: The same happens on Jetson TK1 once I enable live tree:
U-Boot SPL 2017.05-00795-g40fcab4-dirty (May 29 2017 - 17:03:18) Trying to boot from RAM
U-Boot 2017.05-00795-g40fcab4-dirty (May 29 2017 - 17:03:18 +0200)
TEGRA124 Model: NVIDIA Jetson TK1 Board: NVIDIA Jetson TK1 DRAM: 2 GiB Error binding driver 'gpio_tegra': -22 Some drivers failed to bind initcall sequence fffa8ba4 failed at call 801235b8 (err=-22) ### ERROR ### Please RESET the board ###
Cheers
Marcel
Thank you for testing. I do have a beaver as well so may be able to repeat it on that.
Regards, Simon

On Fri, May 19, 2017 at 08:30:43AM -0600, Simon Glass wrote:
This moves an entire board to use a live device tree as an example of the impact.
Nyan-big was chosen because I can easily and boot U-Boot without any media swapping, etc.
Total code size impact on this board is approximately 9KB on U-Boot and 64 bytes on SPL:
27: dm: tegra: nyan-big: Move to livetree arm: (for 1/1 boards) all +9264.0 bss -16.0 data +44.0 rodata +92.0 spl/u-boot-spl:all +326.0 spl/u-boot-spl:rodata +262.0 spl/u-boot-spl:text +64.0 text +9144.0
Tegra does not use Thumb2, which would likely reduce the code size by about 25%, indicating a code-size impact of perhaps 7KB.
So, did your buildman output get messed up in the copy/paste? I see both of the numbers you're saying, but it's all vs u-boot-spl. The 64 bytes in SPL sounds good.
I have not yet collected reliable detailed timing information. I will do that with the next version of this series, after comments are received. I expect that building the live tree will take a little time, and that using it will be very slightly faster.
I assume that you're in the process of rectifying this with the bootstage patches you posted but FWIW I still use http://elinux.org/Grabserial as my first weapon-of-choice in these kinds of things.

Hi Tom,
On 22 May 2017 at 16:15, Tom Rini trini@konsulko.com wrote:
On Fri, May 19, 2017 at 08:30:43AM -0600, Simon Glass wrote:
This moves an entire board to use a live device tree as an example of the impact.
Nyan-big was chosen because I can easily and boot U-Boot without any media swapping, etc.
Total code size impact on this board is approximately 9KB on U-Boot and 64 bytes on SPL:
27: dm: tegra: nyan-big: Move to livetree arm: (for 1/1 boards) all +9264.0 bss -16.0 data +44.0 rodata +92.0 spl/u-boot-spl:all +326.0 spl/u-boot-spl:rodata +262.0 spl/u-boot-spl:text +64.0 text +9144.0
Tegra does not use Thumb2, which would likely reduce the code size by about 25%, indicating a code-size impact of perhaps 7KB.
So, did your buildman output get messed up in the copy/paste? I see both of the numbers you're saying, but it's all vs u-boot-spl. The 64 bytes in SPL sounds good.
I think this is right. See 'text +9144.0' which means 9KB of extra in ARM (not Thumb).
I have not yet collected reliable detailed timing information. I will do that with the next version of this series, after comments are received. I expect that building the live tree will take a little time, and that using it will be very slightly faster.
I assume that you're in the process of rectifying this with the bootstage patches you posted but FWIW I still use http://elinux.org/Grabserial as my first weapon-of-choice in these kinds of things.
Fair enough, but it's hard to measure down to milliseconds isn't it? Also, outputting text affects the timing.
Yes I have completed the timing. Sneak preview...the times above are times to start up driver model at each stage, in microseconds:
Boot time is affected slightly. For nyan-big the times with flat tree are:
2,108 dm_r 7,924 dm_spl 120,724 dm_f 171,816 lcd
With the livetree:
721 dm_r 3,764 of_live 7,990 dm_spl 120,736 dm_f 168,215 lcd
As expected the spl and pre-relocation times are not affected. In the post-relocation case, the live tree must be built, which here takes about 3.8ms. Driver-model device creation takes a bit of 1ms less time with the livetree, so all up the cost is about 2.4ms. After DM init there appears to be a slight reduction in the time taken to set up devices (from 327ms to 319ms) so overall the live tree does not appear to be any slower. This is because pre-parsing the device tree makes reading it later faster.
Regards, Simon
participants (5)
-
Anatolij Gustschin
-
Lukasz Majewski
-
Marcel Ziswiler
-
Simon Glass
-
Tom Rini