Skip to contentSkip to conversation

dm: Introduce new driver model uclasses

PATCH Superseded Simon Glass 10 participants 133 messages Jun 23, 2015 – Aug 11, 2015

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

v3 cover dm: Introduce new driver model uclasses

This series adds several new uclasses. Some of these have been discussed for a while. All are fairly simple and just provide enough functionality for existing use cases. The following are included in this series:

- Clocks - setting and getting PLL and peripheral clocks
- Pinctrl - adjusting pin multiplexing settings
- Reset - reseting the board or SoC
- RAM - setting up RAM controllers and detecting the available RAM
- MMC - MMC controllers (using the existing block device framework)
- LEDs - turning LEDs on and off, with only a GPIO driver so far

Trivial support is also added for regmap and syscon controllers, modelled on how the kernel does this.

This builds on the SPL device tree support which was recently added.

One problem with device tree is that U-Boot has no way of dropping features it does not need or use. For SPL this problem needs to be solved and this series uses a new 'fdtgrep' tool for this. The 45KB Firefly device tree reduces to a 6KB bytes when unused material is removed. SDRAM timings are also in the device tree.

This series includes some changes aimed at reduce code size in SPL, including:
- dropping alias sequence support (the aliases node) since many boards just use a single UART in SPL
- adding a smaller panic() function that does not support printf()-format strings
- removing device unbind code which will never be used in SPL

Changes in v3:
- Use case-insensitve compare for image params (fixes build break with m53evk)
- Fix indentation in function comment
- Convert hex number to upper case to keep bc happy
- Split this series apart from the Rockchip series

Changes in v2:
- Add new patch to remove unused strings from a device tree
- Add new patch with fdt_first/next_region() functions
- Tidy up commit message a little
- Add new patch with fdtgrep tool
- Add new patch to reduce SPL device tree size with fdtgrep

Simon Glass (54):
Add a dhrystone benchmark command
sandbox: Enable dhry command
mkimage: Display a better list of available image types
fdt: Add a function to remove unused strings from a device tree
fdt: Add fdt_first/next_region() functions
fdt: Add fdtgrep tool
dm: Reduce SPL device tree size
dm: arm: Put driver model I2C drivers before legacy ones Add a way of checking the position of a structure member
debug_uart: Remove use of asmlinkage
dm: Allow debug UART to support an early console
sandbox: Drop special-case sandbox console code
dm: Move the tree/uclass dump code into its own file
dm: core: Use debug() instead of printf() for failures
dm: core: Add a function to find any device from device tree
dm: core: Correct device_get_child_by_of_offset() parameter
dm: gpio: Allow GPIO uclass to be used in SPL
dm: gpio: Add dm_gpio_lookup_name() to look up a GPIO name
dm: gpio: Add dm_gpio_request() to manually request a GPIO
dm: Add support for register maps (regmap)
dm: Add support for generic system controllers (syscon)
dm: Correct the missing method check in cpu_get_info()
dm: Add support for LEDs
dm: led: Add a driver for GPIO-controlled LEDs
spl: Add debugging info for spl_mmc boot
dm: mmc: Add an MMC uclass
mmc: Avoid using printf() for errors
mmc: Add debug() output on read errors
dm: mmc: Allow driver model to be used for MMC in SPL
mmc: Add structure comments for dwmmc
mmc: Support bypass mode with the get_mmc_clk() method
mmc: Calculate dwmmc FIFO threshold size if not provided
dm: Add basic support for pin multiplexing (pinctrl)
dm: power: Avoid case-insensitve match for child names
dm: power: Add regulator flags to centralise auto-set logic
dm: pmic: Split output from function
dm: power: Add a function to set up all regulators
dm: power: Use debug() for errors in regulator uclass
dm: pmic: Add functions to adjust PMIC registers
dm: power: Allow use of regulators in SPL
Drop CONFIG_ERRNO_STR from SPL
dm: Add support for RAM drivers
dm: spi: Make local functions static
ns16550: Improve debug UART so it can work with 32-bit access Add rivest cipher 4 (rc4) implementation
lib: Add function to extract a number from the end of a string
fdt: Provide debug info when a device tree cannot be found
dm: spl: Allow device tree/driver model in board_init_f()
spl: Add a debug string before the jump to U-Boot
mkimage: Set up a file size parameter and keep it updated
dm: Add a system reset uclass
zynq: Rename struct clk_ops to zynq_clk_ops
dm: Add a clock uclass
power: pmic: Use trailing_strtol() instead of a local function

 Makefile                                    |    2 +-
 arch/arm/cpu/u-boot-spl.lds                 |   12 +-
 arch/arm/mach-zynq/clk.c                    |    6 +-
 common/console.c                            |   25 +-
 common/image.c                              |   58 +-
 common/spl/spl.c                            |   36 +-
 common/spl/spl_mmc.c                        |   26 +-
 configs/sandbox_defconfig                   |    1 +
 doc/device-tree-bindings/leds/common.txt    |   23 +
 doc/device-tree-bindings/leds/leds-gpio.txt |   52 ++
 drivers/Kconfig                             |    8 +
 drivers/Makefile                            |    4 +
 drivers/clk/Kconfig                         |   19 +
 drivers/clk/Makefile                        |    8 +
 drivers/clk/clk-uclass.c                    |   58 ++
 drivers/core/Makefile                       |    3 +
 drivers/core/device.c                       |   29 +-
 drivers/core/dump.c                         |   96 +++
 drivers/core/lists.c                        |    6 +-
 drivers/core/regmap.c                       |   86 ++
 drivers/core/syscon-uclass.c                |   73 ++
 drivers/cpu/cpu-uclass.c                    |    2 +-
 drivers/gpio/Makefile                       |    4 -
 drivers/gpio/gpio-uclass.c                  |   36 +-
 drivers/led/Kconfig                         |   26 +
 drivers/led/Makefile                        |    9 +
 drivers/led/led-uclass.c                    |   48 ++
 drivers/led/led_gpio.c                      |  101 +++
 drivers/misc/Kconfig                        |    9 +
 drivers/misc/Makefile                       |    1 +
 drivers/misc/reset-uclass.c                 |   62 ++
 drivers/mmc/Kconfig                         |   10 +
 drivers/mmc/Makefile                        |    2 +
 drivers/mmc/dw_mmc.c                        |   33 +-
 drivers/mmc/exynos_dw_mmc.c                 |    2 +-
 drivers/mmc/mmc-uclass.c                    |   34 +
 drivers/mmc/mmc.c                           |   10 +-
 drivers/pinctrl/Kconfig                     |   19 +
 drivers/pinctrl/Makefile                    |    8 +
 drivers/pinctrl/pinctrl-uclass.c            |   51 ++
 drivers/power/pmic/pmic-uclass.c            |   57 +-
 drivers/power/regulator/regulator-uclass.c  |  134 +--
 drivers/ram/Kconfig                         |   18 +
 drivers/ram/Makefile                        |    7 +
 drivers/ram/ram-uclass.c                    |   28 +
 drivers/serial/ns16550.c                    |   36 +-
 drivers/spi/spi-uclass.c                    |    8 +-
 dts/Kconfig                                 |   12 +
 include/asm-generic/global_data.h           |    1 +
 include/asm-generic/gpio.h                  |   25 +
 include/clk.h                               |   80 ++
 include/common.h                            |   11 +
 include/debug_uart.h                        |   22 +-
 include/dm/device.h                         |   16 +-
 include/dm/uclass-id.h                      |    7 +
 include/dm/util.h                           |    6 +
 include/dwmmc.h                             |   34 +-
 include/image.h                             |   11 +
 include/led.h                               |   51 ++
 include/libfdt.h                            |  256 +++++-
 include/mmc.h                               |   22 +
 include/pinctrl.h                           |   74 ++
 include/power/pmic.h                        |   34 +
 include/power/regulator.h                   |   53 +-
 include/power/sandbox_pmic.h                |    4 +-
 include/ram.h                               |   38 +
 include/rc4.h                               |   21 +
 include/regmap.h                            |   72 ++
 include/reset.h                             |   62 ++
 include/spl.h                               |   12 +
 include/syscon.h                            |   56 ++
 include/vsprintf.h                          |   26 +
 lib/Kconfig                                 |    2 +
 lib/Makefile                                |    5 +-
 lib/dhry/Kconfig                            |    7 +
 lib/dhry/Makefile                           |    7 +
 lib/dhry/cmd_dhry.c                         |   34 +
 lib/dhry/dhry.h                             |  442 ++++++++++
 lib/dhry/dhry_1.c                           |  421 +++++++++
 lib/dhry/dhry_2.c                           |  217 +++++
 lib/fdtdec.c                                |   21 +-
 lib/libfdt/Makefile                         |    2 +-
 lib/libfdt/fdt_region.c                     |  492 +++++++++++
 lib/libfdt/fdt_rw.c                         |   32 +
 lib/rc4.c                                   |   49 ++
 lib/vsprintf.c                              |   19 +
 scripts/Makefile.spl                        |   33 +
 test/dm/cmd_dm.c                            |   82 +-
 test/dm/regulator.c                         |    2 +-
 tools/Makefile                              |    6 +-
 tools/fdtgrep.c                             | 1234 +++++++++++++++++++++++++++
 tools/imagetool.h                           |    1 +
 tools/mkimage.c                             |   77 +-
 93 files changed, 5259 insertions(+), 318 deletions(-)
 create mode 100644 doc/device-tree-bindings/leds/common.txt
 create mode 100644 doc/device-tree-bindings/leds/leds-gpio.txt
 create mode 100644 drivers/clk/Kconfig
 create mode 100644 drivers/clk/Makefile
 create mode 100644 drivers/clk/clk-uclass.c
 create mode 100644 drivers/core/dump.c
 create mode 100644 drivers/core/regmap.c
 create mode 100644 drivers/core/syscon-uclass.c
 create mode 100644 drivers/led/Kconfig
 create mode 100644 drivers/led/Makefile
 create mode 100644 drivers/led/led-uclass.c
 create mode 100644 drivers/led/led_gpio.c
 create mode 100644 drivers/misc/reset-uclass.c
 create mode 100644 drivers/mmc/mmc-uclass.c
 create mode 100644 drivers/pinctrl/Kconfig
 create mode 100644 drivers/pinctrl/Makefile
 create mode 100644 drivers/pinctrl/pinctrl-uclass.c
 create mode 100644 drivers/ram/Kconfig
 create mode 100644 drivers/ram/Makefile
 create mode 100644 drivers/ram/ram-uclass.c
 create mode 100644 include/led.h
 create mode 100644 include/pinctrl.h
 create mode 100644 include/ram.h
 create mode 100644 include/rc4.h
 create mode 100644 include/regmap.h
 create mode 100644 include/reset.h
 create mode 100644 include/syscon.h
 create mode 100644 lib/dhry/Kconfig
 create mode 100644 lib/dhry/Makefile
 create mode 100644 lib/dhry/cmd_dhry.c
 create mode 100644 lib/dhry/dhry.h
 create mode 100644 lib/dhry/dhry_1.c
 create mode 100644 lib/dhry/dhry_2.c
 create mode 100644 lib/libfdt/fdt_region.c
 create mode 100644 lib/rc4.c
 create mode 100644 tools/fdtgrep.c
Signature · 1 line
2.4.3.573.g4eafbef
#1 lore raw

PATCH v3 1/54 Add a dhrystone benchmark command

Drystone provides a convenient sanity check that the CPU is running at full speed. Add this as a command which can be enabled as needed.

Note: I investigated using Coremark for this but there was a license agreement and I could not work out if it was GPL-compatible.

---

Changes in v3: None
Changes in v2: None

 lib/Kconfig         |   2 +
 lib/Makefile        |   2 +
 lib/dhry/Kconfig    |   7 +
 lib/dhry/Makefile   |   7 +
 lib/dhry/cmd_dhry.c |  34 ++++
 lib/dhry/dhry.h     | 442 ++++++++++++++++++++++++++++++++++++++++++++++++++++
 lib/dhry/dhry_1.c   | 421 +++++++++++++++++++++++++++++++++++++++++++++++++
 lib/dhry/dhry_2.c   | 217 ++++++++++++++++++++++++++
 8 files changed, 1132 insertions(+)
 create mode 100644 lib/dhry/Kconfig
 create mode 100644 lib/dhry/Makefile
 create mode 100644 lib/dhry/cmd_dhry.c
 create mode 100644 lib/dhry/dhry.h
 create mode 100644 lib/dhry/dhry_1.c
 create mode 100644 lib/dhry/dhry_2.c
lib/Kconfig +2 -0
index 7ec8c98..f75dff1 100644
@@ -49,6 +49,8 @@ config LIB_RAND
 	help
 	  This library provides pseudo-random number generator functions.
 
+source lib/dhry/Kconfig
+
 source lib/rsa/Kconfig
 
 menu "Hashing Support"
lib/Makefile +2 -0
index 97ed398..ca72187 100644
@@ -15,6 +15,8 @@ obj-$(CONFIG_BZIP2) += bzip2/
 obj-$(CONFIG_TIZEN) += tizen/
 obj-$(CONFIG_OF_LIBFDT) += libfdt/
 obj-$(CONFIG_FIT) += libfdt/
+obj-$(CONFIG_FIT) += libfdt/
+obj-$(CONFIG_CMD_DHRYSTONE) += dhry/
 
 obj-$(CONFIG_AES) += aes.o
 obj-$(CONFIG_USB_TTY) += circbuf.o
lib/dhry/Kconfig new file +7 -0
new file mode 100644
index 0000000..641b806
@@ -0,0 +1,7 @@
+config CMD_DHRYSTONE
+	bool "Support the 'dhry' command to run the dhrystone benchmark"
+	help
+	  Dhrystone is an old benchmark in the public domain that gives a
+	  rough idea of CPU performance. This enables a 'dhry' command
+	  which runs this benchmark within U-Boot and reports the performance.
+	  The number of 'Dhrystone MIPS' is also reported.
lib/dhry/Makefile new file +7 -0
new file mode 100644
index 0000000..926c0d6
@@ -0,0 +1,7 @@
+#
+# Copyright (c) 2015 Google, Inc
+#
+# SPDX-License-Identifier:	GPL-2.0+
+#
+
+obj-y += cmd_dhry.o dhry_1.o dhry_2.o
lib/dhry/cmd_dhry.c new file +34 -0
new file mode 100644
index 0000000..5dc191e
@@ -0,0 +1,34 @@
+/*
+ * (C) Copyright 2015 Google, Inc
+ *
+ * SPDX-License-Identifier:     GPL-2.0+
+ */
+
+#include <common.h>
+#include <command.h>
+#include "dhry.h"
+
+static int do_dhry(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
+{
+	ulong start, duration, dhry_per_sec, vax_mips;
+	int iterations = 1000000;
+
+	if (argc > 1)
+		iterations = simple_strtoul(argv[1], NULL, 10);
+
+	start = get_timer(0);
+	dhry(iterations);
+	duration = get_timer(start);
+	dhry_per_sec = iterations * 1000 / duration;
+	vax_mips = dhry_per_sec / 1757;
+	printf("%d iterations in %lu ms: %lu/s, %lu DMIPS\n", iterations,
+	       duration, dhry_per_sec, vax_mips);
+
+	return 0;
+}
+
+U_BOOT_CMD(
+	dhry,	2,	1,	do_dhry,
+	"[iterations] - run dhrystone benchmark",
+	"\n    - run the Dhrystone 2.1 benchmark, a rough measure of CPU speed\n"
+);
lib/dhry/dhry.h new file +442 -0

442 lines not on this page · raw message

lib/dhry/dhry_1.c new file +421 -0

421 lines not on this page · raw message

lib/dhry/dhry_2.c new file +217 -0

217 lines not on this page · raw message

Signature · 1 line
2.4.3.573.g4eafbef
#2 lore raw

PATCH v3 1/54 Add a dhrystone benchmark command

Quoted 13 lines · Simon Glass

Drystone provides a convenient sanity check that the CPU is running at full speed. Add this as a command which can be enabled as needed.

Note: I investigated using Coremark for this but there was a license agreement and I could not work out if it was GPL-compatible.

---

Changes in v3: None
Changes in v2: None

Quoted 15 lines
 lib/Kconfig         |   2 +
 lib/Makefile        |   2 +
 lib/dhry/Kconfig    |   7 +
 lib/dhry/Makefile   |   7 +
 lib/dhry/cmd_dhry.c |  34 ++++
 lib/dhry/dhry.h     | 442 ++++++++++++++++++++++++++++++++++++++++++++++++++++
 lib/dhry/dhry_1.c   | 421 +++++++++++++++++++++++++++++++++++++++++++++++++
 lib/dhry/dhry_2.c   | 217 ++++++++++++++++++++++++++
 8 files changed, 1132 insertions(+)
 create mode 100644 lib/dhry/Kconfig
 create mode 100644 lib/dhry/Makefile
 create mode 100644 lib/dhry/cmd_dhry.c
 create mode 100644 lib/dhry/dhry.h
 create mode 100644 lib/dhry/dhry_1.c
 create mode 100644 lib/dhry/dhry_2.c

Applied to u-boot-dm.

#3 lore raw

PATCH v3 2/54 sandbox: Enable dhry command

In reply to Simon Glass

Provide access to the dhrystone benchmark command.

---

Changes in v3: None
Changes in v2: None

 configs/sandbox_defconfig | 1 +
 1 file changed, 1 insertion(+)
configs/sandbox_defconfig +1 -0
index 31fe2f9..3953ec3 100644
@@ -19,6 +19,7 @@ CONFIG_DM_PCI=y
 CONFIG_PCI_SANDBOX=y
 CONFIG_SPI_FLASH_SANDBOX=y
 CONFIG_CMD_CROS_EC=y
+CONFIG_CMD_DHRYSTONE=y
 CONFIG_CROS_EC=y
 CONFIG_CROS_EC_SANDBOX=y
 CONFIG_CROS_EC_KEYB=y
Signature · 1 line
2.4.3.573.g4eafbef
#4 lore raw

PATCH v3 2/54 sandbox: Enable dhry command

Quoted 10 lines · Simon Glass

Provide access to the dhrystone benchmark command.

---

Changes in v3: None
Changes in v2: None

 configs/sandbox_defconfig | 1 +
 1 file changed, 1 insertion(+)

Applied to u-boot-dm.

#5 lore raw

PATCH v3 3/54 mkimage: Display a better list of available image types

In reply to Simon Glass

Offer to display the available image types in help. Also, rather than hacking the genimg_get_type_id() function to display a list of types, do this in the tool. Also, sort the list.

The list of image types is quite long, and hard to discover. Print it out when we show help information.

---

Changes in v3:
- Use case-insensitve compare for image params (fixes build break with m53evk)

Changes in v2: None

 common/image.c  | 58 +++++++++++++++++++++++++++++++-------------------------
 include/image.h | 11 +++++++++++
 tools/mkimage.c | 59 ++++++++++++++++++++++++++++++++++++++++++++++++++-------
 3 files changed, 95 insertions(+), 33 deletions(-)
common/image.c +32 -26
index f0f0135..9efacf8 100644
@@ -543,6 +543,15 @@ void genimg_print_time(time_t timestamp)
 }
 #endif
 
+const table_entry_t *get_table_entry(const table_entry_t *table, int id)
+{
+	for (; table->id >= 0; ++table) {
+		if (table->id == id)
+			return table;
+	}
+	return NULL;
+}
+
 /**
  * get_table_entry_name - translate entry id to long name
  * @table: pointer to a translation table for entries of a specific type
@@ -559,15 +568,14 @@ void genimg_print_time(time_t timestamp)
  */
 char *get_table_entry_name(const table_entry_t *table, char *msg, int id)
 {
-	for (; table->id >= 0; ++table) {
-		if (table->id == id)
+	table = get_table_entry(table, id);
+	if (!table)
+		return msg;
 #if defined(USE_HOSTCC) || !defined(CONFIG_NEEDS_MANUAL_RELOC)
-			return table->lname;
+	return table->lname;
 #else
-			return table->lname + gd->reloc_off;
+	return table->lname + gd->reloc_off;
 #endif
-	}
-	return (msg);
 }
 
 const char *genimg_get_os_name(uint8_t os)
@@ -586,6 +594,20 @@ const char *genimg_get_type_name(uint8_t type)
 	return (get_table_entry_name(uimage_type, "Unknown Image", type));
 }
 
+const char *genimg_get_type_short_name(uint8_t type)
+{
+	const table_entry_t *table;
+
+	table = get_table_entry(uimage_type, type);
+	if (!table)
+		return "unknown";
+#if defined(USE_HOSTCC) || !defined(CONFIG_NEEDS_MANUAL_RELOC)
+	return table->sname;
+#else
+	return table->sname + gd->reloc_off;
+#endif
+}
+
 const char *genimg_get_comp_name(uint8_t comp)
 {
 	return (get_table_entry_name(uimage_comp, "Unknown Compression",
@@ -610,34 +632,18 @@ int get_table_entry_id(const table_entry_t *table,
 		const char *table_name, const char *name)
 {
 	const table_entry_t *t;
-#ifdef USE_HOSTCC
-	int first = 1;
-
-	for (t = table; t->id >= 0; ++t) {
-		if (t->sname && strcasecmp(t->sname, name) == 0)
-			return(t->id);
-	}
 
-	fprintf(stderr, "\nInvalid %s Type - valid names are", table_name);
-	for (t = table; t->id >= 0; ++t) {
-		if (t->sname == NULL)
-			continue;
-		fprintf(stderr, "%c %s", (first) ? ':' : ',', t->sname);
-		first = 0;
-	}
-	fprintf(stderr, "\n");
-#else
 	for (t = table; t->id >= 0; ++t) {
 #ifdef CONFIG_NEEDS_MANUAL_RELOC
-		if (t->sname && strcmp(t->sname + gd->reloc_off, name) == 0)
+		if (t->sname && strcasecmp(t->sname + gd->reloc_off, name) == 0)
 #else
-		if (t->sname && strcmp(t->sname, name) == 0)
+		if (t->sname && strcasecmp(t->sname, name) == 0)
 #endif
 			return (t->id);
 	}
 	debug("Invalid %s Type: %s\n", table_name, name);
-#endif /* USE_HOSTCC */
-	return (-1);
+
+	return -1;
 }
 
 int genimg_get_os_id(const char *name)
include/image.h +11 -0
index b6eb57e..63c3d37 100644
@@ -246,6 +246,8 @@ struct lmb;
 #define IH_TYPE_LPC32XXIMAGE	21	/* x86 setup.bin Image		*/
 #define IH_TYPE_LOADABLE	22	/* A list of typeless images	*/
 
+#define IH_TYPE_COUNT		23	/* Number of image types */
+
 /*
  * Compression Types
  */
@@ -411,6 +413,15 @@ char *get_table_entry_name(const table_entry_t *table, char *msg, int id);
 const char *genimg_get_os_name(uint8_t os);
 const char *genimg_get_arch_name(uint8_t arch);
 const char *genimg_get_type_name(uint8_t type);
+
+/**
+ * genimg_get_type_short_name() - get the short name for an image type
+ *
+ * @param type	Image type (IH_TYPE_...)
+ * @return image short name, or "unknown" if unknown
+ */
+const char *genimg_get_type_short_name(uint8_t type);
+
 const char *genimg_get_comp_name(uint8_t comp);
 int genimg_get_os_id(const char *name);
 int genimg_get_arch_id(const char *name);
tools/mkimage.c +52 -7

78 lines not on this page · raw message

Signature · 1 line
2.4.3.573.g4eafbef
#6 lore raw

PATCH v3 3/54 mkimage: Display a better list of available image types

Quoted 13 lines · Simon Glass

Offer to display the available image types in help. Also, rather than hacking the genimg_get_type_id() function to display a list of types, do this in the tool. Also, sort the list.

The list of image types is quite long, and hard to discover. Print it out when we show help information.

---

Changes in v3:
- Use case-insensitve compare for image params (fixes build break with m53evk)

Quoted 6 lines

Changes in v2: None

 common/image.c  | 58 +++++++++++++++++++++++++++++++-------------------------
 include/image.h | 11 +++++++++++
 tools/mkimage.c | 59 ++++++++++++++++++++++++++++++++++++++++++++++++++-------
 3 files changed, 95 insertions(+), 33 deletions(-)

Applied to u-boot-dm.

(If people have time to test this out it would be great!)

#7 lore raw

PATCH v3 4/54 fdt: Add a function to remove unused strings from a device tree

In reply to Simon Glass

Property names are stored in a string table. When a node property is removed, the string table is not updated since other nodes may have a property with the same name.

Thus it is possible for the string table to build up a number of unused strings. Add a function to remove these. This works by building a new device tree from the old one, adding strings one by one as needed.

---

Changes in v3:
- Fix indentation in function comment

Changes in v2:
- Add new patch to remove unused strings from a device tree

 include/libfdt.h    | 17 +++++++++++++++++
 lib/libfdt/fdt_rw.c | 32 ++++++++++++++++++++++++++++++++
 2 files changed, 49 insertions(+)
include/libfdt.h +17 -0
index f3cbb63..610c507 100644
@@ -1646,6 +1646,23 @@ int fdt_del_node(void *fdt, int nodeoffset);
 
 const char *fdt_strerror(int errval);
 
+/**
+ * fdt_remove_unused_strings() - Remove any unused strings from an FDT
+ *
+ * This creates a new device tree in @new with unused strings removed. The
+ * called can then use fdt_pack() to minimise the space consumed.
+ *
+ * @old:	Old device tree blog
+ * @new:	Place to put new device tree blob, which must be as large as
+ *		@old
+ * @return
+ *	0, on success
+ *	-FDT_ERR_BADOFFSET, corrupt device tree
+ *	-FDT_ERR_NOSPACE, out of space, which should not happen unless there
+ *		is something very wrong with the device tree input
+ */
+int fdt_remove_unused_strings(const void *old, void *new);
+
 struct fdt_region {
 	int offset;
 	int size;
lib/libfdt/fdt_rw.c +32 -0
index bec8b8a..1a358a8 100644
@@ -449,3 +449,35 @@ int fdt_pack(void *fdt)
 
 	return 0;
 }
+
+int fdt_remove_unused_strings(const void *old, void *new)
+{
+	const struct fdt_property *old_prop;
+	struct fdt_property *new_prop;
+	int size = fdt_totalsize(old);
+	int next_offset, offset;
+	const char *str;
+	int ret;
+	int tag = FDT_PROP;
+
+	/* Make a copy and remove the strings */
+	memcpy(new, old, size);
+	fdt_set_size_dt_strings(new, 0);
+
+	/* Add every property name back into the new string table */
+	for (offset = 0; tag != FDT_END; offset = next_offset) {
+		tag = fdt_next_tag(old, offset, &next_offset);
+		if (tag != FDT_PROP)
+			continue;
+		old_prop = fdt_get_property_by_offset(old, offset, NULL);
+		new_prop = (struct fdt_property *)(unsigned long)
+			fdt_get_property_by_offset(new, offset, NULL);
+		str = fdt_string(old, fdt32_to_cpu(old_prop->nameoff));
+		ret = _fdt_find_add_string(new, str);
+		if (ret < 0)
+			return ret;
+		new_prop->nameoff = cpu_to_fdt32(ret);
+	}
+
+	return 0;
+}
Signature · 1 line
2.4.3.573.g4eafbef
#8 lore raw

PATCH v3 4/54 fdt: Add a function to remove unused strings from a device tree

Quoted 14 lines · Simon Glass

Property names are stored in a string table. When a node property is removed, the string table is not updated since other nodes may have a property with the same name.

Thus it is possible for the string table to build up a number of unused strings. Add a function to remove these. This works by building a new device tree from the old one, adding strings one by one as needed.

---

Changes in v3:
- Fix indentation in function comment

Quoted 6 lines

Changes in v2:
- Add new patch to remove unused strings from a device tree

 include/libfdt.h    | 17 +++++++++++++++++
 lib/libfdt/fdt_rw.c | 32 ++++++++++++++++++++++++++++++++
 2 files changed, 49 insertions(+)

Applied to u-boot-dm.

#9 lore raw

PATCH v3 5/54 fdt: Add fdt_first/next_region() functions

In reply to Simon Glass

These have been sent upstream but not accepted to libfdt. For now, bring these into U-Boot to enable fdtgrep to operate. We will use fdtgrep to cut device tree files down for SPL.

---

Changes in v3: None
Changes in v2:
- Add new patch with fdt_first/next_region() functions
- Tidy up commit message a little

 include/libfdt.h        | 239 ++++++++++++++++++++++-
 lib/libfdt/Makefile     |   2 +-
 lib/libfdt/fdt_region.c | 492 ++++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 731 insertions(+), 2 deletions(-)
 create mode 100644 lib/libfdt/fdt_region.c
include/libfdt.h +238 -1
index 610c507..b8b1866 100644
@@ -121,7 +121,12 @@
 	/* FDT_ERR_BADNCELLS: Device tree has a #address-cells, #size-cells
 	 * or similar property with a bad format or value */
 
-#define FDT_ERR_MAX		14
+#define FDT_ERR_TOODEEP		15
+	/* FDT_ERR_TOODEEP: The depth of a node has exceeded the internal
+	 * libfdt limit. This can happen if you have more than
+	 * FDT_MAX_DEPTH nested nodes. */
+
+#define FDT_ERR_MAX		15
 
 /**********************************************************************/
 /* Low-level functions (you probably don't need these)                */
@@ -1668,6 +1673,77 @@ struct fdt_region {
 	int size;
 };
 
+/*
+ * Flags for fdt_find_regions()
+ *
+ * Add a region for the string table (always the last region)
+ */
+#define FDT_REG_ADD_STRING_TAB		(1 << 0)
+
+/*
+ * Add all supernodes of a matching node/property, useful for creating a
+ * valid subset tree
+ */
+#define FDT_REG_SUPERNODES		(1 << 1)
+
+/* Add the FDT_BEGIN_NODE tags of subnodes, including their names */
+#define FDT_REG_DIRECT_SUBNODES	(1 << 2)
+
+/* Add all subnodes of a matching node */
+#define FDT_REG_ALL_SUBNODES		(1 << 3)
+
+/* Add a region for the mem_rsvmap table (always the first region) */
+#define FDT_REG_ADD_MEM_RSVMAP		(1 << 4)
+
+/* Indicates what an fdt part is (node, property, value) */
+#define FDT_IS_NODE			(1 << 0)
+#define FDT_IS_PROP			(1 << 1)
+#define FDT_IS_VALUE			(1 << 2)	/* not supported */
+#define FDT_IS_COMPAT			(1 << 3)	/* used internally */
+#define FDT_NODE_HAS_PROP		(1 << 4)	/* node contains prop */
+
+#define FDT_ANY_GLOBAL		(FDT_IS_NODE | FDT_IS_PROP | FDT_IS_VALUE | \
+					FDT_IS_COMPAT)
+#define FDT_IS_ANY			0x1f		/* all the above */
+
+/* We set a reasonable limit on the number of nested nodes */
+#define FDT_MAX_DEPTH			32
+
+/* Decribes what we want to include from the current tag */
+enum want_t {
+	WANT_NOTHING,
+	WANT_NODES_ONLY,		/* No properties */
+	WANT_NODES_AND_PROPS,		/* Everything for one level */
+	WANT_ALL_NODES_AND_PROPS	/* Everything for all levels */
+};
+
+/* Keeps track of the state at parent nodes */
+struct fdt_subnode_stack {
+	int offset;		/* Offset of node */
+	enum want_t want;	/* The 'want' value here */
+	int included;		/* 1 if we included this node, 0 if not */
+};
+
+struct fdt_region_ptrs {
+	int depth;			/* Current tree depth */
+	int done;			/* What we have completed scanning */
+	enum want_t want;		/* What we are currently including */
+	char *end;			/* Pointer to end of full node path */
+	int nextoffset;			/* Next node offset to check */
+};
+
+/* The state of our finding algortihm */
+struct fdt_region_state {
+	struct fdt_subnode_stack stack[FDT_MAX_DEPTH];	/* node stack */
+	struct fdt_region *region;	/* Contains list of regions found */
+	int count;			/* Numnber of regions found */
+	const void *fdt;		/* FDT blob */
+	int max_regions;		/* Maximum regions to find */
+	int can_merge;		/* 1 if we can merge with previous region */
+	int start;			/* Start position of current region */
+	struct fdt_region_ptrs ptrs;	/* Pointers for what we are up to */
+};
+
 /**
  * fdt_find_regions() - find regions in device tree
  *
@@ -1727,4 +1803,165 @@ int fdt_find_regions(const void *fdt, char * const inc[], int inc_count,
 		     struct fdt_region region[], int max_regions,
 		     char *path, int path_len, int add_string_tab);
 
+/**
+ * fdt_first_region() - find regions in device tree
+ *
+ * Given a nodes and properties to include and properties to exclude, find
+ * the regions of the device tree which describe those included parts.
+ *
+ * The use for this function is twofold. Firstly it provides a convenient
+ * way of performing a structure-aware grep of the tree. For example it is
+ * possible to grep for a node and get all the properties associated with
+ * that node. Trees can be subsetted easily, by specifying the nodes that
+ * are required, and then writing out the regions returned by this function.
+ * This is useful for small resource-constrained systems, such as boot
+ * loaders, which want to use an FDT but do not need to know about all of
+ * it.
+ *
+ * Secondly it makes it easy to hash parts of the tree and detect changes.
+ * The intent is to get a list of regions which will be invariant provided
+ * those parts are invariant. For example, if you request a list of regions
+ * for all nodes but exclude the property "data", then you will get the
+ * same region contents regardless of any change to "data" properties.
+ *
+ * This function can be used to produce a byte-stream to send to a hashing
+ * function to verify that critical parts of the FDT have not changed.
+ * Note that semantically null changes in order could still cause false
+ * hash misses. Such reordering might happen if the tree is regenerated
+ * from source, and nodes are reordered (the bytes-stream will be emitted
+ * in a different order and mnay hash functions will detect this). However
+ * if an existing tree is modified using libfdt functions, such as
+ * fdt_add_subnode() and fdt_setprop(), then this problem is avoided.
+ *
+ * The nodes/properties to include/exclude are defined by a function
+ * provided by the caller. This function is called for each node and
+ * property, and must return:
+ *
+ *    0 - to exclude this part
+ *    1 - to include this part
+ *   -1 - for FDT_IS_PROP only: no information is available, so include
+ *		if its containing node is included
+ *
+ * The last case is only used to deal with properties. Often a property is
+ * included if its containing node is included - this is the case where
+ * -1 is returned.. However if the property is specifically required to be
+ * included/excluded, then 0 or 1 can be returned. Note that including a
+ * property when the FDT_REG_SUPERNODES flag is given will force its
+ * containing node to be included since it is not valid to have a property
+ * that is not in a node.
+ *
+ * Using the information provided, the inclusion of a node can be controlled
+ * either by a node name or its compatible string, or any other property
+ * that the function can determine.
+ *
+ * As an example, including node "/" means to include the root node and all
+ * root properties. A flag provides a way of also including supernodes (of
+ * which there is none for the root node), and another flag includes
+ * immediate subnodes, so in this case we would get the FDT_BEGIN_NODE and
+ * FDT_END_NODE of all subnodes of /.
+ *
+ * The subnode feature helps in a hashing situation since it prevents the
+ * root node from changing@all. Any change to non-excluded properties,
+ * names of subnodes or number of subnodes would be detected.
+ *
+ * When used with FITs this provides the ability to hash and sign parts of
+ * the FIT based on different configurations in the FIT. Then it is
+ * impossible to change anything about that configuration (include images
+ * attached to the configuration), but it may be possible to add new
+ * configurations, new images or new signatures within the existing
+ * framework.
+ *
+ * Adding new properties to a device tree may result in the string table
+ * being extended (if the new property names are different from those
+ * already added). This function can optionally include a region for
+ * the string table so that this can be part of the hash too. This is always
+ * the last region.
+ *
+ * The FDT also has a mem_rsvmap table which can also be included, and is
+ * always the first region if so.
+ *
+ * The device tree header is not included in the region list. Since the
+ * contents of the FDT are changing (shrinking, often), the caller will need
+ * to regenerate the header anyway.
+ *
+ * @fdt:	Device tree to check
+ * @h_include:	Function to call to determine whether to include a part or
+ *		not:
+ *
+ *		@priv: Private pointer as passed to fdt_find_regions()
+ *		@fdt: Pointer to FDT blob
+ *		@offset: Offset of this node / property
+ *		@type: Type of this part, FDT_IS_...
+ *		@data: Pointer to data (node name, property name, compatible
+ *			string, value (not yet supported)
+ *		@size: Size of data, or 0 if none
+ *		@return 0 to exclude, 1 to include, -1 if no information is
+ *		available
+ * @priv:	Private pointer passed to h_include
+ * @region:	Returns list of regions, sorted by offset
+ * @max_regions: Maximum length of region list
+ * @path:	Pointer to a temporary string for the function to use for
+ *		building path names
+ * @path_len:	Length of path, must be large enough to hold the longest
+ *		path in the tree
+ * @flags:	Various flags that control the region algortihm, see
+ *		FDT_REG_...
+ * @return number of regions in list. If this is >max_regions then the
+ * region array was exhausted. You should increase max_regions and try
+ * the call again. Only the first max_regions elements are available in the
+ * array.
+ *
+ * On error a -ve value is return, which can be:
+ *
+ *	-FDT_ERR_BADSTRUCTURE (too deep or more END tags than BEGIN tags
+ *	-FDT_ERR_BADLAYOUT
+ *	-FDT_ERR_NOSPACE (path area is too small)
+ */
+int fdt_first_region(const void *fdt,
+		int (*h_include)(void *priv, const void *fdt, int offset,
+				 int type, const char *data, int size),
+		void *priv, struct fdt_region *region,
+		char *path, int path_len, int flags,
+		struct fdt_region_state *info);
+
+/** fdt_next_region() - find next region
+ *
+ * See fdt_first_region() for full description. This function finds the
+ * next region according to the provided parameters, which must be the same
+ * as passed to fdt_first_region().
+ *
+ * This function can additionally return -FDT_ERR_NOTFOUND when there are no
+ * more regions
+ */
+int fdt_next_region(const void *fdt,
+		int (*h_include)(void *priv, const void *fdt, int offset,
+				 int type, const char *data, int size),
+		void *priv, struct fdt_region *region,
+		char *path, int path_len, int flags,
+		struct fdt_region_state *info);
+
+/**
+ * fdt_add_alias_regions() - find aliases that point to existing regions
+ *
+ * Once a device tree grep is complete some of the nodes will be present
+ * and some will have been dropped. This function checks all the alias nodes
+ * to figure out which points point to nodes which are still present. These
+ * aliases need to be kept, along with the nodes they reference.
+ *
+ * Given a list of regions function finds the aliases that still apply and
+ * adds more regions to the list for these. This function is called after
+ * fdt_next_region() has finished returning regions and requires the same
+ * state.
+ *
+ * @fdt:	Device tree file to reference
+ * @region:	List of regions that will be kept
+ * @count:	Number of regions
+ * @max_regions: Number of entries that can fit in @region
+ * @info:	Region state as returned from fdt_next_region()
+ * @return new number of regions in @region (i.e. count + the number added)
+ * or -FDT_ERR_NOSPACE if there was not enough space.
+ */
+int fdt_add_alias_regions(const void *fdt, struct fdt_region *region, int count,
+			  int max_regions, struct fdt_region_state *info);
+
 #endif /* _LIBFDT_H */
lib/libfdt/Makefile +1 -1
index 2f5413f..934d614 100644
@@ -6,4 +6,4 @@
 #
 
 obj-y += fdt.o fdt_ro.o fdt_rw.o fdt_strerror.o fdt_sw.o fdt_wip.o \
-	fdt_empty_tree.o fdt_addresses.o
+	fdt_empty_tree.o fdt_addresses.o fdt_region.o
lib/libfdt/fdt_region.c new file +492 -0

492 lines not on this page · raw message

Signature · 1 line
2.4.3.573.g4eafbef
#10 lore raw

PATCH v3 5/54 fdt: Add fdt_first/next_region() functions

Quoted 12 lines · Simon Glass

These have been sent upstream but not accepted to libfdt. For now, bring these into U-Boot to enable fdtgrep to operate. We will use fdtgrep to cut device tree files down for SPL.

---

Changes in v3: None
Changes in v2:
- Add new patch with fdt_first/next_region() functions
- Tidy up commit message a little

Quoted 5 lines
 include/libfdt.h        | 239 ++++++++++++++++++++++-
 lib/libfdt/Makefile     |   2 +-
 lib/libfdt/fdt_region.c | 492 ++++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 731 insertions(+), 2 deletions(-)
 create mode 100644 lib/libfdt/fdt_region.c

Applied to u-boot-dm.

#11 lore raw

PATCH v3 6/54 fdt: Add fdtgrep tool

In reply to Simon Glass

This tool allows us to extract subsets of a device tree file. It is used by the SPL vuild, which needs to cut down the device tree size for use in limited memory.

This tool was originally written for libfdt but it has not been accepted upstream, so for now, include it in U-Boot. Several utilfdt library functions been included inline here.

If fdtgrep is eventually accepted in libfdt then we can bring that version of libfdt in here, and drop fdtgrep (requiring that fdtgrep is provided by the user).

If it is not accepted then another approach would be to write a special tool for chopping down device tree files for SPL. While it would use the same libfdt support, it would be less code than fdtgrep.c because it would not have general-purpose functions.

Another approach (which was used with v1 of this series) is to sprinkler all the device tree files with #ifdef. I don't like that idea.

---

Changes in v3: None
Changes in v2:
- Add new patch with fdtgrep tool

 tools/Makefile  |    6 +-
 tools/fdtgrep.c | 1234 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 1239 insertions(+), 1 deletion(-)
 create mode 100644 tools/fdtgrep.c
tools/Makefile +5 -1
index 8ff9c2e..98414f7 100644
@@ -58,7 +58,8 @@ hostprogs-$(CONFIG_FIT_SIGNATURE) += fit_info fit_check_sign
 FIT_SIG_OBJS-$(CONFIG_FIT_SIGNATURE) := common/image-sig.o
 # Flattened device tree objects
 LIBFDT_OBJS := $(addprefix lib/libfdt/, \
-			fdt.o fdt_ro.o fdt_rw.o fdt_strerror.o fdt_wip.o)
+			fdt.o fdt_ro.o fdt_rw.o fdt_strerror.o fdt_wip.o \
+			fdt_region.o)
 RSA_OBJS-$(CONFIG_FIT_SIGNATURE) := $(addprefix lib/rsa/, \
 					rsa-sign.o rsa-verify.o rsa-checksum.o \
 					rsa-mod-exp.o)
@@ -155,6 +156,9 @@ hostprogs-$(CONFIG_ARMADA_XP) += kwboot
 hostprogs-y += proftool
 hostprogs-$(CONFIG_STATIC_RELA) += relocate-rela
 
+hostprogs-y += fdtgrep
+fdtgrep-objs += $(LIBFDT_OBJS) fdtgrep.o
+
 # We build some files with extra pedantic flags to try to minimize things
 # that won't build on some weird host compiler -- though there are lots of
 # exceptions for files that aren't complaint.
tools/fdtgrep.c new file +1234 -0

1,234 lines not on this page · raw message

Signature · 1 line
2.4.3.573.g4eafbef
#12 lore raw

PATCH v3 6/54 fdt: Add fdtgrep tool

Quoted 23 lines · Simon Glass

This tool allows us to extract subsets of a device tree file. It is used by the SPL vuild, which needs to cut down the device tree size for use in limited memory.

This tool was originally written for libfdt but it has not been accepted upstream, so for now, include it in U-Boot. Several utilfdt library functions been included inline here.

If fdtgrep is eventually accepted in libfdt then we can bring that version of libfdt in here, and drop fdtgrep (requiring that fdtgrep is provided by the user).

If it is not accepted then another approach would be to write a special tool for chopping down device tree files for SPL. While it would use the same libfdt support, it would be less code than fdtgrep.c because it would not have general-purpose functions.

Another approach (which was used with v1 of this series) is to sprinkler all the device tree files with #ifdef. I don't like that idea.

---

Quoted 8 lines

Changes in v3: None
Changes in v2:
- Add new patch with fdtgrep tool

 tools/Makefile  |    6 +-
 tools/fdtgrep.c | 1234 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 1239 insertions(+), 1 deletion(-)
 create mode 100644 tools/fdtgrep.c

Applied to u-boot-dm.

#13 lore raw

PATCH v3 7/54 dm: Reduce SPL device tree size

In reply to Simon Glass

The SPL device tree size must be minimised to save memory. Only include properties that are needed by SPL - this is determined by the presence of the "u-boot,dm-pre-reloc" property. Also remove a predefined list of unused properties from the nodes that remain.

---

Changes in v3:
- Convert hex number to upper case to keep bc happy

Changes in v2:
- Add new patch to reduce SPL device tree size with fdtgrep

 Makefile                    |  2 +-
 arch/arm/cpu/u-boot-spl.lds |  2 +-
 dts/Kconfig                 | 12 ++++++++++++
 scripts/Makefile.spl        | 28 ++++++++++++++++++++++++++++
 4 files changed, 42 insertions(+), 2 deletions(-)
Makefile +1 -1
index 0a674bf..4276f13 100644
@@ -1258,7 +1258,7 @@ u-boot.lds: $(LDSCRIPT) prepare FORCE
 
 spl/u-boot-spl.bin: spl/u-boot-spl
 	@:
-spl/u-boot-spl: tools prepare
+spl/u-boot-spl: tools prepare $(if $(CONFIG_OF_SEPARATE),dts/dt.dtb)
 	$(Q)$(MAKE) obj=spl -f $(srctree)/scripts/Makefile.spl all
 
 spl/sunxi-spl.bin: spl/u-boot-spl
arch/arm/cpu/u-boot-spl.lds +1 -1
index a8be204..4b6e0f6 100644
@@ -66,7 +66,7 @@ SECTIONS
 		 . = ALIGN(4);
 		__bss_end = .;
 	}
-
+	__bss_size = __bss_end - __bss_start;
 	.dynsym _image_binary_end : { *(.dynsym) }
 	.dynbss : { *(.dynbss) }
 	.dynstr : { *(.dynstr*) }
dts/Kconfig +12 -0
index 957f5c7..09cfefb 100644
@@ -56,4 +56,16 @@ config DEFAULT_DEVICE_TREE
 	  It can be overridden from the command line:
 	  $ make DEVICE_TREE=<device-tree-name>
 
+config OF_SPL_REMOVE_PROPS
+	string "List of device tree properties to drop for SPL"
+	depends on OF_CONTROL && SPL
+	default "pinctrl-0 pinctrl-names clocks clock-names interrupt-parent"
+	help
+	  Since SPL normally runs in a reduced memory space, the device tree
+	  is cut down to only what is needed to load and start U-Boot. Only
+	  nodes marked with the property "u-boot,dm-pre-reloc" will be
+	  included. In addition, some properties are not used by U-Boot and
+	  can be discarded. This option defines the list of properties to
+	  discard.
+
 endmenu
scripts/Makefile.spl +28 -0
index fd572f4..bcc7ca2 100644
@@ -151,6 +151,8 @@ boot.bin: $(obj)/u-boot-spl.bin
 
 ALL-y	+= $(obj)/$(SPL_BIN).bin $(obj)/$(SPL_BIN).cfg
 
+ALL-$(CONFIG_OF_SEPARATE) += $(obj)/$(SPL_BIN)-pad.bin $(obj)/$(SPL_BIN)-dtb.bin
+
 ifdef CONFIG_SAMSUNG
 ALL-y	+= $(obj)/$(BOARD)-spl.bin
 endif
@@ -165,6 +167,32 @@ endif
 
 all:	$(ALL-y)
 
+quiet_cmd_cat = CAT     $@
+cmd_cat = cat $(filter-out $(PHONY), $^) > $@
+
+$(obj)/$(SPL_BIN)-dtb.bin: $(obj)/$(SPL_BIN).bin $(obj)/$(SPL_BIN)-pad.bin \
+		$(obj)/$(SPL_BIN).dtb FORCE
+	$(call if_changed,cat)
+
+# Create a file that pads from the end of u-boot-spl.bin to bss_end
+$(obj)/$(SPL_BIN)-pad.bin: $(obj)/$(SPL_BIN)
+	@bss_size_str=$(shell $(NM) $< | awk 'BEGIN {size = 0} /__bss_size/ {size = $$1} END {print "ibase=16; " toupper(size)}' | bc); \
+	dd if=/dev/zero of=$@ bs=1 count=$${bss_size_str} 2>/dev/null;
+
+# Pass the original device tree file through fdtgrep twice. The first pass
+# removes any unwanted nodes (i.e. those which don't have the
+# 'u-boot,dm-pre-reloc' property and thus are not needed by SPL. The second
+# pass removes various unused properties from the remaining nodes.
+# The output is typically a much smaller device tree file.
+quiet_cmd_fdtgrep = FDTGREP $@
+      cmd_fdtgrep = $(objtree)/tools/fdtgrep -b u-boot,dm-pre-reloc -RT $< \
+		-n /chosen -O dtb | \
+	$(objtree)/tools/fdtgrep -r -O dtb - -o $@ \
+		$(addprefix -P ,$(subst $\",,$(CONFIG_OF_SPL_REMOVE_PROPS)))
+
+$(obj)/$(SPL_BIN).dtb: dts/dt.dtb
+	$(call cmd,fdtgrep)
+
 quiet_cmd_cpp_cfg = CFG     $@
 cmd_cpp_cfg = $(CPP) -Wp,-MD,$(depfile) $(cpp_flags) $(LDPPFLAGS) -ansi \
 	-DDO_DEPS_ONLY -D__ASSEMBLY__ -x assembler-with-cpp -P -dM -E -o $@ $<
Signature · 1 line
2.4.3.573.g4eafbef
#14 lore raw

PATCH v3 7/54 dm: Reduce SPL device tree size

Quoted 11 lines · Simon Glass

The SPL device tree size must be minimised to save memory. Only include properties that are needed by SPL - this is determined by the presence of the "u-boot,dm-pre-reloc" property. Also remove a predefined list of unused properties from the nodes that remain.

---

Changes in v3:
- Convert hex number to upper case to keep bc happy

Quoted 8 lines

Changes in v2:
- Add new patch to reduce SPL device tree size with fdtgrep

 Makefile                    |  2 +-
 arch/arm/cpu/u-boot-spl.lds |  2 +-
 dts/Kconfig                 | 12 ++++++++++++
 scripts/Makefile.spl        | 28 ++++++++++++++++++++++++++++
 4 files changed, 42 insertions(+), 2 deletions(-)

Applied to u-boot-dm.

#15 lore raw

PATCH v3 8/54 dm: arm: Put driver model I2C drivers before legacy ones

In reply to Simon Glass

Driver-model I2C drivers can be picked up by the linker script rule for legacy drivers. Change the order to avoid this.

We could make the legacy code depend on !CONFIG_DM_I2C but that is not necessary and it is good to keep conditions to a minimum.

---

Changes in v3: None
Changes in v2: None

 arch/arm/cpu/u-boot-spl.lds | 10 +++++-----
 1 file changed, 5 insertions(+), 5 deletions(-)
arch/arm/cpu/u-boot-spl.lds +5 -5
index 4b6e0f6..c5b4f7c 100644
@@ -32,17 +32,17 @@ SECTIONS
 	}
 
 	. = ALIGN(4);
-	.u_boot_list : {
-		KEEP(*(SORT(.u_boot_list*_i2c_*)));
-	}
-
-	. = .;
 #ifdef CONFIG_SPL_DM
 	.u_boot_list : {
 		KEEP(*(SORT(.u_boot_list_*_driver_*)));
 		KEEP(*(SORT(.u_boot_list_*_uclass_*)));
 	}
 #endif
+	. = .;
+	.u_boot_list : {
+		KEEP(*(SORT(.u_boot_list*_i2c_*)));
+	}
+
 	. = ALIGN(4);
 
 	__image_copy_end = .;
Signature · 1 line
2.4.3.573.g4eafbef
#16 lore raw

PATCH v3 8/54 dm: arm: Put driver model I2C drivers before legacy ones

Quoted 6 lines · Simon Glass

Driver-model I2C drivers can be picked up by the linker script rule for legacy drivers. Change the order to avoid this.

We could make the legacy code depend on !CONFIG_DM_I2C but that is not necessary and it is good to keep conditions to a minimum.

Quoted 8 lines

---

Changes in v3: None
Changes in v2: None

 arch/arm/cpu/u-boot-spl.lds | 10 +++++-----
 1 file changed, 5 insertions(+), 5 deletions(-)

Applied to u-boot-dm.

#17 lore raw

PATCH v3 9/54 Add a way of checking the position of a structure member

In reply to Simon Glass

U-Boot uses structures for hardware access so it is important that these structures are correct. Add a way of asserting that a structure member is at a particular offset. This can be created using the datasheet for the hardware.

This implementation uses Static_assert() since BUILD_BUG_ON() only works within functions.

---

Changes in v3: None
Changes in v2: None

 include/common.h | 11 +++++++++++
 1 file changed, 11 insertions(+)
include/common.h +11 -0
index 8f4b2ec..4566bd1 100644
@@ -1010,6 +1010,17 @@ int cpu_release(int nr, int argc, char * const argv[]);
 #define DEFINE_CACHE_ALIGN_BUFFER(type, name, size)			\
 	DEFINE_ALIGN_BUFFER(type, name, size, ARCH_DMA_MINALIGN)
 
+/*
+ * check_member() - Check the offset of a structure member
+ *
+ * @structure:	Name of structure (e.g. global_data)
+ * @member:	Name of member (e.g. baudrate)
+ * @offset:	Expected offset in bytes
+ */
+#define check_member(structure, member, offset) _Static_assert( \
+	offsetof(struct structure, member) == offset, \
+	"`struct " #structure "` offset for `" #member "` is not " #offset)
+
 /* Pull in stuff for the build system */
 #ifdef DO_DEPS_ONLY
 # include <environment.h>
Signature · 1 line
2.4.3.573.g4eafbef
#18 lore raw

PATCH v3 9/54 Add a way of checking the position of a structure member

Quoted 8 lines · Simon Glass

U-Boot uses structures for hardware access so it is important that these structures are correct. Add a way of asserting that a structure member is at a particular offset. This can be created using the datasheet for the hardware.

This implementation uses Static_assert() since BUILD_BUG_ON() only works within functions.

Quoted 8 lines

---

Changes in v3: None
Changes in v2: None

 include/common.h | 11 +++++++++++
 1 file changed, 11 insertions(+)

Applied to u-boot-dm.

#19 lore raw

PATCH v3 10/54 debug_uart: Remove use of asmlinkage

In reply to Simon Glass

This does not actually help any current arch. For x86 it makes it harder to call (requires stack) and for ARM it has no effect. Drop it.

---

Changes in v3: None
Changes in v2: None

 include/debug_uart.h | 22 ++++++++++------------
 1 file changed, 10 insertions(+), 12 deletions(-)
include/debug_uart.h +10 -12
index f56797b..a75e377 100644
@@ -10,8 +10,6 @@
 #ifndef _DEBUG_UART_H
 #define _DEBUG_UART_H
 
-#include <linux/linkage.h>
-
 /*
  * The debug UART is intended for use very early in U-Boot to debug problems
  * when an ICE or other debug mechanism is not available.
@@ -64,46 +62,46 @@ void debug_uart_init(void);
  *
  * @ch:		Character to output
  */
-asmlinkage void printch(int ch);
+void printch(int ch);
 
 /**
  * printascii() - Output an ASCII string to the debug UART
  *
  * @str:	String to output
  */
-asmlinkage void printascii(const char *str);
+void printascii(const char *str);
 
 /**
  * printhex2() - Output a 2-digit hex value
  *
  * @value:	Value to output
  */
-asmlinkage void printhex2(uint value);
+void printhex2(uint value);
 
 /**
  * printhex4() - Output a 4-digit hex value
  *
  * @value:	Value to output
  */
-asmlinkage void printhex4(uint value);
+void printhex4(uint value);
 
 /**
  * printhex8() - Output a 8-digit hex value
  *
  * @value:	Value to output
  */
-asmlinkage void printhex8(uint value);
+void printhex8(uint value);
 
 /*
  * Now define some functions - this should be inserted into the serial driver
  */
 #define DEBUG_UART_FUNCS \
-	asmlinkage void printch(int ch) \
+	void printch(int ch) \
 	{ \
 		_debug_uart_putc(ch); \
 	} \
 \
-	asmlinkage void printascii(const char *str) \
+	void printascii(const char *str) \
 	{ \
 		while (*str) \
 			_debug_uart_putc(*str++); \
@@ -121,17 +119,17 @@ asmlinkage void printhex8(uint value);
 			printhex1(value >> (4 * digits)); \
 	} \
 \
-	asmlinkage void printhex2(uint value) \
+	void printhex2(uint value) \
 	{ \
 		printhex(value, 2); \
 	} \
 \
-	asmlinkage void printhex4(uint value) \
+	void printhex4(uint value) \
 	{ \
 		printhex(value, 4); \
 	} \
 \
-	asmlinkage void printhex8(uint value) \
+	void printhex8(uint value) \
 	{ \
 		printhex(value, 8); \
 	}
Signature · 1 line
2.4.3.573.g4eafbef
#20 lore raw

PATCH v3 10/54 debug_uart: Remove use of asmlinkage

Quoted 11 lines · Simon Glass

This does not actually help any current arch. For x86 it makes it harder to call (requires stack) and for ARM it has no effect. Drop it.

---

Changes in v3: None
Changes in v2: None

 include/debug_uart.h | 22 ++++++++++------------
 1 file changed, 10 insertions(+), 12 deletions(-)

Applied to u-boot-dm.

#21 lore raw

PATCH v3 11/54 dm: Allow debug UART to support an early console

In reply to Simon Glass

When there is no console ready, allow the debug UART to be used for output. This makes debugging of early code considerably easier.

---

Changes in v3: None
Changes in v2: None

 common/console.c | 19 +++++++++++++++++++
 1 file changed, 19 insertions(+)
common/console.c +19 -0
index 0058222..acad8bd 100644
@@ -6,6 +6,7 @@
  */
 
 #include <common.h>
+#include <debug_uart.h>
 #include <stdarg.h>
 #include <iomux.h>
 #include <malloc.h>
@@ -460,6 +461,13 @@ void putc(const char c)
 		return;
 	}
 #endif
+#ifdef CONFIG_DEBUG_UART
+	/* if we don't have a console yet, use the debug UART */
+	if (!gd || !(gd->flags & GD_FLG_SERIAL_READY)) {
+		printch(c);
+		return;
+	}
+#endif
 #ifdef CONFIG_SILENT_CONSOLE
 	if (gd->flags & GD_FLG_SILENT)
 		return;
@@ -491,7 +499,18 @@ void puts(const char *s)
 		return;
 	}
 #endif
+#ifdef CONFIG_DEBUG_UART
+	if (!gd || !(gd->flags & GD_FLG_SERIAL_READY)) {
+		while (*s) {
+			int ch = *s++;
 
+			printch(ch);
+			if (ch == '\n')
+				printch('\r');
+		}
+		return;
+	}
+#endif
 #ifdef CONFIG_SILENT_CONSOLE
 	if (gd->flags & GD_FLG_SILENT)
 		return;
Signature · 1 line
2.4.3.573.g4eafbef
#22 lore raw

PATCH v3 11/54 dm: Allow debug UART to support an early console

Quoted 11 lines · Simon Glass

When there is no console ready, allow the debug UART to be used for output. This makes debugging of early code considerably easier.

---

Changes in v3: None
Changes in v2: None

 common/console.c | 19 +++++++++++++++++++
 1 file changed, 19 insertions(+)

Applied to u-boot-dm.

#23 lore raw

PATCH v3 12/54 sandbox: Drop special-case sandbox console code

In reply to Simon Glass

At present printf() skips output if it can see there is no console. This is really just an optimisation, and is not necessary. Also it is currently incorrect in some cases. Rather than update the logic, just remove it so that we don't need to keep it in sync.

---

Changes in v3: None
Changes in v2: None

 common/console.c | 6 +-----
 1 file changed, 1 insertion(+), 5 deletions(-)
common/console.c +1 -5
index acad8bd..ace206c 100644
@@ -456,6 +456,7 @@ static inline void print_pre_console_buffer(int flushpoint) {}
 void putc(const char c)
 {
 #ifdef CONFIG_SANDBOX
+	/* sandbox can send characters to stdout before it has a console */
 	if (!gd || !(gd->flags & GD_FLG_SERIAL_READY)) {
 		os_putc(c);
 		return;
@@ -540,11 +541,6 @@ int printf(const char *fmt, ...)
 	uint i;
 	char printbuffer[CONFIG_SYS_PBSIZE];
 
-#if !defined(CONFIG_SANDBOX) && !defined(CONFIG_PRE_CONSOLE_BUFFER)
-	if (!gd->have_console)
-		return 0;
-#endif
-
 	va_start(args, fmt);
 
 	/* For this to work, printbuffer must be larger than
Signature · 1 line
2.4.3.573.g4eafbef
#24 lore raw

PATCH v3 12/54 sandbox: Drop special-case sandbox console code

Quoted 5 lines · Simon Glass

At present printf() skips output if it can see there is no console. This is really just an optimisation, and is not necessary. Also it is currently incorrect in some cases. Rather than update the logic, just remove it so that we don't need to keep it in sync.

Quoted 8 lines

---

Changes in v3: None
Changes in v2: None

 common/console.c | 6 +-----
 1 file changed, 1 insertion(+), 5 deletions(-)

Applied to u-boot-dm.

#25 lore raw

PATCH v3 13/54 dm: Move the tree/uclass dump code into its own file

In reply to Simon Glass

In SPL it is sometimes useful to be able to obtain a dump of the current driver model state. Since commands are not available, provide a way to directly call the functions to output this information.

Adjust the existing commands to use these functions.

---

Changes in v3: None
Changes in v2: None

 drivers/core/Makefile |  1 +
 drivers/core/dump.c   | 96 +++++++++++++++++++++++++++++++++++++++++++++++++++
 include/dm/util.h     |  6 ++++
 test/dm/cmd_dm.c      | 82 ++-----------------------------------------
 4 files changed, 106 insertions(+), 79 deletions(-)
 create mode 100644 drivers/core/dump.c
drivers/core/Makefile +1 -0
index a3fec38..ed21fed 100644
@@ -9,3 +9,4 @@ ifndef CONFIG_SPL_BUILD
 obj-$(CONFIG_OF_CONTROL) += simple-bus.o
 endif
 obj-$(CONFIG_DM_DEVICE_REMOVE)	+= device-remove.o
+obj-$(CONFIG_DM)	+= dump.o
drivers/core/dump.c new file +96 -0

96 lines not on this page · raw message

include/dm/util.h +6 -0
index 0cec17b..7dbed67 100644
@@ -33,4 +33,10 @@ struct list_head;
  */
 int list_count_items(struct list_head *head);
 
+/* Dump out a tree of all devices */
+void dm_dump_all(void);
+
+/* Dump out a list of uclasses and their devices */
+void dm_dump_uclass(void);
+
 #endif
test/dm/cmd_dm.c +3 -79

99 lines not on this page · raw message

Signature · 1 line
2.4.3.573.g4eafbef
#26 lore raw

PATCH v3 13/54 dm: Move the tree/uclass dump code into its own file

Quoted 12 lines · Simon Glass

In SPL it is sometimes useful to be able to obtain a dump of the current driver model state. Since commands are not available, provide a way to directly call the functions to output this information.

Adjust the existing commands to use these functions.

---

Changes in v3: None
Changes in v2: None

Quoted 6 lines
 drivers/core/Makefile |  1 +
 drivers/core/dump.c   | 96 +++++++++++++++++++++++++++++++++++++++++++++++++++
 include/dm/util.h     |  6 ++++
 test/dm/cmd_dm.c      | 82 ++-----------------------------------------
 4 files changed, 106 insertions(+), 79 deletions(-)
 create mode 100644 drivers/core/dump.c

Applied to u-boot-dm.

#27 lore raw

PATCH v3 14/54 dm: core: Use debug() instead of printf() for failures

In reply to Simon Glass

To avoid bloating SPL code, use debug() where possible in the driver model core code. The error code is already returned, and can be investigated as needed.

---

Changes in v3: None
Changes in v2: None

 drivers/core/lists.c | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)
drivers/core/lists.c +3 -3
index 0c49d99..2e52500 100644
@@ -86,13 +86,13 @@ int device_bind_driver_to_node(struct udevice *parent, const char *drv_name,
 
 	drv = lists_driver_lookup_name(drv_name);
 	if (!drv) {
-		printf("Cannot find driver '%s'\n", drv_name);
+		debug("Cannot find driver '%s'\n", drv_name);
 		return -ENOENT;
 	}
 	ret = device_bind(parent, drv, dev_name, NULL, node, devp);
 	if (ret) {
-		printf("Cannot create device named '%s' (err=%d)\n",
-		       dev_name, ret);
+		debug("Cannot create device named '%s' (err=%d)\n",
+		      dev_name, ret);
 		return ret;
 	}
 
Signature · 1 line
2.4.3.573.g4eafbef
#28 lore raw

PATCH v3 14/54 dm: core: Use debug() instead of printf() for failures

Quoted 4 lines · Simon Glass

To avoid bloating SPL code, use debug() where possible in the driver model core code. The error code is already returned, and can be investigated as needed.

Quoted 8 lines

---

Changes in v3: None
Changes in v2: None

 drivers/core/lists.c | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

Applied to u-boot-dm.

#29 lore raw

PATCH v3 15/54 dm: core: Add a function to find any device from device tree

In reply to Simon Glass

In some rare cases it is useful to be able to locate a device given a device tree node offset. An example is when you have an alias that points to a node and you want to find the associated device. The device may be SPI, MMC or something else, but you don't need to know the uclass to find it.

Add a function to do a global search for a device, given its device tree offset.

---

Changes in v3: None
Changes in v2: None

 drivers/core/device.c | 25 +++++++++++++++++++++++++
 include/dm/device.h   | 14 ++++++++++++++
 2 files changed, 39 insertions(+)
drivers/core/device.c +25 -0
index 85fd1fc..43aff54 100644
@@ -470,6 +470,31 @@ int device_get_child_by_of_offset(struct udevice *parent, int seq,
 	return device_get_device_tail(dev, ret, devp);
 }
 
+static struct udevice *_device_find_global_by_of_offset(struct udevice *parent,
+							int of_offset)
+{
+	struct udevice *dev, *found;
+
+	if (parent->of_offset == of_offset)
+		return parent;
+
+	list_for_each_entry(dev, &parent->child_head, sibling_node) {
+		found = _device_find_global_by_of_offset(dev, of_offset);
+		if (found)
+			return found;
+	}
+
+	return NULL;
+}
+
+int device_get_global_by_of_offset(int of_offset, struct udevice **devp)
+{
+	struct udevice *dev;
+
+	dev = _device_find_global_by_of_offset(gd->dm_root, of_offset);
+	return device_get_device_tail(dev, dev ? 0 : -ENOENT, devp);
+}
+
 int device_find_first_child(struct udevice *parent, struct udevice **devp)
 {
 	if (list_empty(&parent->child_head)) {
include/dm/device.h +14 -0
index 18296bb..9a94ee1 100644
@@ -390,6 +390,20 @@ int device_get_child_by_of_offset(struct udevice *parent, int seq,
 				  struct udevice **devp);
 
 /**
+ * device_get_global_by_of_offset() - Get a device based on FDT offset
+ *
+ * Locates a device by its device tree offset, searching globally throughout
+ * the all driver model devices.
+ *
+ * The device is probed to activate it ready for use.
+ *
+ * @of_offset: Device tree offset to find
+ * @devp: Returns pointer to device if found, otherwise this is set to NULL
+ * @return 0 if OK, -ve on error
+ */
+int device_get_global_by_of_offset(int of_offset, struct udevice **devp);
+
+/**
  * device_find_first_child() - Find the first child of a device
  *
  * @parent: Parent device to search
Signature · 1 line
2.4.3.573.g4eafbef
#30 lore raw

PATCH v3 15/54 dm: core: Add a function to find any device from device tree

Quoted 9 lines · Simon Glass

In some rare cases it is useful to be able to locate a device given a device tree node offset. An example is when you have an alias that points to a node and you want to find the associated device. The device may be SPI, MMC or something else, but you don't need to know the uclass to find it.

Add a function to do a global search for a device, given its device tree offset.

Quoted 8 lines

---

Changes in v3: None
Changes in v2: None

 drivers/core/device.c | 25 +++++++++++++++++++++++++
 include/dm/device.h   | 14 ++++++++++++++
 2 files changed, 39 insertions(+)

Applied to u-boot-dm.

#31 lore raw

PATCH v3 16/54 dm: core: Correct device_get_child_by_of_offset() parameter

In reply to Simon Glass

This parameter is named 'seq' but should be named 'of_offset'.

---

Changes in v3: None
Changes in v2: None

 drivers/core/device.c | 4 ++--
 include/dm/device.h   | 2 +-
 2 files changed, 3 insertions(+), 3 deletions(-)
drivers/core/device.c +2 -2
index 43aff54..456426a 100644
@@ -459,14 +459,14 @@ int device_find_child_by_of_offset(struct udevice *parent, int of_offset,
 	return -ENODEV;
 }
 
-int device_get_child_by_of_offset(struct udevice *parent, int seq,
+int device_get_child_by_of_offset(struct udevice *parent, int node,
 				  struct udevice **devp)
 {
 	struct udevice *dev;
 	int ret;
 
 	*devp = NULL;
-	ret = device_find_child_by_of_offset(parent, seq, &dev);
+	ret = device_find_child_by_of_offset(parent, node, &dev);
 	return device_get_device_tail(dev, ret, devp);
 }
 
include/dm/device.h +1 -1
index 9a94ee1..9fa0048 100644
@@ -386,7 +386,7 @@ int device_find_child_by_of_offset(struct udevice *parent, int of_offset,
  * @devp: Returns pointer to device if found, otherwise this is set to NULL
  * @return 0 if OK, -ve on error
  */
-int device_get_child_by_of_offset(struct udevice *parent, int seq,
+int device_get_child_by_of_offset(struct udevice *parent, int of_offset,
 				  struct udevice **devp);
 
 /**
Signature · 1 line
2.4.3.573.g4eafbef
#32 lore raw

PATCH v3 16/54 dm: core: Correct device_get_child_by_of_offset() parameter

Quoted 11 lines · Simon Glass

This parameter is named 'seq' but should be named 'of_offset'.

---

Changes in v3: None
Changes in v2: None

 drivers/core/device.c | 4 ++--
 include/dm/device.h   | 2 +-
 2 files changed, 3 insertions(+), 3 deletions(-)

Applied to u-boot-dm.

#33 lore raw

PATCH v3 17/54 dm: gpio: Allow GPIO uclass to be used in SPL

In reply to Simon Glass

Now that we support driver model in SPL, allow GPIO drivers to be used there also.

---

Changes in v3: None
Changes in v2: None

 drivers/gpio/Makefile | 4 ----
 1 file changed, 4 deletions(-)
drivers/gpio/Makefile +0 -4
index 5864850..67c6374 100644
@@ -6,13 +6,9 @@
 #
 
 ifndef CONFIG_SPL_BUILD
-obj-$(CONFIG_DM_GPIO)		+= gpio-uclass.o
 obj-$(CONFIG_AXP_GPIO)		+= axp_gpio.o
 endif
-/* TODO(sjg at chromium.org): Only tegra supports driver model in SPL */
-ifdef CONFIG_TEGRA_GPIO
 obj-$(CONFIG_DM_GPIO)		+= gpio-uclass.o
-endif
 
 obj-$(CONFIG_AT91_GPIO)	+= at91_gpio.o
 obj-$(CONFIG_INTEL_ICH6_GPIO)	+= intel_ich6_gpio.o
Signature · 1 line
2.4.3.573.g4eafbef
#34 lore raw

PATCH v3 17/54 dm: gpio: Allow GPIO uclass to be used in SPL

Quoted 11 lines · Simon Glass

Now that we support driver model in SPL, allow GPIO drivers to be used there also.

---

Changes in v3: None
Changes in v2: None

 drivers/gpio/Makefile | 4 ----
 1 file changed, 4 deletions(-)

Applied to u-boot-dm.

#35 lore raw

PATCH v3 18/54 dm: gpio: Add dm_gpio_lookup_name() to look up a GPIO name

In reply to Simon Glass

Provide a driver-model function to look up a GPIO name. Make the standard function use it.

---

Changes in v3: None
Changes in v2: None

 drivers/gpio/gpio-uclass.c | 34 ++++++++++++++++++++++++++--------
 include/asm-generic/gpio.h | 13 +++++++++++++
 2 files changed, 39 insertions(+), 8 deletions(-)
drivers/gpio/gpio-uclass.c +26 -8
index bf982b9..c6fd580 100644
@@ -48,8 +48,7 @@ static int gpio_to_device(unsigned int gpio, struct gpio_desc *desc)
 	return ret ? ret : -ENOENT;
 }
 
-int gpio_lookup_name(const char *name, struct udevice **devp,
-		     unsigned int *offsetp, unsigned int *gpiop)
+int dm_gpio_lookup_name(const char *name, struct gpio_desc *desc)
 {
 	struct gpio_dev_priv *uc_priv = NULL;
 	struct udevice *dev;
@@ -57,8 +56,6 @@ int gpio_lookup_name(const char *name, struct udevice **devp,
 	int numeric;
 	int ret;
 
-	if (devp)
-		*devp = NULL;
 	numeric = isdigit(*name) ? simple_strtoul(name, NULL, 10) : -1;
 	for (ret = uclass_first_device(UCLASS_GPIO, &dev);
 	     dev;
@@ -84,12 +81,33 @@ int gpio_lookup_name(const char *name, struct udevice **devp,
 	if (!dev)
 		return ret ? ret : -EINVAL;
 
+	desc->dev = dev;
+	desc->offset = offset;
+
+	return 0;
+}
+
+int gpio_lookup_name(const char *name, struct udevice **devp,
+		     unsigned int *offsetp, unsigned int *gpiop)
+{
+	struct gpio_desc desc;
+	int ret;
+
+	if (devp)
+		*devp = NULL;
+	ret = dm_gpio_lookup_name(name, &desc);
+	if (ret)
+		return ret;
+
 	if (devp)
-		*devp = dev;
+		*devp = desc.dev;
 	if (offsetp)
-		*offsetp = offset;
-	if (gpiop)
-		*gpiop = uc_priv->gpio_base + offset;
+		*offsetp = desc.offset;
+	if (gpiop) {
+		struct gpio_dev_priv *uc_priv = dev_get_uclass_priv(desc.dev);
+
+		*gpiop = uc_priv->gpio_base + desc.offset;
+	}
 
 	return 0;
 }
include/asm-generic/gpio.h +13 -0
index de91e57..b1cf95c 100644
@@ -322,6 +322,19 @@ struct gpio_dev_priv {
 const char *gpio_get_bank_info(struct udevice *dev, int *offset_count);
 
 /**
+ * dm_gpio_lookup_name() - Look up a named GPIO and return its description
+ *
+ * The name of a GPIO is typically its bank name followed by a number from 0.
+ * For example A0 is the first GPIO in bank A. Each bank is a separate driver
+ * model device.
+ *
+ * @name:	Name to look up
+ * @desc:	Returns description, on success
+ * @return 0 if OK, -ve on error
+ */
+int dm_gpio_lookup_name(const char *name, struct gpio_desc *desc);
+
+/**
  * gpio_lookup_name - Look up a GPIO name and return its details
  *
  * This is used to convert a named GPIO into a device, offset and GPIO
Signature · 1 line
2.4.3.573.g4eafbef
#36 lore raw

PATCH v3 18/54 dm: gpio: Add dm_gpio_lookup_name() to look up a GPIO name

Quoted 4 lines · Simon Glass

Provide a driver-model function to look up a GPIO name. Make the standard function use it.

Quoted 8 lines

---

Changes in v3: None
Changes in v2: None

 drivers/gpio/gpio-uclass.c | 34 ++++++++++++++++++++++++++--------
 include/asm-generic/gpio.h | 13 +++++++++++++
 2 files changed, 39 insertions(+), 8 deletions(-)

Applied to u-boot-dm.

#37 lore raw

PATCH v3 19/54 dm: gpio: Add dm_gpio_request() to manually request a GPIO

In reply to Simon Glass

This function can be used for testing to manually request a GPIO for use, without resorting to the legacy GPIO API.

---

Changes in v3: None
Changes in v2: None

 drivers/gpio/gpio-uclass.c |  2 +-
 include/asm-generic/gpio.h | 12 ++++++++++++
 2 files changed, 13 insertions(+), 1 deletion(-)
drivers/gpio/gpio-uclass.c +1 -1
index c6fd580..4efda31 100644
@@ -127,7 +127,7 @@ static int gpio_find_and_xlate(struct gpio_desc *desc,
 	return ops->xlate ? ops->xlate(desc->dev, desc, args) : 0;
 }
 
-static int dm_gpio_request(struct gpio_desc *desc, const char *label)
+int dm_gpio_request(struct gpio_desc *desc, const char *label)
 {
 	struct udevice *dev = desc->dev;
 	struct gpio_dev_priv *uc_priv;
include/asm-generic/gpio.h +12 -0
index b1cf95c..0af599f 100644
@@ -434,6 +434,18 @@ int gpio_request_list_by_name(struct udevice *dev, const char *list_name,
 			      int flags);
 
 /**
+ * dm_gpio_request() - manually request a GPIO
+ *
+ * Note: This function should only be used for testing / debugging. Instead.
+ * use gpio_request_by_name() to pull GPIOs from the device tree.
+ *
+ * @desc:	GPIO description of GPIO to request (see dm_gpio_lookup_name())
+ * @label:	Label to attach to the GPIO while claimed
+ * @return 0 if OK, -ve on error
+ */
+int dm_gpio_request(struct gpio_desc *desc, const char *label);
+
+/**
  * gpio_get_list_count() - Returns the number of GPIOs in a list
  *
  * Counts the GPIOs in a list. See gpio_request_by_name() for additional
Signature · 1 line
2.4.3.573.g4eafbef
#38 lore raw

PATCH v3 19/54 dm: gpio: Add dm_gpio_request() to manually request a GPIO

Quoted 4 lines · Simon Glass

This function can be used for testing to manually request a GPIO for use, without resorting to the legacy GPIO API.

Quoted 8 lines

---

Changes in v3: None
Changes in v2: None

 drivers/gpio/gpio-uclass.c |  2 +-
 include/asm-generic/gpio.h | 12 ++++++++++++
 2 files changed, 13 insertions(+), 1 deletion(-)

Applied to u-boot-dm.

#39 lore raw

PATCH v3 20/54 dm: Add support for register maps (regmap)

In reply to Simon Glass

Add a simple implementaton of register maps, supporting only direct I/O for now. This can be enhanced later to support buses which have registers, such as I2C, SPI and PCI.

It allows drivers which can operate with multiple buses to avoid dealing with the particulars of register access on that bus.

---

Changes in v3: None
Changes in v2: None

 drivers/core/Makefile |  1 +
 drivers/core/regmap.c | 86 +++++++++++++++++++++++++++++++++++++++++++++++++++
 include/regmap.h      | 72 ++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 159 insertions(+)
 create mode 100644 drivers/core/regmap.c
 create mode 100644 include/regmap.h
drivers/core/Makefile +1 -0
index ed21fed..7851824 100644
@@ -10,3 +10,4 @@ obj-$(CONFIG_OF_CONTROL) += simple-bus.o
 endif
 obj-$(CONFIG_DM_DEVICE_REMOVE)	+= device-remove.o
 obj-$(CONFIG_DM)	+= dump.o
+obj-$(CONFIG_OF_CONTROL)	+= regmap.o
drivers/core/regmap.c new file +86 -0

86 lines not on this page · raw message

include/regmap.h new file +72 -0

72 lines not on this page · raw message

Signature · 1 line
2.4.3.573.g4eafbef
#40 lore raw

PATCH v3 20/54 dm: Add support for register maps (regmap)

Quoted 13 lines · Simon Glass

Add a simple implementaton of register maps, supporting only direct I/O for now. This can be enhanced later to support buses which have registers, such as I2C, SPI and PCI.

It allows drivers which can operate with multiple buses to avoid dealing with the particulars of register access on that bus.

---

Changes in v3: None
Changes in v2: None

Quoted 6 lines
 drivers/core/Makefile |  1 +
 drivers/core/regmap.c | 86 +++++++++++++++++++++++++++++++++++++++++++++++++++
 include/regmap.h      | 72 ++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 159 insertions(+)
 create mode 100644 drivers/core/regmap.c
 create mode 100644 include/regmap.h

Applied to u-boot-dm.

#41 lore raw

PATCH v3 21/54 dm: Add support for generic system controllers (syscon)

In reply to Simon Glass

Many SoCs have a number of system controllers which are dealt with as a group by a single driver. It is a pain to have to add lots of compatible strings and/or separate drivers for each. Instead we can identify the controllers by a number and request the address of the one we want.

Add a simple implementation of this which can be used by SoC driver code.

---

Changes in v3: None
Changes in v2: None

 drivers/core/Makefile        |  1 +
 drivers/core/syscon-uclass.c | 73 ++++++++++++++++++++++++++++++++++++++++++++
 include/dm/uclass-id.h       |  1 +
 include/syscon.h             | 56 +++++++++++++++++++++++++++++++++
 4 files changed, 131 insertions(+)
 create mode 100644 drivers/core/syscon-uclass.c
 create mode 100644 include/syscon.h
drivers/core/Makefile +1 -0
index 7851824..54d57e5 100644
@@ -11,3 +11,4 @@ endif
 obj-$(CONFIG_DM_DEVICE_REMOVE)	+= device-remove.o
 obj-$(CONFIG_DM)	+= dump.o
 obj-$(CONFIG_OF_CONTROL)	+= regmap.o
+obj-$(CONFIG_OF_CONTROL)	+= syscon-uclass.o
drivers/core/syscon-uclass.c new file +73 -0

73 lines not on this page · raw message

include/dm/uclass-id.h +1 -0
index c7310d7..24baa5c 100644
@@ -46,6 +46,7 @@ enum uclass_id {
 	UCLASS_SPI,		/* SPI bus */
 	UCLASS_SPI_FLASH,	/* SPI flash */
 	UCLASS_SPI_GENERIC,	/* Generic SPI flash target */
+	UCLASS_SYSCON,		/* System configuration device */
 	UCLASS_THERMAL,		/* Thermal sensor */
 	UCLASS_USB,		/* USB bus */
 	UCLASS_USB_DEV_GENERIC,	/* USB generic device */
include/syscon.h new file +56 -0

56 lines not on this page · raw message

Signature · 1 line
2.4.3.573.g4eafbef
#42 lore raw

PATCH v3 21/54 dm: Add support for generic system controllers (syscon)

Quoted 13 lines · Simon Glass

Many SoCs have a number of system controllers which are dealt with as a group by a single driver. It is a pain to have to add lots of compatible strings and/or separate drivers for each. Instead we can identify the controllers by a number and request the address of the one we want.

Add a simple implementation of this which can be used by SoC driver code.

---

Changes in v3: None
Changes in v2: None

Quoted 7 lines
 drivers/core/Makefile        |  1 +
 drivers/core/syscon-uclass.c | 73 ++++++++++++++++++++++++++++++++++++++++++++
 include/dm/uclass-id.h       |  1 +
 include/syscon.h             | 56 +++++++++++++++++++++++++++++++++
 4 files changed, 131 insertions(+)
 create mode 100644 drivers/core/syscon-uclass.c
 create mode 100644 include/syscon.h

Applied to u-boot-dm.

#43 lore raw

PATCH v3 22/54 dm: Correct the missing method check in cpu_get_info()

In reply to Simon Glass

This is checking the wrong method. Fix it.

---

Changes in v3: None
Changes in v2: None

 drivers/cpu/cpu-uclass.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/cpu/cpu-uclass.c +1 -1
index ab18ee2..ffe250d 100644
@@ -25,7 +25,7 @@ int cpu_get_info(struct udevice *dev, struct cpu_info *info)
 {
 	struct cpu_ops *ops = cpu_get_ops(dev);
 
-	if (!ops->get_desc)
+	if (!ops->get_info)
 		return -ENOSYS;
 
 	return ops->get_info(dev, info);
Signature · 1 line
2.4.3.573.g4eafbef
#44 lore raw

PATCH v3 22/54 dm: Correct the missing method check in cpu_get_info()

Quoted 25 lines · Simon Glass

This is checking the wrong method. Fix it.

---

Changes in v3: None
Changes in v2: None

 drivers/cpu/cpu-uclass.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/cpu/cpu-uclass.c +1 -2
index ab18ee2..ffe250d 100644
@@ -25,7 +25,7 @@ int cpu_get_info(struct udevice *dev, struct cpu_info *info)
 {
        struct cpu_ops *ops = cpu_get_ops(dev);
 
-       if (!ops->get_desc)
+       if (!ops->get_info)
                return -ENOSYS;
 
        return ops->get_info(dev, info);
--
Quoted 2 lines

2.4.3.573.g4eafbef

Applied to u-boot-x86.

#45 lore raw

PATCH v3 23/54 dm: Add support for LEDs

In reply to Simon Glass

Add a simple uclass for LEDs, so that these can be controlled by the device tree and activated when needed. LEDs are referred to by their label.

This implementation requires a driver for each type of LED (e.g GPIO, I2C).

---

Changes in v3: None
Changes in v2: None

 doc/device-tree-bindings/leds/common.txt | 23 ++++++++++++++
 drivers/Kconfig                          |  2 ++
 drivers/Makefile                         |  1 +
 drivers/led/Kconfig                      | 17 +++++++++++
 drivers/led/Makefile                     |  8 +++++
 drivers/led/led-uclass.c                 | 48 ++++++++++++++++++++++++++++++
 include/dm/uclass-id.h                   |  1 +
 include/led.h                            | 51 ++++++++++++++++++++++++++++++++
 scripts/Makefile.spl                     |  1 +
 9 files changed, 152 insertions(+)
 create mode 100644 doc/device-tree-bindings/leds/common.txt
 create mode 100644 drivers/led/Kconfig
 create mode 100644 drivers/led/Makefile
 create mode 100644 drivers/led/led-uclass.c
 create mode 100644 include/led.h
doc/device-tree-bindings/leds/common.txt new file +23 -0
new file mode 100644
index 0000000..2d88816
@@ -0,0 +1,23 @@
+Common leds properties.
+
+Optional properties for child nodes:
+- label : The label for this LED.  If omitted, the label is
+  taken from the node name (excluding the unit address).
+
+- linux,default-trigger :  This parameter, if present, is a
+    string defining the trigger assigned to the LED.  Current triggers are:
+     "backlight" - LED will act as a back-light, controlled by the framebuffer
+		   system
+     "default-on" - LED will turn on (but for leds-gpio see "default-state"
+		    property in Documentation/devicetree/bindings/gpio/led.txt)
+     "heartbeat" - LED "double" flashes at a load average based rate
+     "ide-disk" - LED indicates disk activity
+     "timer" - LED flashes at a fixed, configurable rate
+
+Examples:
+
+system-status {
+	label = "Status";
+	linux,default-trigger = "heartbeat";
+	...
+};
drivers/Kconfig +2 -0
index 1f40887..ee942e2 100644
@@ -20,6 +20,8 @@ source "drivers/net/Kconfig"
 
 source "drivers/input/Kconfig"
 
+source "drivers/led/Kconfig"
+
 source "drivers/serial/Kconfig"
 
 source "drivers/tpm/Kconfig"
drivers/Makefile +1 -0
index 405b64b..c090aba 100644
@@ -7,6 +7,7 @@ obj-$(CONFIG_CPU) += cpu/
 obj-y += crypto/
 obj-$(CONFIG_FPGA) += fpga/
 obj-y += hwmon/
+obj-$(CONFIG_LED) += led/
 obj-y += misc/
 obj-y += pcmcia/
 obj-y += dfu/
drivers/led/Kconfig new file +17 -0
new file mode 100644
index 0000000..e4d9a84
@@ -0,0 +1,17 @@
+config LED
+	bool "Enable LED support"
+	depends on DM
+	help
+	  Many boards have LEDs which can be used to signal status or alerts.
+	  U-Boot provides a uclass API to implement this feature. LED drivers
+	  can provide access to board-specific LEDs. Use of the device tree
+	  for configuration is encouraged.
+
+config SPL_LED_SUPPORT
+	bool "Enable LED support in SPL"
+	depends on LED
+	help
+	  The LED subsystem adds a small amount of overhead to the image.
+	  If this is acceptable and you have a need to use LEDs in SPL,
+	  enable this option. You will need to enable device tree in SPL
+	  for this to work.
drivers/led/Makefile new file +8 -0
new file mode 100644
index 0000000..b39b205
@@ -0,0 +1,8 @@
+#
+# Copyright (c) 2015 Google, Inc
+# Written by Simon Glass <[email protected]>
+#
+# SPDX-License-Identifier:	GPL-2.0+
+#
+
+obj-$(CONFIG_LED) += led-uclass.o
drivers/led/led-uclass.c new file +48 -0

48 lines not on this page · raw message

include/dm/uclass-id.h +1 -0
index 24baa5c..a961648 100644
@@ -33,6 +33,7 @@ enum uclass_id {
 	UCLASS_I2C,		/* I2C bus */
 	UCLASS_I2C_EEPROM,	/* I2C EEPROM device */
 	UCLASS_I2C_GENERIC,	/* Generic I2C device */
+	UCLASS_LED,		/* Light-emitting diode (LED) */
 	UCLASS_LPC,		/* x86 'low pin count' interface */
 	UCLASS_MASS_STORAGE,	/* Mass storage device */
 	UCLASS_MOD_EXP,		/* RSA Mod Exp device */
include/led.h new file +51 -0

51 lines not on this page · raw message

scripts/Makefile.spl +1 -0
index bcc7ca2..6b32618 100644
@@ -64,6 +64,7 @@ libs-$(CONFIG_SPL_SERIAL_SUPPORT) += drivers/serial/
 libs-$(CONFIG_SPL_SPI_FLASH_SUPPORT) += drivers/mtd/spi/
 libs-$(CONFIG_SPL_SPI_SUPPORT) += drivers/spi/
 libs-y += fs/
+libs-$(CONFIG_SPL_LED_SUPPORT) += drivers/led/
 libs-$(CONFIG_SPL_LIBGENERIC_SUPPORT) += lib/
 libs-$(CONFIG_SPL_POWER_SUPPORT) += drivers/power/ drivers/power/pmic/
 libs-$(CONFIG_SPL_MTD_SUPPORT) += drivers/mtd/
Signature · 1 line
2.4.3.573.g4eafbef
#46 lore raw

PATCH v3 23/54 dm: Add support for LEDs

Quoted 11 lines · Simon Glass

Add a simple uclass for LEDs, so that these can be controlled by the device tree and activated when needed. LEDs are referred to by their label.

This implementation requires a driver for each type of LED (e.g GPIO, I2C).

---

Changes in v3: None
Changes in v2: None

Quoted 15 lines
 doc/device-tree-bindings/leds/common.txt | 23 ++++++++++++++
 drivers/Kconfig                          |  2 ++
 drivers/Makefile                         |  1 +
 drivers/led/Kconfig                      | 17 +++++++++++
 drivers/led/Makefile                     |  8 +++++
 drivers/led/led-uclass.c                 | 48 ++++++++++++++++++++++++++++++
 include/dm/uclass-id.h                   |  1 +
 include/led.h                            | 51 ++++++++++++++++++++++++++++++++
 scripts/Makefile.spl                     |  1 +
 9 files changed, 152 insertions(+)
 create mode 100644 doc/device-tree-bindings/leds/common.txt
 create mode 100644 drivers/led/Kconfig
 create mode 100644 drivers/led/Makefile
 create mode 100644 drivers/led/led-uclass.c
 create mode 100644 include/led.h

Applied to u-boot-dm.

#47 lore raw

PATCH v3 24/54 dm: led: Add a driver for GPIO-controlled LEDs

In reply to Simon Glass

Add a simple driver which allows use of LEDs attached to GPIOs. The linux device tree binding is used.

---

Changes in v3: None
Changes in v2: None

 doc/device-tree-bindings/leds/leds-gpio.txt |  52 ++++++++++++++
 drivers/led/Kconfig                         |   9 +++
 drivers/led/Makefile                        |   1 +
 drivers/led/led_gpio.c                      | 101 ++++++++++++++++++++++++++++
 4 files changed, 163 insertions(+)
 create mode 100644 doc/device-tree-bindings/leds/leds-gpio.txt
 create mode 100644 drivers/led/led_gpio.c
doc/device-tree-bindings/leds/leds-gpio.txt new file +52 -0
new file mode 100644
index 0000000..df1b308
@@ -0,0 +1,52 @@
+LEDs connected to GPIO lines
+
+Required properties:
+- compatible : should be "gpio-leds".
+
+Each LED is represented as a sub-node of the gpio-leds device.  Each
+node's name represents the name of the corresponding LED.
+
+LED sub-node properties:
+- gpios :  Should specify the LED's GPIO, see "gpios property" in
+  Documentation/devicetree/bindings/gpio/gpio.txt.  Active low LEDs should be
+  indicated using flags in the GPIO specifier.
+- label :  (optional)
+  see Documentation/devicetree/bindings/leds/common.txt
+- linux,default-trigger :  (optional)
+  see Documentation/devicetree/bindings/leds/common.txt
+- default-state:  (optional) The initial state of the LED.  Valid
+  values are "on", "off", and "keep".  If the LED is already on or off
+  and the default-state property is set the to same value, then no
+  glitch should be produced where the LED momentarily turns off (or
+  on).  The "keep" setting will keep the LED at whatever its current
+  state is, without producing a glitch.  The default is off if this
+  property is not present.
+
+Examples:
+
+leds {
+	compatible = "gpio-leds";
+	hdd {
+		label = "IDE Activity";
+		gpios = <&mcu_pio 0 1>; /* Active low */
+		linux,default-trigger = "ide-disk";
+	};
+
+	fault {
+		gpios = <&mcu_pio 1 0>;
+		/* Keep LED on if BIOS detected hardware fault */
+		default-state = "keep";
+	};
+};
+
+run-control {
+	compatible = "gpio-leds";
+	red {
+		gpios = <&mpc8572 6 0>;
+		default-state = "off";
+	};
+	green {
+		gpios = <&mpc8572 7 0>;
+		default-state = "on";
+	};
+};
drivers/led/Kconfig +9 -0
index e4d9a84..de5feea 100644
@@ -15,3 +15,12 @@ config SPL_LED_SUPPORT
 	  If this is acceptable and you have a need to use LEDs in SPL,
 	  enable this option. You will need to enable device tree in SPL
 	  for this to work.
+
+config LED_GPIO
+	bool "LED support for GPIO-connected LEDs"
+	depends on LED && DM_GPIO
+	help
+	  Enable support for LEDs which are connected to GPIO lines. These
+	  GPIOs may be on the SoC or some other device which provides GPIOs.
+	  The GPIO driver must used driver model. LEDs are configured using
+	  the device tree.
drivers/led/Makefile +1 -0
index b39b205..990129e 100644
@@ -6,3 +6,4 @@
 #
 
 obj-$(CONFIG_LED) += led-uclass.o
+obj-$(CONFIG_LED_GPIO) += led_gpio.o
drivers/led/led_gpio.c new file +101 -0

101 lines not on this page · raw message

Signature · 1 line
2.4.3.573.g4eafbef
#48 lore raw

PATCH v3 24/54 dm: led: Add a driver for GPIO-controlled LEDs

Quoted 9 lines · Simon Glass

Add a simple driver which allows use of LEDs attached to GPIOs. The linux device tree binding is used.

---

Changes in v3: None
Changes in v2: None

Quoted 7 lines
 doc/device-tree-bindings/leds/leds-gpio.txt |  52 ++++++++++++++
 drivers/led/Kconfig                         |   9 +++
 drivers/led/Makefile                        |   1 +
 drivers/led/led_gpio.c                      | 101 ++++++++++++++++++++++++++++
 4 files changed, 163 insertions(+)
 create mode 100644 doc/device-tree-bindings/leds/leds-gpio.txt
 create mode 100644 drivers/led/led_gpio.c

Applied to u-boot-dm.

#49 lore raw

PATCH v3 25/54 spl: Add debugging info for spl_mmc boot

In reply to Simon Glass

Add a few messages to indicate progress and failure.

---

Changes in v3: None
Changes in v2: None

 common/spl/spl_mmc.c | 9 +++++++--
 1 file changed, 7 insertions(+), 2 deletions(-)
common/spl/spl_mmc.c +7 -2
index 552f80d..51add39 100644
@@ -26,11 +26,14 @@ static int mmc_load_image_raw_sector(struct mmc *mmc, unsigned long sector)
 
 	/* read image header to find the image size & load address */
 	count = mmc->block_dev.block_read(0, sector, 1, header);
+	debug("read sector %lx, count=%lu\n", sector, count);
 	if (count == 0)
 		goto end;
 
-	if (image_get_magic(header) != IH_MAGIC)
+	if (image_get_magic(header) != IH_MAGIC) {
+		puts("bad magic\n");
 		return -1;
+	}
 
 	spl_parse_image_header(header);
 
@@ -40,7 +43,9 @@ static int mmc_load_image_raw_sector(struct mmc *mmc, unsigned long sector)
 
 	/* Read the header too to avoid extra memcpy */
 	count = mmc->block_dev.block_read(0, sector, image_size_sectors,
-					  (void *) spl_image.load_addr);
+					  (void *)spl_image.load_addr);
+	debug("read %x sectors to %x\n", image_size_sectors,
+	      spl_image.load_addr);
 
 end:
 	if (count == 0) {
Signature · 1 line
2.4.3.573.g4eafbef
#50 lore raw

PATCH v3 25/54 spl: Add debugging info for spl_mmc boot

Quoted 10 lines · Simon Glass

Add a few messages to indicate progress and failure.

---

Changes in v3: None
Changes in v2: None

 common/spl/spl_mmc.c | 9 +++++++--
 1 file changed, 7 insertions(+), 2 deletions(-)

Applied to u-boot-dm.

#51 lore raw

PATCH v3 26/54 dm: mmc: Add an MMC uclass

In reply to Simon Glass

Add basic support for MMC, providing a uclass which can set up an MMC device. This allows MMC drivers to move to using driver model.

---

Changes in v3: None
Changes in v2: None

 drivers/mmc/Kconfig      | 10 ++++++++++
 drivers/mmc/Makefile     |  2 ++
 drivers/mmc/mmc-uclass.c | 34 ++++++++++++++++++++++++++++++++++
 drivers/mmc/mmc.c        |  2 ++
 include/dm/uclass-id.h   |  1 +
 include/mmc.h            | 22 ++++++++++++++++++++++
 6 files changed, 71 insertions(+)
 create mode 100644 drivers/mmc/mmc-uclass.c
drivers/mmc/Kconfig +10 -0
index 7ba85a2..3e835f7 100644
@@ -1,5 +1,15 @@
 menu "MMC Host controller Support"
 
+config DM_MMC
+	bool "Enable MMC controllers using Driver Model"
+	depends on DM
+	help
+	  This enables the MultiMediaCard (MMC) uclass which suports MMC and
+	  Secure Digital I/O (SDIO) cards. Both removable (SD, micro-SD, etc.)
+	  and non-removable (e.g. eMMC chip) devices are supported. These
+	  appear as block devices in U-Boot and can support filesystems such
+	  as EXT4 and FAT.
+
 config SH_SDHI
 	bool "SuperH/Renesas ARM SoCs on-chip SDHI host controller support"
 	depends on RMOBILE
drivers/mmc/Makefile +2 -0
index ed73687..2680c63 100644
@@ -5,6 +5,8 @@
 # SPDX-License-Identifier:	GPL-2.0+
 #
 
+obj-$(CONFIG_DM_MMC) += mmc-uclass.o
+
 obj-$(CONFIG_ARM_PL180_MMCI) += arm_pl180_mmci.o
 obj-$(CONFIG_BCM2835_SDHCI) += bcm2835_sdhci.o
 obj-$(CONFIG_BFIN_SDH) += bfin_sdh.o
drivers/mmc/mmc-uclass.c new file +34 -0
new file mode 100644
index 0000000..777489f
@@ -0,0 +1,34 @@
+/*
+ * Copyright (C) 2015 Google, Inc
+ * Written by Simon Glass <[email protected]>
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#include <common.h>
+#include <mmc.h>
+#include <dm.h>
+#include <dm/lists.h>
+#include <dm/root.h>
+
+struct mmc *mmc_get_mmc_dev(struct udevice *dev)
+{
+	struct mmc_uclass_priv *upriv;
+
+	if (!device_active(dev))
+		return NULL;
+	upriv = dev_get_uclass_priv(dev);
+	return upriv->mmc;
+}
+
+U_BOOT_DRIVER(mmc) = {
+	.name	= "mmc",
+	.id	= UCLASS_MMC,
+};
+
+UCLASS_DRIVER(mmc) = {
+	.id		= UCLASS_MMC,
+	.name		= "mmc",
+	.flags		= DM_UC_FLAG_SEQ_ALIAS,
+	.per_device_auto_alloc_size = sizeof(struct mmc_uclass_priv),
+};
drivers/mmc/mmc.c +2 -0
index 79e6fee..4eab274 100644
@@ -1761,8 +1761,10 @@ int mmc_initialize(bd_t *bis)
 	INIT_LIST_HEAD (&mmc_devices);
 	cur_dev_num = 0;
 
+#ifndef CONFIG_DM_MMC
 	if (board_mmc_init(bis) < 0)
 		cpu_mmc_init(bis);
+#endif
 
 #ifndef CONFIG_SPL_BUILD
 	print_mmc_devices(',');
include/dm/uclass-id.h +1 -0
index a961648..cba7c0a 100644
@@ -36,6 +36,7 @@ enum uclass_id {
 	UCLASS_LED,		/* Light-emitting diode (LED) */
 	UCLASS_LPC,		/* x86 'low pin count' interface */
 	UCLASS_MASS_STORAGE,	/* Mass storage device */
+	UCLASS_MMC,		/* SD / MMC card or chip */
 	UCLASS_MOD_EXP,		/* RSA Mod Exp device */
 	UCLASS_PCH,		/* x86 platform controller hub */
 	UCLASS_PCI,		/* PCI bus */
include/mmc.h +22 -0
index dd98b3b..cda9a19 100644
@@ -266,6 +266,28 @@
 #define MMC_NUM_BOOT_PARTITION	2
 #define MMC_PART_RPMB           3       /* RPMB partition number */
 
+/* Driver model support */
+
+/**
+ * struct mmc_uclass_priv - Holds information about a device used by the uclass
+ */
+struct mmc_uclass_priv {
+	struct mmc *mmc;
+};
+
+/**
+ * mmc_get_mmc_dev() - get the MMC struct pointer for a device
+ *
+ * Provided that the device is already probed and ready for use, this value
+ * will be available.
+ *
+ * @dev:	Device
+ * @return associated mmc struct pointer if available, else NULL
+ */
+struct mmc *mmc_get_mmc_dev(struct udevice *dev);
+
+/* End of driver model support */
+
 struct mmc_cid {
 	unsigned long psn;
 	unsigned short oid;
Signature · 1 line
2.4.3.573.g4eafbef
#52 lore raw

PATCH v3 26/54 dm: mmc: Add an MMC uclass

Quoted 9 lines · Simon Glass

Add basic support for MMC, providing a uclass which can set up an MMC device. This allows MMC drivers to move to using driver model.

---

Changes in v3: None
Changes in v2: None

Quoted 8 lines
 drivers/mmc/Kconfig      | 10 ++++++++++
 drivers/mmc/Makefile     |  2 ++
 drivers/mmc/mmc-uclass.c | 34 ++++++++++++++++++++++++++++++++++
 drivers/mmc/mmc.c        |  2 ++
 include/dm/uclass-id.h   |  1 +
 include/mmc.h            | 22 ++++++++++++++++++++++
 6 files changed, 71 insertions(+)
 create mode 100644 drivers/mmc/mmc-uclass.c

Applied to u-boot-dm.

#53 lore raw

PATCH v3 27/54 mmc: Avoid using printf() for errors

In reply to Simon Glass

These bloat the code and cause problems for SPL. Use debug() where possible and try to return a useful error code instead.

---

Changes in v3: None
Changes in v2: None

 drivers/mmc/dw_mmc.c | 21 +++++++++++----------
 1 file changed, 11 insertions(+), 10 deletions(-)
drivers/mmc/dw_mmc.c +11 -10
index 53a8aca..8f28d7e 100644
@@ -8,6 +8,7 @@
 
 #include <bouncebuf.h>
 #include <common.h>
+#include <errno.h>
 #include <malloc.h>
 #include <mmc.h>
 #include <dwmmc.h>
@@ -119,7 +120,7 @@ static int dwmci_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd,
 
 	while (dwmci_readl(host, DWMCI_STATUS) & DWMCI_BUSY) {
 		if (get_timer(start) > timeout) {
-			printf("%s: Timeout on data busy\n", __func__);
+			debug("%s: Timeout on data busy\n", __func__);
 			return TIMEOUT;
 		}
 	}
@@ -178,7 +179,7 @@ static int dwmci_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd,
 	}
 
 	if (i == retry) {
-		printf("%s: Timeout.\n", __func__);
+		debug("%s: Timeout.\n", __func__);
 		return TIMEOUT;
 	}
 
@@ -194,8 +195,8 @@ static int dwmci_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd,
 		debug("%s: Response Timeout.\n", __func__);
 		return TIMEOUT;
 	} else if (mask & DWMCI_INTMSK_RE) {
-		printf("%s: Response Error.\n", __func__);
-		return -1;
+		debug("%s: Response Error.\n", __func__);
+		return -EIO;
 	}
 
 
@@ -214,7 +215,7 @@ static int dwmci_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd,
 		do {
 			mask = dwmci_readl(host, DWMCI_RINTSTS);
 			if (mask & (DWMCI_DATA_ERR | DWMCI_DATA_TOUT)) {
-				printf("%s: DATA ERROR!\n", __func__);
+				debug("%s: DATA ERROR!\n", __func__);
 				return -1;
 			}
 		} while (!(mask & DWMCI_INTMSK_DTO));
@@ -251,7 +252,7 @@ static int dwmci_setup_bus(struct dwmci_host *host, u32 freq)
 	else if (host->bus_hz)
 		sclk = host->bus_hz;
 	else {
-		printf("%s: Didn't get source clock value.\n", __func__);
+		debug("%s: Didn't get source clock value.\n", __func__);
 		return -EINVAL;
 	}
 
@@ -270,7 +271,7 @@ static int dwmci_setup_bus(struct dwmci_host *host, u32 freq)
 	do {
 		status = dwmci_readl(host, DWMCI_CMD);
 		if (timeout-- < 0) {
-			printf("%s: Timeout!\n", __func__);
+			debug("%s: Timeout!\n", __func__);
 			return -ETIMEDOUT;
 		}
 	} while (status & DWMCI_CMD_START);
@@ -285,7 +286,7 @@ static int dwmci_setup_bus(struct dwmci_host *host, u32 freq)
 	do {
 		status = dwmci_readl(host, DWMCI_CMD);
 		if (timeout-- < 0) {
-			printf("%s: Timeout!\n", __func__);
+			debug("%s: Timeout!\n", __func__);
 			return -ETIMEDOUT;
 		}
 	} while (status & DWMCI_CMD_START);
@@ -339,8 +340,8 @@ static int dwmci_init(struct mmc *mmc)
 	dwmci_writel(host, DWMCI_PWREN, 1);
 
 	if (!dwmci_wait_reset(host, DWMCI_RESET_ALL)) {
-		printf("%s[%d] Fail-reset!!\n", __func__, __LINE__);
-		return -1;
+		debug("%s[%d] Fail-reset!!\n", __func__, __LINE__);
+		return -EIO;
 	}
 
 	/* Enumerate@400KHz */
Signature · 1 line
2.4.3.573.g4eafbef
#54 lore raw

PATCH v3 27/54 mmc: Avoid using printf() for errors

Quoted 10 lines · Simon Glass

These bloat the code and cause problems for SPL. Use debug() where possible and try to return a useful error code instead.

---

Changes in v3: None
Changes in v2: None

 drivers/mmc/dw_mmc.c | 21 +++++++++++----------

Subject line and description should show this is dwmmc specific.

ChenYu

Quoted 97 lines
 1 file changed, 11 insertions(+), 10 deletions(-)
drivers/mmc/dw_mmc.c +11 -11
index 53a8aca..8f28d7e 100644
@@ -8,6 +8,7 @@
 
 #include <bouncebuf.h>
 #include <common.h>
+#include <errno.h>
 #include <malloc.h>
 #include <mmc.h>
 #include <dwmmc.h>
@@ -119,7 +120,7 @@ static int dwmci_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd,
 
        while (dwmci_readl(host, DWMCI_STATUS) & DWMCI_BUSY) {
                if (get_timer(start) > timeout) {
-                       printf("%s: Timeout on data busy\n", __func__);
+                       debug("%s: Timeout on data busy\n", __func__);
                        return TIMEOUT;
                }
        }
@@ -178,7 +179,7 @@ static int dwmci_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd,
        }
 
        if (i == retry) {
-               printf("%s: Timeout.\n", __func__);
+               debug("%s: Timeout.\n", __func__);
                return TIMEOUT;
        }
 
@@ -194,8 +195,8 @@ static int dwmci_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd,
                debug("%s: Response Timeout.\n", __func__);
                return TIMEOUT;
        } else if (mask & DWMCI_INTMSK_RE) {
-               printf("%s: Response Error.\n", __func__);
-               return -1;
+               debug("%s: Response Error.\n", __func__);
+               return -EIO;
        }
 
 
@@ -214,7 +215,7 @@ static int dwmci_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd,
                do {
                        mask = dwmci_readl(host, DWMCI_RINTSTS);
                        if (mask & (DWMCI_DATA_ERR | DWMCI_DATA_TOUT)) {
-                               printf("%s: DATA ERROR!\n", __func__);
+                               debug("%s: DATA ERROR!\n", __func__);
                                return -1;
                        }
                } while (!(mask & DWMCI_INTMSK_DTO));
@@ -251,7 +252,7 @@ static int dwmci_setup_bus(struct dwmci_host *host, u32 freq)
        else if (host->bus_hz)
                sclk = host->bus_hz;
        else {
-               printf("%s: Didn't get source clock value.\n", __func__);
+               debug("%s: Didn't get source clock value.\n", __func__);
                return -EINVAL;
        }
 
@@ -270,7 +271,7 @@ static int dwmci_setup_bus(struct dwmci_host *host, u32 freq)
        do {
                status = dwmci_readl(host, DWMCI_CMD);
                if (timeout-- < 0) {
-                       printf("%s: Timeout!\n", __func__);
+                       debug("%s: Timeout!\n", __func__);
                        return -ETIMEDOUT;
                }
        } while (status & DWMCI_CMD_START);
@@ -285,7 +286,7 @@ static int dwmci_setup_bus(struct dwmci_host *host, u32 freq)
        do {
                status = dwmci_readl(host, DWMCI_CMD);
                if (timeout-- < 0) {
-                       printf("%s: Timeout!\n", __func__);
+                       debug("%s: Timeout!\n", __func__);
                        return -ETIMEDOUT;
                }
        } while (status & DWMCI_CMD_START);
@@ -339,8 +340,8 @@ static int dwmci_init(struct mmc *mmc)
        dwmci_writel(host, DWMCI_PWREN, 1);
 
        if (!dwmci_wait_reset(host, DWMCI_RESET_ALL)) {
-               printf("%s[%d] Fail-reset!!\n", __func__, __LINE__);
-               return -1;
+               debug("%s[%d] Fail-reset!!\n", __func__, __LINE__);
+               return -EIO;
        }
 
        /* Enumerate at 400KHz */
--

2.4.3.573.g4eafbef

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

#55 lore raw

PATCH v3 28/54 mmc: Add debug() output on read errors

In reply to Simon Glass

Allow read errors to be diagnosed more easily.

---

Changes in v3: None
Changes in v2: None

 drivers/mmc/mmc.c | 8 ++++++--
 1 file changed, 6 insertions(+), 2 deletions(-)
drivers/mmc/mmc.c +6 -2
index 4eab274..da47037 100644
@@ -250,14 +250,18 @@ static ulong mmc_bread(int dev_num, lbaint_t start, lbaint_t blkcnt, void *dst)
 		return 0;
 	}
 
-	if (mmc_set_blocklen(mmc, mmc->read_bl_len))
+	if (mmc_set_blocklen(mmc, mmc->read_bl_len)) {
+		debug("%s: Failed to set blocklen\n", __func__);
 		return 0;
+	}
 
 	do {
 		cur = (blocks_todo > mmc->cfg->b_max) ?
 			mmc->cfg->b_max : blocks_todo;
-		if(mmc_read_blocks(mmc, dst, start, cur) != cur)
+		if (mmc_read_blocks(mmc, dst, start, cur) != cur) {
+			debug("%s: Failed to read blocks\n", __func__);
 			return 0;
+		}
 		blocks_todo -= cur;
 		start += cur;
 		dst += cur * mmc->read_bl_len;
Signature · 1 line
2.4.3.573.g4eafbef
#56 lore raw

PATCH v3 28/54 mmc: Add debug() output on read errors

Quoted 10 lines · Simon Glass

Allow read errors to be diagnosed more easily.

---

Changes in v3: None
Changes in v2: None

 drivers/mmc/mmc.c | 8 ++++++--
 1 file changed, 6 insertions(+), 2 deletions(-)

Applied to u-boot-dm.

#57 lore raw

PATCH v3 29/54 dm: mmc: Allow driver model to be used for MMC in SPL

In reply to Simon Glass

Enable MMC using driver model in SPL for consistency with U-Boot proper.

---

Changes in v3: None
Changes in v2: None

 common/spl/spl_mmc.c | 17 +++++++++++++++--
 1 file changed, 15 insertions(+), 2 deletions(-)
common/spl/spl_mmc.c +15 -2
index 51add39..5f1cfbf 100644
@@ -7,6 +7,7 @@
  * SPDX-License-Identifier:	GPL-2.0+
  */
 #include <common.h>
+#include <dm.h>
 #include <spl.h>
 #include <linux/compiler.h>
 #include <asm/u-boot.h>
@@ -101,9 +102,18 @@ void spl_mmc_load_image(void)
 {
 	struct mmc *mmc;
 	u32 boot_mode;
-	int err;
+	int err = 0;
 	__maybe_unused int part;
 
+#ifdef CONFIG_DM_MMC
+	struct udevice *dev;
+
+	mmc_initialize(NULL);
+	err = uclass_get_device(UCLASS_MMC, 0, &dev);
+	mmc = NULL;
+	if (!err)
+		mmc = mmc_get_mmc_dev(dev);
+#else
 	mmc_initialize(gd->bd);
 
 	/* We register only one device. So, the dev id is always 0 */
@@ -114,8 +124,11 @@ void spl_mmc_load_image(void)
 #endif
 		hang();
 	}
+#endif
+
+	if (!err)
+		err = mmc_init(mmc);
 
-	err = mmc_init(mmc);
 	if (err) {
 #ifdef CONFIG_SPL_LIBCOMMON_SUPPORT
 		printf("spl: mmc init failed with error: %d\n", err);
Signature · 1 line
2.4.3.573.g4eafbef
#58 lore raw

PATCH v3 29/54 dm: mmc: Allow driver model to be used for MMC in SPL

Quoted 10 lines · Simon Glass

Enable MMC using driver model in SPL for consistency with U-Boot proper.

---

Changes in v3: None
Changes in v2: None

 common/spl/spl_mmc.c | 17 +++++++++++++++--
 1 file changed, 15 insertions(+), 2 deletions(-)

Applied to u-boot-dm.

#59 lore raw

PATCH v3 30/54 mmc: Add structure comments for dwmmc

In reply to Simon Glass

It took a little while to figure this out, so this patch adds documentation to help the next person who needs to do this.

---

Changes in v3: None
Changes in v2: None

 include/dwmmc.h | 18 +++++++++++++++++-
 1 file changed, 17 insertions(+), 1 deletion(-)
include/dwmmc.h +17 -1
index 86a5491..7a7555a 100644
@@ -129,8 +129,24 @@
 /* quirks */
 #define DWMCI_QUIRK_DISABLE_SMU		(1 << 0)
 
+/**
+ * struct dwmci_host - Information about a designware MMC host
+ *
+ * @name:	Device name
+ * @ioaddr:	Base I/O address of controller
+ * @quirks:	Quick flags - see DWMCI_QUIRK_...
+ * @caps:	Capabilities - see MMC_MODE_...
+ * @bus_hz:	Bus speed in Hz, if @get_mmc_clk() is NULL
+ * @div:	Arbitrary clock divider value for use by controller
+ * @dev_index:	Arbitrary device index for use by controller
+ * @dev_id:	Arbitrary device ID for use by controller
+ * @buswidth:	Bus width in bits (8 or 4)
+ * @fifoth_val:	Value for FIFOTH register (or 0 to leave unset)
+ * @mmc:	Pointer to generic MMC structure for this device
+ * @priv:	Private pointer for use by controller
+ */
 struct dwmci_host {
-	char *name;
+	const char *name;
 	void *ioaddr;
 	unsigned int quirks;
 	unsigned int caps;
Signature · 1 line
2.4.3.573.g4eafbef
#60 lore raw

PATCH v3 30/54 mmc: Add structure comments for dwmmc

Quoted 11 lines · Simon Glass

It took a little while to figure this out, so this patch adds documentation to help the next person who needs to do this.

---

Changes in v3: None
Changes in v2: None

 include/dwmmc.h | 18 +++++++++++++++++-
 1 file changed, 17 insertions(+), 1 deletion(-)

Applied to u-boot-dm.

#61 lore raw

PATCH v3 31/54 mmc: Support bypass mode with the get_mmc_clk() method

In reply to Simon Glass

Some SoCs want to adjust the input clock to the DWMMC block as a way of controlling the MMC bus clock. Update the get_mmc_clk() method to support this.

---

Changes in v3: None
Changes in v2: None

 drivers/mmc/dw_mmc.c        |  2 +-
 drivers/mmc/exynos_dw_mmc.c |  2 +-
 include/dwmmc.h             | 16 +++++++++++++++-
 3 files changed, 17 insertions(+), 3 deletions(-)
drivers/mmc/dw_mmc.c +1 -1
index 8f28d7e..a034c3f 100644
@@ -248,7 +248,7 @@ static int dwmci_setup_bus(struct dwmci_host *host, u32 freq)
 	 * host->bus_hz should be set by user.
 	 */
 	if (host->get_mmc_clk)
-		sclk = host->get_mmc_clk(host);
+		sclk = host->get_mmc_clk(host, freq);
 	else if (host->bus_hz)
 		sclk = host->bus_hz;
 	else {
drivers/mmc/exynos_dw_mmc.c +1 -1
index e083745..3f702ba 100644
@@ -39,7 +39,7 @@ static void exynos_dwmci_clksel(struct dwmci_host *host)
 	dwmci_writel(host, DWMCI_CLKSEL, priv->sdr_timing);
 }
 
-unsigned int exynos_dwmci_get_clk(struct dwmci_host *host)
+unsigned int exynos_dwmci_get_clk(struct dwmci_host *host, uint freq)
 {
 	unsigned long sclk;
 	int8_t clk_div;
include/dwmmc.h +15 -1
index 7a7555a..25cf42c 100644
@@ -163,7 +163,21 @@ struct dwmci_host {
 
 	void (*clksel)(struct dwmci_host *host);
 	void (*board_init)(struct dwmci_host *host);
-	unsigned int (*get_mmc_clk)(struct dwmci_host *host);
+
+	/**
+	 * Get / set a particular MMC clock frequency
+	 *
+	 * This is used to request the current clock frequency of the clock
+	 * that drives the DWMMC peripheral. The caller will then use this
+	 * information to work out the divider it needs to achieve the
+	 * required MMC bus clock frequency. If you want to handle the
+	 * clock external to DWMMC, use @freq to select the frequency and
+	 * return that value too. Then DWMMC will put itself in bypass mode.
+	 *
+	 * @host:	DWMMC host
+	 * @freq:	Frequency the host is trying to achieve
+	 */
+	unsigned int (*get_mmc_clk)(struct dwmci_host *host, uint freq);
 
 	struct mmc_config cfg;
 };
Signature · 1 line
2.4.3.573.g4eafbef
#62 lore raw

PATCH v3 31/54 mmc: Support bypass mode with the get_mmc_clk() method

Hi,

Quoted 3 lines · Simon Glass

Some SoCs want to adjust the input clock to the DWMMC block as a way of controlling the MMC bus clock. Update the get_mmc_clk() method to support this.

The subject line should probably reflect this is a DWMMC only patch? There are systems that have MMC and don't use the DWMMC controller.

ChenYu

Quoted 71 lines

---

Changes in v3: None
Changes in v2: None

 drivers/mmc/dw_mmc.c        |  2 +-
 drivers/mmc/exynos_dw_mmc.c |  2 +-
 include/dwmmc.h             | 16 +++++++++++++++-
 3 files changed, 17 insertions(+), 3 deletions(-)
drivers/mmc/dw_mmc.c +1 -1
index 8f28d7e..a034c3f 100644
@@ -248,7 +248,7 @@ static int dwmci_setup_bus(struct dwmci_host *host, u32 freq)
         * host->bus_hz should be set by user.
         */
        if (host->get_mmc_clk)
-               sclk = host->get_mmc_clk(host);
+               sclk = host->get_mmc_clk(host, freq);
        else if (host->bus_hz)
                sclk = host->bus_hz;
        else {
drivers/mmc/exynos_dw_mmc.c +1 -1
index e083745..3f702ba 100644
@@ -39,7 +39,7 @@ static void exynos_dwmci_clksel(struct dwmci_host *host)
        dwmci_writel(host, DWMCI_CLKSEL, priv->sdr_timing);
 }
 
-unsigned int exynos_dwmci_get_clk(struct dwmci_host *host)
+unsigned int exynos_dwmci_get_clk(struct dwmci_host *host, uint freq)
 {
        unsigned long sclk;
        int8_t clk_div;
include/dwmmc.h +15 -2
index 7a7555a..25cf42c 100644
@@ -163,7 +163,21 @@ struct dwmci_host {
 
        void (*clksel)(struct dwmci_host *host);
        void (*board_init)(struct dwmci_host *host);
-       unsigned int (*get_mmc_clk)(struct dwmci_host *host);
+
+       /**
+        * Get / set a particular MMC clock frequency
+        *
+        * This is used to request the current clock frequency of the clock
+        * that drives the DWMMC peripheral. The caller will then use this
+        * information to work out the divider it needs to achieve the
+        * required MMC bus clock frequency. If you want to handle the
+        * clock external to DWMMC, use @freq to select the frequency and
+        * return that value too. Then DWMMC will put itself in bypass mode.
+        *
+        * @host:       DWMMC host
+        * @freq:       Frequency the host is trying to achieve
+        */
+       unsigned int (*get_mmc_clk)(struct dwmci_host *host, uint freq);
 
        struct mmc_config cfg;
 };
--

2.4.3.573.g4eafbef

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

#63 lore raw

PATCH v3 31/54 mmc: Support bypass mode with the get_mmc_clk() method

In reply to Simon Glass

Hi, Simon.

Quoted 3 lines · Simon Glass

Some SoCs want to adjust the input clock to the DWMMC block as a way of controlling the MMC bus clock. Update the get_mmc_clk() method to support this.

I didn't see your other patches.
But i don't know this patch's purpose.
I think that @freq usage seems like host->bus_hz ("bus_hz" property), doesn't it?

Best Regards,
Jaehoon Chung

Quoted 66 lines

---

Changes in v3: None
Changes in v2: None

 drivers/mmc/dw_mmc.c        |  2 +-
 drivers/mmc/exynos_dw_mmc.c |  2 +-
 include/dwmmc.h             | 16 +++++++++++++++-
 3 files changed, 17 insertions(+), 3 deletions(-)
drivers/mmc/dw_mmc.c +1 -1
index 8f28d7e..a034c3f 100644
@@ -248,7 +248,7 @@ static int dwmci_setup_bus(struct dwmci_host *host, u32 freq)
 	 * host->bus_hz should be set by user.
 	 */
 	if (host->get_mmc_clk)
-		sclk = host->get_mmc_clk(host);
+		sclk = host->get_mmc_clk(host, freq);
 	else if (host->bus_hz)
 		sclk = host->bus_hz;
 	else {
drivers/mmc/exynos_dw_mmc.c +1 -1
index e083745..3f702ba 100644
@@ -39,7 +39,7 @@ static void exynos_dwmci_clksel(struct dwmci_host *host)
 	dwmci_writel(host, DWMCI_CLKSEL, priv->sdr_timing);
 }
 
-unsigned int exynos_dwmci_get_clk(struct dwmci_host *host)
+unsigned int exynos_dwmci_get_clk(struct dwmci_host *host, uint freq)
 {
 	unsigned long sclk;
 	int8_t clk_div;
include/dwmmc.h +15 -1
index 7a7555a..25cf42c 100644
@@ -163,7 +163,21 @@ struct dwmci_host {
 
 	void (*clksel)(struct dwmci_host *host);
 	void (*board_init)(struct dwmci_host *host);
-	unsigned int (*get_mmc_clk)(struct dwmci_host *host);
+
+	/**
+	 * Get / set a particular MMC clock frequency
+	 *
+	 * This is used to request the current clock frequency of the clock
+	 * that drives the DWMMC peripheral. The caller will then use this
+	 * information to work out the divider it needs to achieve the
+	 * required MMC bus clock frequency. If you want to handle the
+	 * clock external to DWMMC, use @freq to select the frequency and
+	 * return that value too. Then DWMMC will put itself in bypass mode.
+	 *
+	 * @host:	DWMMC host
+	 * @freq:	Frequency the host is trying to achieve
+	 */
+	unsigned int (*get_mmc_clk)(struct dwmci_host *host, uint freq);
 
 	struct mmc_config cfg;
 };
#64 lore raw

PATCH v3 32/54 mmc: Calculate dwmmc FIFO threshold size if not provided

In reply to Simon Glass

We can calculate this. Add code to do this if it is not provided.

---

Changes in v3: None
Changes in v2: None

 drivers/mmc/dw_mmc.c | 10 ++++++++--
 1 file changed, 8 insertions(+), 2 deletions(-)
drivers/mmc/dw_mmc.c +8 -2
index a034c3f..cce2a5d 100644
@@ -355,9 +355,15 @@ static int dwmci_init(struct mmc *mmc)
 	dwmci_writel(host, DWMCI_IDINTEN, 0);
 	dwmci_writel(host, DWMCI_BMOD, 1);
 
-	if (host->fifoth_val) {
-		dwmci_writel(host, DWMCI_FIFOTH, host->fifoth_val);
+	if (!host->fifoth_val) {
+		uint32_t fifo_size;
+
+		fifo_size = dwmci_readl(host, DWMCI_FIFOTH);
+		fifo_size = ((fifo_size & RX_WMARK_MASK) >> RX_WMARK_SHIFT) + 1;
+		host->fifoth_val = MSIZE(0x2) | RX_WMARK(fifo_size / 2 - 1) |
+				TX_WMARK(fifo_size / 2);
 	}
+	dwmci_writel(host, DWMCI_FIFOTH, host->fifoth_val);
 
 	dwmci_writel(host, DWMCI_CLKENA, 0);
 	dwmci_writel(host, DWMCI_CLKSRC, 0);
Signature · 1 line
2.4.3.573.g4eafbef
#65 lore raw

PATCH v3 32/54 mmc: Calculate dwmmc FIFO threshold size if not provided

Hi, Simon.

Quoted 1 line · Simon Glass

We can calculate this. Add code to do this if it is not provided.

Did you consider the kernel side?

Best Regards,
Jaehoon Chung

Quoted 33 lines

---

Changes in v3: None
Changes in v2: None

 drivers/mmc/dw_mmc.c | 10 ++++++++--
 1 file changed, 8 insertions(+), 2 deletions(-)
drivers/mmc/dw_mmc.c +8 -2
index a034c3f..cce2a5d 100644
@@ -355,9 +355,15 @@ static int dwmci_init(struct mmc *mmc)
 	dwmci_writel(host, DWMCI_IDINTEN, 0);
 	dwmci_writel(host, DWMCI_BMOD, 1);
 
-	if (host->fifoth_val) {
-		dwmci_writel(host, DWMCI_FIFOTH, host->fifoth_val);
+	if (!host->fifoth_val) {
+		uint32_t fifo_size;
+
+		fifo_size = dwmci_readl(host, DWMCI_FIFOTH);
+		fifo_size = ((fifo_size & RX_WMARK_MASK) >> RX_WMARK_SHIFT) + 1;
+		host->fifoth_val = MSIZE(0x2) | RX_WMARK(fifo_size / 2 - 1) |
+				TX_WMARK(fifo_size / 2);
 	}
+	dwmci_writel(host, DWMCI_FIFOTH, host->fifoth_val);
 
 	dwmci_writel(host, DWMCI_CLKENA, 0);
 	dwmci_writel(host, DWMCI_CLKSRC, 0);
#66 lore raw

PATCH v3 32/54 mmc: Calculate dwmmc FIFO threshold size if not provided

Hi Jaehoon,

Quoted 7 lines · Jaehoon Chung

Hi, Simon.

Quoted 1 line · Simon Glass

We can calculate this. Add code to do this if it is not provided.

Did you consider the kernel side?

Can you please be more specific?

Regards,
Simon

Quoted 38 lines

Best Regards,
Jaehoon Chung

Quoted 33 lines

---

Changes in v3: None
Changes in v2: None

 drivers/mmc/dw_mmc.c | 10 ++++++++--
 1 file changed, 8 insertions(+), 2 deletions(-)
drivers/mmc/dw_mmc.c +8 -2
index a034c3f..cce2a5d 100644
@@ -355,9 +355,15 @@ static int dwmci_init(struct mmc *mmc)
      dwmci_writel(host, DWMCI_IDINTEN, 0);
      dwmci_writel(host, DWMCI_BMOD, 1);
 
-     if (host->fifoth_val) {
-             dwmci_writel(host, DWMCI_FIFOTH, host->fifoth_val);
+     if (!host->fifoth_val) {
+             uint32_t fifo_size;
+
+             fifo_size = dwmci_readl(host, DWMCI_FIFOTH);
+             fifo_size = ((fifo_size & RX_WMARK_MASK) >> RX_WMARK_SHIFT) + 1;
+             host->fifoth_val = MSIZE(0x2) | RX_WMARK(fifo_size / 2 - 1) |
+                             TX_WMARK(fifo_size / 2);
      }
+     dwmci_writel(host, DWMCI_FIFOTH, host->fifoth_val);
 
      dwmci_writel(host, DWMCI_CLKENA, 0);
      dwmci_writel(host, DWMCI_CLKSRC, 0);
#67 lore raw

PATCH v3 32/54 mmc: Calculate dwmmc FIFO threshold size if not provided

Hi, Simon.

Quoted 4 lines · Simon Glass

Hi Jaehoon,

Quoted 1 line · Jaehoon Chung
Quoted 8 lines
Quoted 6 lines

Hi, Simon.

Quoted 1 line · Simon Glass

We can calculate this. Add code to do this if it is not provided.

Did you consider the kernel side?

Can you please be more specific?

I didn't check now for fifoth value.
But as i know (in my experiment), if it's not defined fifoth_val into kernel dt file, fifoth value is calculated with value of reading register.

Well, i think your patch is right.
(It needs to calculate the exactly fifoth_val.)

The below case should be problem.

1. Calculate and set the fifoth value at bootloader.
fifoth register = 0x203f0040
2. If fifoth_val doesn't set into dt-file(kernel), on kernel side re-calculate fifoth value. Should be fifo_size = 3f, since fifoth register's value is 0x203f0040.
and fifoth register should be set to 0x201e001f.(just example.)

So i will try to find more generic solution for this problem. If i missed something, let me know, plz. :)

Actually, this case is complicated case.

Best Regards,
Jaehoon Chung

Quoted 43 lines

Regards,1
Simon

Quoted 38 lines

Best Regards,
Jaehoon Chung

Quoted 33 lines

---

Changes in v3: None
Changes in v2: None

 drivers/mmc/dw_mmc.c | 10 ++++++++--
 1 file changed, 8 insertions(+), 2 deletions(-)
drivers/mmc/dw_mmc.c +8 -2
index a034c3f..cce2a5d 100644
@@ -355,9 +355,15 @@ static int dwmci_init(struct mmc *mmc)
      dwmci_writel(host, DWMCI_IDINTEN, 0);
      dwmci_writel(host, DWMCI_BMOD, 1);
 
-     if (host->fifoth_val) {
-             dwmci_writel(host, DWMCI_FIFOTH, host->fifoth_val);
+     if (!host->fifoth_val) {
+             uint32_t fifo_size;
+
+             fifo_size = dwmci_readl(host, DWMCI_FIFOTH);
+             fifo_size = ((fifo_size & RX_WMARK_MASK) >> RX_WMARK_SHIFT) + 1;
+             host->fifoth_val = MSIZE(0x2) | RX_WMARK(fifo_size / 2 - 1) |
+                             TX_WMARK(fifo_size / 2);
      }
+     dwmci_writel(host, DWMCI_FIFOTH, host->fifoth_val);
 
      dwmci_writel(host, DWMCI_CLKENA, 0);
      dwmci_writel(host, DWMCI_CLKSRC, 0);
#68 lore raw

PATCH v3 33/54 dm: Add basic support for pin multiplexing (pinctrl)

In reply to Simon Glass

Add a uclass which permits pin multiplexing to be configured for a particular function. It uses the concept of a peripheral ID to specify the peripheral to adjust. Typically peripheral IDs are SPI0, SPI1, MMC0, etc.

The uclass provides two methods:

- get_periph_id() - returns the peripheral ID for a particular driver model device. This can be used to look up (say) an I2C device, and then find its peripheral ID so that the pins for that device can be requested.

- request() - allows a particular function to be requested. This change may impact multiple pins on the chip. For example, an I2C bus requires two pins (clock and data) and the request() method will set up both pins.

This also allows GPIO drivers which sit under the 'pinctrl' device tree node to be detected and used.

At some point this could be expanded to support a full interface with support for the full device tree bindings. In that case the concept of peripheral ID might not be needed.

---

Changes in v3: None
Changes in v2: None

 drivers/Kconfig                  |  2 ++
 drivers/Makefile                 |  1 +
 drivers/pinctrl/Kconfig          | 19 +++++++++++
 drivers/pinctrl/Makefile         |  8 +++++
 drivers/pinctrl/pinctrl-uclass.c | 51 +++++++++++++++++++++++++++
 include/dm/uclass-id.h           |  1 +
 include/pinctrl.h                | 74 ++++++++++++++++++++++++++++++++++++++++
 scripts/Makefile.spl             |  1 +
 8 files changed, 157 insertions(+)
 create mode 100644 drivers/pinctrl/Kconfig
 create mode 100644 drivers/pinctrl/Makefile
 create mode 100644 drivers/pinctrl/pinctrl-uclass.c
 create mode 100644 include/pinctrl.h
drivers/Kconfig +2 -0
index ee942e2..17a61e4 100644
@@ -32,6 +32,8 @@ source "drivers/spi/Kconfig"
 
 source "drivers/gpio/Kconfig"
 
+source "drivers/pinctrl/Kconfig"
+
 source "drivers/power/Kconfig"
 
 source "drivers/hwmon/Kconfig"
drivers/Makefile +1 -0
index c090aba..b68c4ee 100644
@@ -11,6 +11,7 @@ obj-$(CONFIG_LED) += led/
 obj-y += misc/
 obj-y += pcmcia/
 obj-y += dfu/
+obj-$(CONFIG_PINCTRL) += pinctrl/
 obj-y += rtc/
 obj-y += sound/
 obj-y += tpm/
drivers/pinctrl/Kconfig new file +19 -0
new file mode 100644
index 0000000..e667361
@@ -0,0 +1,19 @@
+config PINCTRL
+	bool "Pin multiplexing driver support"
+	help
+	  Support pin multiplexing control in U-Boot. Most SoCs have their own
+	  own multiplexing arrangement where a single pin can be used for
+	  several functions. An SoC pinctrl driver allows the required
+	  function to be selected for each pin. The driver is typically
+	  controlled by the device tree.
+
+config SPL_PINCTRL_SUPPORT
+	bool "Enable pin multiplexing (pinctrl) support in SPL"
+	depends on PINCTRL
+	help
+	  The pinctrl subsystem can add a substantial overhead to the SPL
+	  image since it typically requires quite a few tables either in the
+	  driver or in the device tree. If this is acceptable and you need
+	  to adjust pin multiplexing in SPL in order to boot into U-Boot,
+	  enable this option. You will need to enable device tree in SPL
+	  for this to work.
drivers/pinctrl/Makefile new file +8 -0
new file mode 100644
index 0000000..6e63ee7
@@ -0,0 +1,8 @@
+#
+# Copyright (c) 2015 Google, Inc
+# Written by Simon Glass <[email protected]>
+#
+# SPDX-License-Identifier:	GPL-2.0+
+#
+
+obj-$(CONFIG_PINCTRL) += pinctrl-uclass.o
drivers/pinctrl/pinctrl-uclass.c new file +51 -0

51 lines not on this page · raw message

include/dm/uclass-id.h +1 -0
index cba7c0a..14a1614 100644
@@ -41,6 +41,7 @@ enum uclass_id {
 	UCLASS_PCH,		/* x86 platform controller hub */
 	UCLASS_PCI,		/* PCI bus */
 	UCLASS_PCI_GENERIC,	/* Generic PCI bus device */
+	UCLASS_PINCTRL,		/* Pin multiplexing control */
 	UCLASS_PMIC,		/* PMIC I/O device */
 	UCLASS_REGULATOR,	/* Regulator device */
 	UCLASS_RTC,		/* Real time clock device */
include/pinctrl.h new file +74 -0

74 lines not on this page · raw message

scripts/Makefile.spl +1 -0
index 6b32618..24ca58b 100644
@@ -77,6 +77,7 @@ libs-$(CONFIG_SPL_NET_SUPPORT) += net/
 libs-$(CONFIG_SPL_ETH_SUPPORT) += drivers/net/
 libs-$(CONFIG_SPL_ETH_SUPPORT) += drivers/net/phy/
 libs-$(CONFIG_SPL_USBETH_SUPPORT) += drivers/net/phy/
+libs-$(CONFIG_SPL_PINCTRL_SUPPORT) += drivers/pinctrl/
 libs-$(CONFIG_SPL_MUSB_NEW_SUPPORT) += drivers/usb/musb-new/
 libs-$(CONFIG_SPL_USBETH_SUPPORT) += drivers/usb/gadget/
 libs-$(CONFIG_SPL_WATCHDOG_SUPPORT) += drivers/watchdog/
Signature · 1 line
2.4.3.573.g4eafbef
#69 lore raw

PATCH v3 34/54 dm: power: Avoid case-insensitve match for child names

In reply to Simon Glass

This is not user input (i.e. from the command line). It should be possible to get the case correct and avoid the case-insensitive match. This will help avoid sloppy device tree setups.

---

Changes in v3: None
Changes in v2: None

 drivers/power/pmic/pmic-uclass.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/power/pmic/pmic-uclass.c +1 -1
index 812ac13..40b5135 100644
@@ -55,7 +55,7 @@ int pmic_bind_children(struct udevice *pmic, int offset,
 		child = NULL;
 		for (info = child_info; info->prefix && info->driver; info++) {
 			prefix_len = strlen(info->prefix);
-			if (strncasecmp(info->prefix, node_name, prefix_len))
+			if (strncmp(info->prefix, node_name, prefix_len))
 				continue;
 
 			debug("  - compatible prefix: '%s'\n", info->prefix);
Signature · 1 line
2.4.3.573.g4eafbef
#70 lore raw

PATCH v3 34/54 dm: power: Avoid case-insensitve match for child names

Hello,

Quoted 19 lines · Simon Glass

This is not user input (i.e. from the command line). It should be possible to get the case correct and avoid the case-insensitive match. This will help avoid sloppy device tree setups.

---

Changes in v3: None
Changes in v2: None

  drivers/power/pmic/pmic-uclass.c | 2 +-
  1 file changed, 1 insertion(+), 1 deletion(-)
drivers/power/pmic/pmic-uclass.c +0 -0
index 812ac13..40b5135 100644

drivers/power/pmic/pmic-uclass.c int pmic_bind_children(struct udevice *pmic, int offset, · line 61

Quoted 8 lines
drivers/power/pmic/pmic-uclass.c +1 -1
@@ -55,7 +55,7 @@ int pmic_bind_children(struct udevice *pmic, int offset,
  		child = NULL;
  		for (info = child_info; info->prefix && info->driver; info++) {
  			prefix_len = strlen(info->prefix);
-			if (strncasecmp(info->prefix, node_name, prefix_len))
+			if (strncmp(info->prefix, node_name, prefix_len))
  				continue;
 
  			debug("  - compatible prefix: '%s'\n", info->prefix);

Tested on:
- Odroid U3 (odroid_defconfig)
- Sandbox - ut pmic/regulator

Best regards,

Signature · 4 lines
Przemyslaw Marczak
Samsung R&D Institute Poland
Samsung Electronics
p.marczak at samsung.com
#71 lore raw

PATCH v3 34/54 dm: power: Avoid case-insensitve match for child names

Quoted 40 lines · Przemyslaw Marczak

Hello,

Quoted 29 lines · Simon Glass

This is not user input (i.e. from the command line). It should be possible to get the case correct and avoid the case-insensitive match. This will help avoid sloppy device tree setups.

---

Changes in v3: None
Changes in v2: None

  drivers/power/pmic/pmic-uclass.c | 2 +-
  1 file changed, 1 insertion(+), 1 deletion(-)
drivers/power/pmic/pmic-uclass.c +1 -1
index 812ac13..40b5135 100644
@@ -55,7 +55,7 @@ int pmic_bind_children(struct udevice *pmic, int offset,
                child = NULL;
                for (info = child_info; info->prefix && info->driver;
 info++) {
                        prefix_len = strlen(info->prefix);
-                       if (strncasecmp(info->prefix, node_name,
 prefix_len))
+                       if (strncmp(info->prefix, node_name, prefix_len))
                                continue;
Quoted 3 lines
                        debug("  - compatible prefix: '%s'\n",

info->prefix);

Tested on:
- Odroid U3 (odroid_defconfig)
- Sandbox - ut pmic/regulator

Quoted 2 lines

Thanks for all the testing and review!

Applied to u-boot-dm.

#72 lore raw

PATCH v3 35/54 dm: power: Add regulator flags to centralise auto-set logic

In reply to Simon Glass

Decide when the regulator is set up whether we want to auto-set the voltage or current. This avoids the complex logic spilling into the processing code.

---

Changes in v3: None
Changes in v2: None

 drivers/power/regulator/regulator-uclass.c | 12 ++++++++++++
 include/power/regulator.h                  |  8 ++++++++
 2 files changed, 20 insertions(+)
drivers/power/regulator/regulator-uclass.c +12 -0
index 31ffd44..0f1ca77 100644
@@ -319,6 +319,18 @@ static int regulator_pre_probe(struct udevice *dev)
 	uc_pdata->boot_on = fdtdec_get_bool(gd->fdt_blob, offset,
 					    "regulator-boot-on");
 
+	/* Those values are optional (-ENODATA if unset) */
+	if ((uc_pdata->min_uV != -ENODATA) &&
+	    (uc_pdata->max_uV != -ENODATA) &&
+	    (uc_pdata->min_uV == uc_pdata->max_uV))
+		uc_pdata->flags |= REGULATOR_FLAG_AUTOSET_UV;
+
+	/* Those values are optional (-ENODATA if unset) */
+	if ((uc_pdata->min_uA != -ENODATA) &&
+	    (uc_pdata->max_uA != -ENODATA) &&
+	    (uc_pdata->min_uA == uc_pdata->max_uA))
+		uc_pdata->flags |= REGULATOR_FLAG_AUTOSET_UA;
+
 	return 0;
 }
 
include/power/regulator.h +8 -0
index 03a2cef..79ce0a4 100644
@@ -128,6 +128,11 @@ struct dm_regulator_mode {
 	const char *name;
 };
 
+enum regulator_flag {
+	REGULATOR_FLAG_AUTOSET_UV	= 1 << 0,
+	REGULATOR_FLAG_AUTOSET_UA	= 1 << 1,
+};
+
 /**
  * struct dm_regulator_uclass_platdata - pointed by dev->uclass_platdata, and
  * allocated on each regulator bind. This structure holds an information
@@ -143,6 +148,8 @@ struct dm_regulator_mode {
  * @max_uA*    - maximum amperage (micro Amps)
  * @always_on* - bool type, true or false
  * @boot_on*   - bool type, true or false
+ * TODO(sjg at chromium.org): Consider putting the above two into @flags
+ * @flags:     - flags value (see REGULATOR_FLAG_...)
  * @name**     - fdt regulator name - should be taken from the device tree
  *
  * Note:
@@ -162,6 +169,7 @@ struct dm_regulator_uclass_platdata {
 	bool always_on;
 	bool boot_on;
 	const char *name;
+	int flags;
 };
 
 /* Regulator device operations */
Signature · 1 line
2.4.3.573.g4eafbef
#73 lore raw

PATCH v3 35/54 dm: power: Add regulator flags to centralise auto-set logic

Hello Simon,

Quoted 63 lines · Simon Glass

Decide when the regulator is set up whether we want to auto-set the voltage or current. This avoids the complex logic spilling into the processing code.

---

Changes in v3: None
Changes in v2: None

  drivers/power/regulator/regulator-uclass.c | 12 ++++++++++++
  include/power/regulator.h                  |  8 ++++++++
  2 files changed, 20 insertions(+)
drivers/power/regulator/regulator-uclass.c +12 -0
index 31ffd44..0f1ca77 100644
@@ -319,6 +319,18 @@ static int regulator_pre_probe(struct udevice *dev)
  	uc_pdata->boot_on = fdtdec_get_bool(gd->fdt_blob, offset,
  					    "regulator-boot-on");
 
+	/* Those values are optional (-ENODATA if unset) */
+	if ((uc_pdata->min_uV != -ENODATA) &&
+	    (uc_pdata->max_uV != -ENODATA) &&
+	    (uc_pdata->min_uV == uc_pdata->max_uV))
+		uc_pdata->flags |= REGULATOR_FLAG_AUTOSET_UV;
+
+	/* Those values are optional (-ENODATA if unset) */
+	if ((uc_pdata->min_uA != -ENODATA) &&
+	    (uc_pdata->max_uA != -ENODATA) &&
+	    (uc_pdata->min_uA == uc_pdata->max_uA))
+		uc_pdata->flags |= REGULATOR_FLAG_AUTOSET_UA;
+
  	return 0;
  }
 
include/power/regulator.h +7 -0
index 03a2cef..79ce0a4 100644
@@ -128,6 +128,11 @@ struct dm_regulator_mode {
  	const char *name;
  };
 
+enum regulator_flag {
+	REGULATOR_FLAG_AUTOSET_UV	= 1 << 0,
+	REGULATOR_FLAG_AUTOSET_UA	= 1 << 1,
+};
+
  /**
   * struct dm_regulator_uclass_platdata - pointed by dev->uclass_platdata, and
   * allocated on each regulator bind. This structure holds an information
@@ -143,6 +148,8 @@ struct dm_regulator_mode {
   * @max_uA*    - maximum amperage (micro Amps)
   * @always_on* - bool type, true or false
   * @boot_on*   - bool type, true or false
+ * TODO(sjg at chromium.org): Consider putting the above two into @flags
+ * @flags:     - flags value (see REGULATOR_FLAG_...)
   * @name**     - fdt regulator name - should be taken from the device tree
   *
   * Note:

include/power/regulator.h struct dm_regulator_uclass_platdata { · line 175

Quoted 7 lines
include/power/regulator.h +1 -0
@@ -162,6 +169,7 @@ struct dm_regulator_uclass_platdata {
  	bool always_on;
  	bool boot_on;
  	const char *name;
+	int flags;
  };
 
  /* Regulator device operations */

Tested on:
- Odroid U3 (odroid_defconfig)
- Sandbox - ut pmic/regulator

Best regards,

Signature · 4 lines
Przemyslaw Marczak
Samsung R&D Institute Poland
Samsung Electronics
p.marczak at samsung.com
#74 lore raw

PATCH v3 35/54 dm: power: Add regulator flags to centralise auto-set logic

Quoted 88 lines · Przemyslaw Marczak

Hello Simon,

Quoted 70 lines · Simon Glass

Decide when the regulator is set up whether we want to auto-set the voltage
or current. This avoids the complex logic spilling into the processing code.

---

Changes in v3: None
Changes in v2: None

  drivers/power/regulator/regulator-uclass.c | 12 ++++++++++++
  include/power/regulator.h                  |  8 ++++++++
  2 files changed, 20 insertions(+)
drivers/power/regulator/regulator-uclass.c +12 -0
index 31ffd44..0f1ca77 100644
@@ -319,6 +319,18 @@ static int regulator_pre_probe(struct udevice *dev)
        uc_pdata->boot_on = fdtdec_get_bool(gd->fdt_blob, offset,
                                            "regulator-boot-on");
 
+       /* Those values are optional (-ENODATA if unset) */
+       if ((uc_pdata->min_uV != -ENODATA) &&
+           (uc_pdata->max_uV != -ENODATA) &&
+           (uc_pdata->min_uV == uc_pdata->max_uV))
+               uc_pdata->flags |= REGULATOR_FLAG_AUTOSET_UV;
+
+       /* Those values are optional (-ENODATA if unset) */
+       if ((uc_pdata->min_uA != -ENODATA) &&
+           (uc_pdata->max_uA != -ENODATA) &&
+           (uc_pdata->min_uA == uc_pdata->max_uA))
+               uc_pdata->flags |= REGULATOR_FLAG_AUTOSET_UA;
+
        return 0;
  }
 
include/power/regulator.h +5 -0
index 03a2cef..79ce0a4 100644
@@ -128,6 +128,11 @@ struct dm_regulator_mode {
        const char *name;
  };
 
+enum regulator_flag {
+       REGULATOR_FLAG_AUTOSET_UV       = 1 << 0,
+       REGULATOR_FLAG_AUTOSET_UA       = 1 << 1,
+};
+
  /**
   * struct dm_regulator_uclass_platdata - pointed by

dev->uclass_platdata, and
* allocated on each regulator bind. This structure holds an information

include/power/regulator.h +2 -0
@@ -143,6 +148,8 @@ struct dm_regulator_mode {
   * @max_uA*    - maximum amperage (micro Amps)
   * @always_on* - bool type, true or false
   * @boot_on*   - bool type, true or false
+ * TODO(sjg at chromium.org): Consider putting the above two into @flags
+ * @flags:     - flags value (see REGULATOR_FLAG_...)
   * @name**     - fdt regulator name - should be taken from the device

tree
*
* Note:

include/power/regulator.h struct dm_regulator_uclass_platdata { · line 175

Quoted 7 lines
include/power/regulator.h +1 -0
@@ -162,6 +169,7 @@ struct dm_regulator_uclass_platdata {
        bool always_on;
        bool boot_on;
        const char *name;
+       int flags;
  };
 
  /* Regulator device operations */

Tested on:
- Odroid U3 (odroid_defconfig)
- Sandbox - ut pmic/regulator

Quoted 6 lines

Best regards,
--
Przemyslaw Marczak
Samsung R&D Institute Poland
Samsung Electronics
p.marczak at samsung.com

Applied to u-boot-dm.

#75 lore raw

PATCH v3 36/54 dm: pmic: Split output from function

In reply to Simon Glass

The regulator_autoset() function mixes printf() output and PMIC adjustment code. It provides a boolean to control the output. It is better to avoid missing logic and output, and this permits a smaller SPL code size. So split the output into a separate function.

Also rename the function to have a by_name() suffix, since we would like to be able to pass a device when we know it, and thus avoid the name search.

---

Changes in v3: None
Changes in v2: None

 drivers/power/regulator/regulator-uclass.c | 98 +++++++++++-------------------
 include/power/regulator.h                  | 34 ++++++++---
 include/power/sandbox_pmic.h               |  4 +-
 test/dm/regulator.c                        |  2 +-
 4 files changed, 63 insertions(+), 75 deletions(-)
drivers/power/regulator/regulator-uclass.c +35 -63
index 0f1ca77..687d3b1 100644
@@ -138,87 +138,57 @@ int regulator_get_by_devname(const char *devname, struct udevice **devp)
 	return uclass_get_device_by_name(UCLASS_REGULATOR, devname, devp);
 }
 
-static int failed(int ret, bool verbose, const char *fmt, ...)
+int regulator_autoset(struct udevice *dev)
 {
-	va_list args;
-	char buf[64];
-
-	if (verbose == false)
-		return ret;
+	struct dm_regulator_uclass_platdata *uc_pdata;
+	int ret = 0;
 
-	va_start(args, fmt);
-	vscnprintf(buf, sizeof(buf), fmt, args);
-	va_end(args);
+	uc_pdata = dev_get_uclass_platdata(dev);
+	if (!uc_pdata->always_on && !uc_pdata->boot_on)
+		return -EMEDIUMTYPE;
 
-	printf(buf);
+	if (uc_pdata->flags & REGULATOR_FLAG_AUTOSET_UV)
+		ret = regulator_set_value(dev, uc_pdata->min_uV);
+	if (!ret && (uc_pdata->flags & REGULATOR_FLAG_AUTOSET_UA))
+		ret = regulator_set_current(dev, uc_pdata->min_uA);
 
 	if (!ret)
-		return 0;
-
-	printf(" (ret: %d)", ret);
+		ret = regulator_set_enable(dev, true);
 
 	return ret;
 }
 
-int regulator_autoset(const char *platname,
-		      struct udevice **devp,
-		      bool verbose)
+static void regulator_show(struct udevice *dev, int ret)
 {
 	struct dm_regulator_uclass_platdata *uc_pdata;
-	struct udevice *dev;
-	int ret;
-
-	if (devp)
-		*devp = NULL;
-
-	ret = regulator_get_by_platname(platname, &dev);
-	if (ret) {
-		error("Can get the regulator: %s!", platname);
-		return ret;
-	}
 
 	uc_pdata = dev_get_uclass_platdata(dev);
-	if (!uc_pdata) {
-		error("Can get the regulator %s uclass platdata!", platname);
-		return -ENXIO;
-	}
-
-	if (!uc_pdata->always_on && !uc_pdata->boot_on)
-		goto retdev;
 
-	if (verbose)
-		printf("%s@%s: ", dev->name, uc_pdata->name);
-
-	/* Those values are optional (-ENODATA if unset) */
-	if ((uc_pdata->min_uV != -ENODATA) &&
-	    (uc_pdata->max_uV != -ENODATA) &&
-	    (uc_pdata->min_uV == uc_pdata->max_uV)) {
-		ret = regulator_set_value(dev, uc_pdata->min_uV);
-		if (failed(ret, verbose, "set %d uV", uc_pdata->min_uV))
-			goto exit;
-	}
-
-	/* Those values are optional (-ENODATA if unset) */
-	if ((uc_pdata->min_uA != -ENODATA) &&
-	    (uc_pdata->max_uA != -ENODATA) &&
-	    (uc_pdata->min_uA == uc_pdata->max_uA)) {
-		ret = regulator_set_current(dev, uc_pdata->min_uA);
-		if (failed(ret, verbose, "; set %d uA", uc_pdata->min_uA))
-			goto exit;
-	}
+	printf("%s@%s: ", dev->name, uc_pdata->name);
+	if (uc_pdata->flags & REGULATOR_FLAG_AUTOSET_UV)
+		printf("set %d uV", uc_pdata->min_uV);
+	if (uc_pdata->flags & REGULATOR_FLAG_AUTOSET_UA)
+		printf("; set %d uA", uc_pdata->min_uA);
+	printf("; enabling");
+	if (ret)
+		printf(" (ret: %d)\n", ret);
+	printf("\n");
+}
 
-	ret = regulator_set_enable(dev, true);
-	if (failed(ret, verbose, "; enabling", uc_pdata->min_uA))
-		goto exit;
+int regulator_autoset_by_name(const char *platname, struct udevice **devp)
+{
+	struct udevice *dev;
+	int ret;
 
-retdev:
+	ret = regulator_get_by_platname(platname, &dev);
 	if (devp)
 		*devp = dev;
-exit:
-	if (verbose)
-		printf("\n");
+	if (ret) {
+		debug("Can get the regulator: %s!", platname);
+		return ret;
+	}
 
-	return ret;
+	return regulator_autoset(dev);
 }
 
 int regulator_list_autoset(const char *list_platname[],
@@ -229,7 +199,9 @@ int regulator_list_autoset(const char *list_platname[],
 	int error = 0, i = 0, ret;
 
 	while (list_platname[i]) {
-		ret = regulator_autoset(list_platname[i], &dev, verbose);
+		ret = regulator_autoset_by_name(list_platname[i], &dev);
+		if (ret != -EMEDIUMTYPE && verbose)
+			regulator_show(dev, ret);
 		if (ret & !error)
 			error = ret;
 
include/power/regulator.h +25 -9
index 79ce0a4..86e9c3b 100644
@@ -316,9 +316,28 @@ int regulator_get_mode(struct udevice *dev);
 int regulator_set_mode(struct udevice *dev, int mode_id);
 
 /**
- * regulator_autoset: setup the regulator given by its uclass's platform data
- * name field. The setup depends on constraints found in device's uclass's
- * platform data (struct dm_regulator_uclass_platdata):
+ * regulator_autoset: setup the the voltage/current on a regulator
+ *
+ * The setup depends on constraints found in device's uclass's platform data
+ * (struct dm_regulator_uclass_platdata):
+ *
+ * - Enable - will set - if any of: 'always_on' or 'boot_on' is set to true,
+ *   or if both are unset, then the function returns
+ * - Voltage value - will set - if '.min_uV' and '.max_uV' values are equal
+ * - Current limit - will set - if '.min_uA' and '.max_uA' values are equal
+ *
+ * The function returns on the first-encountered error.
+ *
+ * @platname - expected string for dm_regulator_uclass_platdata .name field
+ * @devp     - returned pointer to the regulator device - if non-NULL passed
+ * @return: 0 on success or negative value of errno.
+ */
+int regulator_autoset(struct udevice *dev);
+
+/**
+ * regulator_autoset_by_name: setup the regulator given by its uclass's
+ * platform data name field. The setup depends on constraints found in device's
+ * uclass's platform data (struct dm_regulator_uclass_platdata):
  * - Enable - will set - if any of: 'always_on' or 'boot_on' is set to true,
  *   or if both are unset, then the function returns
  * - Voltage value - will set - if '.min_uV' and '.max_uV' values are equal
@@ -328,21 +347,18 @@ int regulator_set_mode(struct udevice *dev, int mode_id);
  *
  * @platname - expected string for dm_regulator_uclass_platdata .name field
  * @devp     - returned pointer to the regulator device - if non-NULL passed
- * @verbose  - (true/false) print regulator setup info, or be quiet
  * @return: 0 on success or negative value of errno.
  *
  * The returned 'regulator' device can be used with:
  * - regulator_get/set_*
  */
-int regulator_autoset(const char *platname,
-		      struct udevice **devp,
-		      bool verbose);
+int regulator_autoset_by_name(const char *platname, struct udevice **devp);
 
 /**
  * regulator_list_autoset: setup the regulators given by list of their uclass's
  * platform data name field. The setup depends on constraints found in device's
  * uclass's platform data. The function loops with calls to:
- * regulator_autoset() for each name from the list.
+ * regulator_autoset_by_name() for each name from the list.
  *
  * @list_platname - an array of expected strings for .name field of each
  *                  regulator's uclass platdata
@@ -383,7 +399,7 @@ int regulator_get_by_devname(const char *devname, struct udevice **devp);
  * Search by name, found in regulator uclass platdata.
  *
  * @platname - expected string for uc_pdata->name of regulator uclass platdata
- * @devp     - returned pointer to the regulator device
+ * @devp     - returns pointer to the regulator device or NULL on error
  * @return 0 on success or negative value of errno.
  *
  * The returned 'regulator' device is probed and can be used with:
include/power/sandbox_pmic.h +2 -2
index ae14292..8547674 100644
@@ -117,11 +117,11 @@ enum {
 
 /*
  * Expected regulators setup after call of:
- * - regulator_autoset()
+ * - regulator_autoset_by_name()
  * - regulator_list_autoset()
  */
 
-/* BUCK1: for testing regulator_autoset() */
+/* BUCK1: for testing regulator_autoset_by_name() */
 #define SANDBOX_BUCK1_AUTOSET_EXPECTED_UV	1200000
 #define SANDBOX_BUCK1_AUTOSET_EXPECTED_UA	200000
 #define SANDBOX_BUCK1_AUTOSET_EXPECTED_ENABLE	true
test/dm/regulator.c +1 -1
index d279c04..3d0056f 100644
@@ -210,7 +210,7 @@ static int dm_test_power_regulator_autoset(struct unit_test_state *uts)
 	 * Expected output state: uV=1200000; uA=200000; output enabled
 	 */
 	platname = regulator_names[BUCK1][PLATNAME];
-	ut_assertok(regulator_autoset(platname, &dev_autoset, false));
+	ut_assertok(regulator_autoset_by_name(platname, &dev_autoset));
 
 	/* Check, that the returned device is proper */
 	ut_assertok(regulator_get_by_platname(platname, &dev));
Signature · 1 line
2.4.3.573.g4eafbef
#76 lore raw

PATCH v3 36/54 dm: pmic: Split output from function

Hello Simon,

Quoted 161 lines · Simon Glass

The regulator_autoset() function mixes printf() output and PMIC adjustment code. It provides a boolean to control the output. It is better to avoid missing logic and output, and this permits a smaller SPL code size. So split the output into a separate function.

Also rename the function to have a by_name() suffix, since we would like to be able to pass a device when we know it, and thus avoid the name search.

---

Changes in v3: None
Changes in v2: None

  drivers/power/regulator/regulator-uclass.c | 98 +++++++++++-------------------
  include/power/regulator.h                  | 34 ++++++++---
  include/power/sandbox_pmic.h               |  4 +-
  test/dm/regulator.c                        |  2 +-
  4 files changed, 63 insertions(+), 75 deletions(-)
drivers/power/regulator/regulator-uclass.c +35 -63
index 0f1ca77..687d3b1 100644
@@ -138,87 +138,57 @@ int regulator_get_by_devname(const char *devname, struct udevice **devp)
  	return uclass_get_device_by_name(UCLASS_REGULATOR, devname, devp);
  }
 
-static int failed(int ret, bool verbose, const char *fmt, ...)
+int regulator_autoset(struct udevice *dev)
  {
-	va_list args;
-	char buf[64];
-
-	if (verbose == false)
-		return ret;
+	struct dm_regulator_uclass_platdata *uc_pdata;
+	int ret = 0;
 
-	va_start(args, fmt);
-	vscnprintf(buf, sizeof(buf), fmt, args);
-	va_end(args);
+	uc_pdata = dev_get_uclass_platdata(dev);
+	if (!uc_pdata->always_on && !uc_pdata->boot_on)
+		return -EMEDIUMTYPE;
 
-	printf(buf);
+	if (uc_pdata->flags & REGULATOR_FLAG_AUTOSET_UV)
+		ret = regulator_set_value(dev, uc_pdata->min_uV);
+	if (!ret && (uc_pdata->flags & REGULATOR_FLAG_AUTOSET_UA))
+		ret = regulator_set_current(dev, uc_pdata->min_uA);
 
  	if (!ret)
-		return 0;
-
-	printf(" (ret: %d)", ret);
+		ret = regulator_set_enable(dev, true);
 
  	return ret;
  }
 
-int regulator_autoset(const char *platname,
-		      struct udevice **devp,
-		      bool verbose)
+static void regulator_show(struct udevice *dev, int ret)
  {
  	struct dm_regulator_uclass_platdata *uc_pdata;
-	struct udevice *dev;
-	int ret;
-
-	if (devp)
-		*devp = NULL;
-
-	ret = regulator_get_by_platname(platname, &dev);
-	if (ret) {
-		error("Can get the regulator: %s!", platname);
-		return ret;
-	}
 
  	uc_pdata = dev_get_uclass_platdata(dev);
-	if (!uc_pdata) {
-		error("Can get the regulator %s uclass platdata!", platname);
-		return -ENXIO;
-	}
-
-	if (!uc_pdata->always_on && !uc_pdata->boot_on)
-		goto retdev;
 
-	if (verbose)
-		printf("%s@%s: ", dev->name, uc_pdata->name);
-
-	/* Those values are optional (-ENODATA if unset) */
-	if ((uc_pdata->min_uV != -ENODATA) &&
-	    (uc_pdata->max_uV != -ENODATA) &&
-	    (uc_pdata->min_uV == uc_pdata->max_uV)) {
-		ret = regulator_set_value(dev, uc_pdata->min_uV);
-		if (failed(ret, verbose, "set %d uV", uc_pdata->min_uV))
-			goto exit;
-	}
-
-	/* Those values are optional (-ENODATA if unset) */
-	if ((uc_pdata->min_uA != -ENODATA) &&
-	    (uc_pdata->max_uA != -ENODATA) &&
-	    (uc_pdata->min_uA == uc_pdata->max_uA)) {
-		ret = regulator_set_current(dev, uc_pdata->min_uA);
-		if (failed(ret, verbose, "; set %d uA", uc_pdata->min_uA))
-			goto exit;
-	}
+	printf("%s@%s: ", dev->name, uc_pdata->name);
+	if (uc_pdata->flags & REGULATOR_FLAG_AUTOSET_UV)
+		printf("set %d uV", uc_pdata->min_uV);
+	if (uc_pdata->flags & REGULATOR_FLAG_AUTOSET_UA)
+		printf("; set %d uA", uc_pdata->min_uA);
+	printf("; enabling");
+	if (ret)
+		printf(" (ret: %d)\n", ret);
+	printf("\n");
+}
 
-	ret = regulator_set_enable(dev, true);
-	if (failed(ret, verbose, "; enabling", uc_pdata->min_uA))
-		goto exit;
+int regulator_autoset_by_name(const char *platname, struct udevice **devp)
+{
+	struct udevice *dev;
+	int ret;
 
-retdev:
+	ret = regulator_get_by_platname(platname, &dev);
  	if (devp)
  		*devp = dev;
-exit:
-	if (verbose)
-		printf("\n");
+	if (ret) {
+		debug("Can get the regulator: %s!", platname);
+		return ret;
+	}
 
-	return ret;
+	return regulator_autoset(dev);
  }
 
  int regulator_list_autoset(const char *list_platname[],
@@ -229,7 +199,9 @@ int regulator_list_autoset(const char *list_platname[],
  	int error = 0, i = 0, ret;
 
  	while (list_platname[i]) {
-		ret = regulator_autoset(list_platname[i], &dev, verbose);
+		ret = regulator_autoset_by_name(list_platname[i], &dev);
+		if (ret != -EMEDIUMTYPE && verbose)
+			regulator_show(dev, ret);
  		if (ret & !error)
  			error = ret;
 
include/power/regulator.h +0 -0
index 79ce0a4..86e9c3b 100644

include/power/regulator.h int regulator_get_mode(struct udevice *dev); · line 319

Quoted 7 lines
include/power/regulator.h +1 -3
@@ -316,9 +316,28 @@ int regulator_get_mode(struct udevice *dev);
  int regulator_set_mode(struct udevice *dev, int mode_id);
 
  /**
- * regulator_autoset: setup the regulator given by its uclass's platform data
- * name field. The setup depends on constraints found in device's uclass's
- * platform data (struct dm_regulator_uclass_platdata):
+ * regulator_autoset: setup the the voltage/current on a regulator

duplicated "the"

Quoted 81 lines
include/power/regulator.h +24 -6
+ *
+ * The setup depends on constraints found in device's uclass's platform data
+ * (struct dm_regulator_uclass_platdata):
+ *
+ * - Enable - will set - if any of: 'always_on' or 'boot_on' is set to true,
+ *   or if both are unset, then the function returns
+ * - Voltage value - will set - if '.min_uV' and '.max_uV' values are equal
+ * - Current limit - will set - if '.min_uA' and '.max_uA' values are equal
+ *
+ * The function returns on the first-encountered error.
+ *
+ * @platname - expected string for dm_regulator_uclass_platdata .name field
+ * @devp     - returned pointer to the regulator device - if non-NULL passed
+ * @return: 0 on success or negative value of errno.
+ */
+int regulator_autoset(struct udevice *dev);
+
+/**
+ * regulator_autoset_by_name: setup the regulator given by its uclass's
+ * platform data name field. The setup depends on constraints found in device's
+ * uclass's platform data (struct dm_regulator_uclass_platdata):
   * - Enable - will set - if any of: 'always_on' or 'boot_on' is set to true,
   *   or if both are unset, then the function returns
   * - Voltage value - will set - if '.min_uV' and '.max_uV' values are equal
@@ -328,21 +347,18 @@ int regulator_set_mode(struct udevice *dev, int mode_id);
   *
   * @platname - expected string for dm_regulator_uclass_platdata .name field
   * @devp     - returned pointer to the regulator device - if non-NULL passed
- * @verbose  - (true/false) print regulator setup info, or be quiet
   * @return: 0 on success or negative value of errno.
   *
   * The returned 'regulator' device can be used with:
   * - regulator_get/set_*
   */
-int regulator_autoset(const char *platname,
-		      struct udevice **devp,
-		      bool verbose);
+int regulator_autoset_by_name(const char *platname, struct udevice **devp);
 
  /**
   * regulator_list_autoset: setup the regulators given by list of their uclass's
   * platform data name field. The setup depends on constraints found in device's
   * uclass's platform data. The function loops with calls to:
- * regulator_autoset() for each name from the list.
+ * regulator_autoset_by_name() for each name from the list.
   *
   * @list_platname - an array of expected strings for .name field of each
   *                  regulator's uclass platdata
@@ -383,7 +399,7 @@ int regulator_get_by_devname(const char *devname, struct udevice **devp);
   * Search by name, found in regulator uclass platdata.
   *
   * @platname - expected string for uc_pdata->name of regulator uclass platdata
- * @devp     - returned pointer to the regulator device
+ * @devp     - returns pointer to the regulator device or NULL on error
   * @return 0 on success or negative value of errno.
   *
   * The returned 'regulator' device is probed and can be used with:
include/power/sandbox_pmic.h +2 -2
index ae14292..8547674 100644
@@ -117,11 +117,11 @@ enum {
 
  /*
   * Expected regulators setup after call of:
- * - regulator_autoset()
+ * - regulator_autoset_by_name()
   * - regulator_list_autoset()
   */
 
-/* BUCK1: for testing regulator_autoset() */
+/* BUCK1: for testing regulator_autoset_by_name() */
  #define SANDBOX_BUCK1_AUTOSET_EXPECTED_UV	1200000
  #define SANDBOX_BUCK1_AUTOSET_EXPECTED_UA	200000
  #define SANDBOX_BUCK1_AUTOSET_EXPECTED_ENABLE	true
test/dm/regulator.c +0 -0
index d279c04..3d0056f 100644

test/dm/regulator.c static int dm_test_power_regulator_autoset(struct unit_test_state *uts) · line 216

Quoted 8 lines
test/dm/regulator.c +1 -1
@@ -210,7 +210,7 @@ static int dm_test_power_regulator_autoset(struct unit_test_state *uts)
  	 * Expected output state: uV=1200000; uA=200000; output enabled
  	 */
  	platname = regulator_names[BUCK1][PLATNAME];
-	ut_assertok(regulator_autoset(platname, &dev_autoset, false));
+	ut_assertok(regulator_autoset_by_name(platname, &dev_autoset));
 
  	/* Check, that the returned device is proper */
  	ut_assertok(regulator_get_by_platname(platname, &dev));

Tested on:
- Odroid U3 (odroid_defconfig)
- Sandbox - ut pmic/regulator

Best regards,

Signature · 4 lines
Przemyslaw Marczak
Samsung R&D Institute Poland
Samsung Electronics
p.marczak at samsung.com
#77 lore raw

PATCH v3 36/54 dm: pmic: Split output from function

Quoted 301 lines · Przemyslaw Marczak

Hello Simon,

Quoted 173 lines · Simon Glass

The regulator_autoset() function mixes printf() output and PMIC adjustment code. It provides a boolean to control the output. It is better to avoid missing logic and output, and this permits a smaller SPL code size. So split the output into a separate function.

Also rename the function to have a by_name() suffix, since we would like to be able to pass a device when we know it, and thus avoid the name search.

---

Changes in v3: None
Changes in v2: None

  drivers/power/regulator/regulator-uclass.c | 98
+++++++++++-------------------
  include/power/regulator.h                  | 34 ++++++++---
  include/power/sandbox_pmic.h               |  4 +-
  test/dm/regulator.c                        |  2 +-
  4 files changed, 63 insertions(+), 75 deletions(-)
drivers/power/regulator/regulator-uclass.c +32 -62
index 0f1ca77..687d3b1 100644
@@ -138,87 +138,57 @@ int regulator_get_by_devname(const char *devname,
 struct udevice **devp)
        return uclass_get_device_by_name(UCLASS_REGULATOR, devname, devp);
  }
 
-static int failed(int ret, bool verbose, const char *fmt, ...)
+int regulator_autoset(struct udevice *dev)
  {
-       va_list args;
-       char buf[64];
-
-       if (verbose == false)
-               return ret;
+       struct dm_regulator_uclass_platdata *uc_pdata;
+       int ret = 0;
 
-       va_start(args, fmt);
-       vscnprintf(buf, sizeof(buf), fmt, args);
-       va_end(args);
+       uc_pdata = dev_get_uclass_platdata(dev);
+       if (!uc_pdata->always_on && !uc_pdata->boot_on)
+               return -EMEDIUMTYPE;
 
-       printf(buf);
+       if (uc_pdata->flags & REGULATOR_FLAG_AUTOSET_UV)
+               ret = regulator_set_value(dev, uc_pdata->min_uV);
+       if (!ret && (uc_pdata->flags & REGULATOR_FLAG_AUTOSET_UA))
+               ret = regulator_set_current(dev, uc_pdata->min_uA);
 
        if (!ret)
-               return 0;
-
-       printf(" (ret: %d)", ret);
+               ret = regulator_set_enable(dev, true);
 
        return ret;
  }
 
-int regulator_autoset(const char *platname,
-                     struct udevice **devp,
-                     bool verbose)
+static void regulator_show(struct udevice *dev, int ret)
  {
        struct dm_regulator_uclass_platdata *uc_pdata;
-       struct udevice *dev;
-       int ret;
-
-       if (devp)
-               *devp = NULL;
-
-       ret = regulator_get_by_platname(platname, &dev);
-       if (ret) {
-               error("Can get the regulator: %s!", platname);
-               return ret;
-       }
 
        uc_pdata = dev_get_uclass_platdata(dev);
-       if (!uc_pdata) {
-               error("Can get the regulator %s uclass platdata!",
 platname);
-               return -ENXIO;
-       }
-
-       if (!uc_pdata->always_on && !uc_pdata->boot_on)
-               goto retdev;
 
-       if (verbose)
-               printf("%s@%s: ", dev->name, uc_pdata->name);
-
-       /* Those values are optional (-ENODATA if unset) */
-       if ((uc_pdata->min_uV != -ENODATA) &&
-           (uc_pdata->max_uV != -ENODATA) &&
-           (uc_pdata->min_uV == uc_pdata->max_uV)) {
-               ret = regulator_set_value(dev, uc_pdata->min_uV);
-               if (failed(ret, verbose, "set %d uV", uc_pdata->min_uV))
-                       goto exit;
-       }
-
-       /* Those values are optional (-ENODATA if unset) */
-       if ((uc_pdata->min_uA != -ENODATA) &&
-           (uc_pdata->max_uA != -ENODATA) &&
-           (uc_pdata->min_uA == uc_pdata->max_uA)) {
-               ret = regulator_set_current(dev, uc_pdata->min_uA);
-               if (failed(ret, verbose, "; set %d uA", uc_pdata->min_uA))
-                       goto exit;
-       }
+       printf("%s@%s: ", dev->name, uc_pdata->name);
+       if (uc_pdata->flags & REGULATOR_FLAG_AUTOSET_UV)
+               printf("set %d uV", uc_pdata->min_uV);
+       if (uc_pdata->flags & REGULATOR_FLAG_AUTOSET_UA)
+               printf("; set %d uA", uc_pdata->min_uA);
+       printf("; enabling");
+       if (ret)
+               printf(" (ret: %d)\n", ret);
+       printf("\n");
+}
 
-       ret = regulator_set_enable(dev, true);
-       if (failed(ret, verbose, "; enabling", uc_pdata->min_uA))
-               goto exit;
+int regulator_autoset_by_name(const char *platname, struct udevice
 **devp)
+{
+       struct udevice *dev;
+       int ret;
 
-retdev:
+       ret = regulator_get_by_platname(platname, &dev);
        if (devp)
                *devp = dev;
-exit:
-       if (verbose)
-               printf("\n");
+       if (ret) {
+               debug("Can get the regulator: %s!", platname);
+               return ret;
+       }
 
-       return ret;
+       return regulator_autoset(dev);
  }

int regulator_list_autoset(const char *list_platname[],

drivers/power/regulator/regulator-uclass.c +3 -1
@@ -229,7 +199,9 @@ int regulator_list_autoset(const char
 *list_platname[],
        int error = 0, i = 0, ret;
 
        while (list_platname[i]) {
-               ret = regulator_autoset(list_platname[i], &dev, verbose);
+               ret = regulator_autoset_by_name(list_platname[i], &dev);
+               if (ret != -EMEDIUMTYPE && verbose)
+                       regulator_show(dev, ret);
                if (ret & !error)
                        error = ret;
include/power/regulator.h +0 -1
index 79ce0a4..86e9c3b 100644
@@ -316,9 +316,28 @@ int regulator_get_mode(struct udevice *dev);
  int regulator_set_mode(struct udevice *dev, int mode_id);
 
  /**
- * regulator_autoset: setup the regulator given by its uclass's platform
Quoted 5 lines

data
- * name field. The setup depends on constraints found in device's uclass's
- * platform data (struct dm_regulator_uclass_platdata):
+ * regulator_autoset: setup the the voltage/current on a regulator

duplicated "the"

Quoted 105 lines

+ *
+ * The setup depends on constraints found in device's uclass's platform data
+ * (struct dm_regulator_uclass_platdata):
+ *
+ * - Enable - will set - if any of: 'always_on' or 'boot_on' is set to true,
+ * or if both are unset, then the function returns
+ * - Voltage value - will set - if '.min_uV' and '.max_uV' values are equal
+ * - Current limit - will set - if '.min_uA' and '.max_uA' values are equal
+ *
+ * The function returns on the first-encountered error.
+ *
+ * @platname - expected string for dm_regulator_uclass_platdata .name field
+ * @devp - returned pointer to the regulator device - if non-NULL
passed
+ * @return: 0 on success or negative value of errno.
+ */

include/power/regulator.h +5 -0
+int regulator_autoset(struct udevice *dev);
+
+/**
+ * regulator_autoset_by_name: setup the regulator given by its uclass's
+ * platform data name field. The setup depends on constraints found in

device's
+ * uclass's platform data (struct dm_regulator_uclass_platdata):
* - Enable - will set - if any of: 'always_on' or 'boot_on' is set to
true,
* or if both are unset, then the function returns
* - Voltage value - will set - if '.min_uV' and '.max_uV' values are
equal

include/power/regulator.h +0 -0
@@ -328,21 +347,18 @@ int regulator_set_mode(struct udevice *dev, int
 mode_id);
   *
   * @platname - expected string for dm_regulator_uclass_platdata .name

field
* @devp - returned pointer to the regulator device - if non-NULL
passed
- * @verbose - (true/false) print regulator setup info, or be quiet
* @return: 0 on success or negative value of errno.
*
* The returned 'regulator' device can be used with:
* - regulator_get/set_*
*/

include/power/regulator.h +1 -3
-int regulator_autoset(const char *platname,
-                     struct udevice **devp,
-                     bool verbose);
+int regulator_autoset_by_name(const char *platname, struct udevice

**devp);

/**
* regulator_list_autoset: setup the regulators given by list of their
uclass's
* platform data name field. The setup depends on constraints found in
device's
* uclass's platform data. The function loops with calls to:
- * regulator_autoset() for each name from the list.
+ * regulator_autoset_by_name() for each name from the list.
*
* @list_platname - an array of expected strings for .name field of each
* regulator's uclass platdata

include/power/regulator.h +0 -0
@@ -383,7 +399,7 @@ int regulator_get_by_devname(const char *devname,
 struct udevice **devp);
   * Search by name, found in regulator uclass platdata.
   *
   * @platname - expected string for uc_pdata->name of regulator uclass

platdata
- * @devp - returned pointer to the regulator device
+ * @devp - returns pointer to the regulator device or NULL on error
* @return 0 on success or negative value of errno.
*
* The returned 'regulator' device is probed and can be used with:

include/power/sandbox_pmic.h +2 -2
index ae14292..8547674 100644
@@ -117,11 +117,11 @@ enum {
 
  /*
   * Expected regulators setup after call of:
- * - regulator_autoset()
+ * - regulator_autoset_by_name()
   * - regulator_list_autoset()
   */
 
-/* BUCK1: for testing regulator_autoset() */
+/* BUCK1: for testing regulator_autoset_by_name() */
  #define SANDBOX_BUCK1_AUTOSET_EXPECTED_UV     1200000
  #define SANDBOX_BUCK1_AUTOSET_EXPECTED_UA     200000
  #define SANDBOX_BUCK1_AUTOSET_EXPECTED_ENABLE true
test/dm/regulator.c +1 -1
index d279c04..3d0056f 100644
@@ -210,7 +210,7 @@ static int dm_test_power_regulator_autoset(struct
 unit_test_state *uts)
         * Expected output state: uV=1200000; uA=200000; output enabled
         */
        platname = regulator_names[BUCK1][PLATNAME];
-       ut_assertok(regulator_autoset(platname, &dev_autoset, false));
+       ut_assertok(regulator_autoset_by_name(platname, &dev_autoset));
 
        /* Check, that the returned device is proper */
Quoted 2 lines
        ut_assertok(regulator_get_by_platname(platname, &dev));

Tested on:
- Odroid U3 (odroid_defconfig)
- Sandbox - ut pmic/regulator

Quoted 6 lines

Best regards,
--
Przemyslaw Marczak
Samsung R&D Institute Poland
Samsung Electronics
p.marczak at samsung.com

Applied to u-boot-dm.

#78 lore raw

PATCH v3 37/54 dm: power: Add a function to set up all regulators

In reply to Simon Glass

The device tree provides information about which regulators should be on at boot, or always on. Use this to set them up automatically.

---

Changes in v3: None
Changes in v2: None

 drivers/power/regulator/regulator-uclass.c | 22 ++++++++++++++++++++++
 include/power/regulator.h                  | 11 +++++++++++
 2 files changed, 33 insertions(+)
drivers/power/regulator/regulator-uclass.c +22 -0
index 687d3b1..a2d0b9f 100644
@@ -306,6 +306,28 @@ static int regulator_pre_probe(struct udevice *dev)
 	return 0;
 }
 
+int regulators_enable_boot_on(bool verbose)
+{
+	struct udevice *dev;
+	struct uclass *uc;
+	int ret;
+
+	ret = uclass_get(UCLASS_REGULATOR, &uc);
+	if (ret)
+		return ret;
+	for (uclass_first_device(UCLASS_REGULATOR, &dev);
+	     dev && !ret;
+	     uclass_next_device(&dev)) {
+		ret = regulator_autoset(dev);
+		if (ret == -EMEDIUMTYPE)
+			continue;
+		if (verbose)
+			regulator_show(dev, ret);
+	}
+
+	return ret;
+}
+
 UCLASS_DRIVER(regulator) = {
 	.id		= UCLASS_REGULATOR,
 	.name		= "regulator",
include/power/regulator.h +11 -0
index 86e9c3b..0bdb496 100644
@@ -316,6 +316,17 @@ int regulator_get_mode(struct udevice *dev);
 int regulator_set_mode(struct udevice *dev, int mode_id);
 
 /**
+ * regulators_enable_boot_on() - enable regulators needed for boot
+ *
+ * This enables all regulators which are marked to be on at boot time. This
+ * only works for regulators which don't have a range for voltage/current,
+ * since in that case it is not possible to know which value to use.
+ *
+ * This effectively caslls regulator_autoset() for every regulator.
+ */
+int regulators_enable_boot_on(bool verbose);
+
+/**
  * regulator_autoset: setup the the voltage/current on a regulator
  *
  * The setup depends on constraints found in device's uclass's platform data
Signature · 1 line
2.4.3.573.g4eafbef
#79 lore raw

PATCH v3 37/54 dm: power: Add a function to set up all regulators

Hello Simon,

Quoted 51 lines · Simon Glass

The device tree provides information about which regulators should be on at boot, or always on. Use this to set them up automatically.

---

Changes in v3: None
Changes in v2: None

  drivers/power/regulator/regulator-uclass.c | 22 ++++++++++++++++++++++
  include/power/regulator.h                  | 11 +++++++++++
  2 files changed, 33 insertions(+)
drivers/power/regulator/regulator-uclass.c +22 -0
index 687d3b1..a2d0b9f 100644
@@ -306,6 +306,28 @@ static int regulator_pre_probe(struct udevice *dev)
  	return 0;
  }
 
+int regulators_enable_boot_on(bool verbose)
+{
+	struct udevice *dev;
+	struct uclass *uc;
+	int ret;
+
+	ret = uclass_get(UCLASS_REGULATOR, &uc);
+	if (ret)
+		return ret;
+	for (uclass_first_device(UCLASS_REGULATOR, &dev);
+	     dev && !ret;
+	     uclass_next_device(&dev)) {
+		ret = regulator_autoset(dev);
+		if (ret == -EMEDIUMTYPE)
+			continue;
+		if (verbose)
+			regulator_show(dev, ret);
+	}
+
+	return ret;
+}
+
  UCLASS_DRIVER(regulator) = {
  	.id		= UCLASS_REGULATOR,
  	.name		= "regulator",
include/power/regulator.h +0 -0
index 86e9c3b..0bdb496 100644

include/power/regulator.h int regulator_get_mode(struct udevice *dev); · line 325

Quoted 10 lines
include/power/regulator.h +7 -0
@@ -316,6 +316,17 @@ int regulator_get_mode(struct udevice *dev);
  int regulator_set_mode(struct udevice *dev, int mode_id);
 
  /**
+ * regulators_enable_boot_on() - enable regulators needed for boot
+ *
+ * This enables all regulators which are marked to be on at boot time. This
+ * only works for regulators which don't have a range for voltage/current,
+ * since in that case it is not possible to know which value to use.
+ *
+ * This effectively caslls regulator_autoset() for every regulator.

"calls"

include/power/regulator.h int regulator_get_mode(struct udevice *dev); · line 332

Quoted 8 lines
include/power/regulator.h +4 -0
+ */
+int regulators_enable_boot_on(bool verbose);
+
+/**
   * regulator_autoset: setup the the voltage/current on a regulator
   *
   * The setup depends on constraints found in device's uclass's platform data

Tested on:
- Odroid U3 (odroid_defconfig)
- Sandbox - ut pmic/regulator

Best regards,

Signature · 4 lines
Przemyslaw Marczak
Samsung R&D Institute Poland
Samsung Electronics
p.marczak at samsung.com
#80 lore raw

PATCH v3 37/54 dm: power: Add a function to set up all regulators

Quoted 90 lines · Przemyslaw Marczak

Hello Simon,

Quoted 60 lines · Simon Glass

The device tree provides information about which regulators should be on at boot, or always on. Use this to set them up automatically.

---

Changes in v3: None
Changes in v2: None

  drivers/power/regulator/regulator-uclass.c | 22 ++++++++++++++++++++++
  include/power/regulator.h                  | 11 +++++++++++
  2 files changed, 33 insertions(+)
drivers/power/regulator/regulator-uclass.c +22 -0
index 687d3b1..a2d0b9f 100644
@@ -306,6 +306,28 @@ static int regulator_pre_probe(struct udevice *dev)
        return 0;
  }
 
+int regulators_enable_boot_on(bool verbose)
+{
+       struct udevice *dev;
+       struct uclass *uc;
+       int ret;
+
+       ret = uclass_get(UCLASS_REGULATOR, &uc);
+       if (ret)
+               return ret;
+       for (uclass_first_device(UCLASS_REGULATOR, &dev);
+            dev && !ret;
+            uclass_next_device(&dev)) {
+               ret = regulator_autoset(dev);
+               if (ret == -EMEDIUMTYPE)
+                       continue;
+               if (verbose)
+                       regulator_show(dev, ret);
+       }
+
+       return ret;
+}
+
  UCLASS_DRIVER(regulator) = {
        .id             = UCLASS_REGULATOR,
        .name           = "regulator",
include/power/regulator.h +3 -0
index 86e9c3b..0bdb496 100644
@@ -316,6 +316,17 @@ int regulator_get_mode(struct udevice *dev);
  int regulator_set_mode(struct udevice *dev, int mode_id);
 
  /**
+ * regulators_enable_boot_on() - enable regulators needed for boot
+ *
+ * This enables all regulators which are marked to be on at boot time.
Quoted 6 lines

This
+ * only works for regulators which don't have a range for voltage/current,
+ * since in that case it is not possible to know which value to use.
+ *
+ * This effectively caslls regulator_autoset() for every regulator.

"calls"

Quoted 9 lines

+ */

include/power/regulator.h +3 -0
+int regulators_enable_boot_on(bool verbose);
+
+/**
   * regulator_autoset: setup the the voltage/current on a regulator
   *
   * The setup depends on constraints found in device's uclass's platform

data

Tested on:
- Odroid U3 (odroid_defconfig)
- Sandbox - ut pmic/regulator

Quoted 6 lines

Best regards,
--
Przemyslaw Marczak
Samsung R&D Institute Poland
Samsung Electronics
p.marczak at samsung.com

Applied to u-boot-dm.

#81 lore raw

PATCH v3 38/54 dm: power: Use debug() for errors in regulator uclass

In reply to Simon Glass

To reduce unnecessary code size in an uncommon code path, use debug() where possible(). The driver returns an error which indicates failure.

---

Changes in v3: None
Changes in v2: None

 drivers/power/regulator/regulator-uclass.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/power/regulator/regulator-uclass.c +1 -1
index a2d0b9f..12e141b 100644
@@ -262,7 +262,7 @@ static int regulator_post_bind(struct udevice *dev)
 	if (regulator_name_is_unique(dev, uc_pdata->name))
 		return 0;
 
-	error("\"%s\" of dev: \"%s\", has nonunique value: \"%s\"",
+	debug("\"%s\" of dev: \"%s\", has nonunique value: \"%s\"",
 	      property, dev->name, uc_pdata->name);
 
 	return -EINVAL;
Signature · 1 line
2.4.3.573.g4eafbef
#82 lore raw

PATCH v3 38/54 dm: power: Use debug() for errors in regulator uclass

Hello Simon,

Quoted 18 lines · Simon Glass

To reduce unnecessary code size in an uncommon code path, use debug() where possible(). The driver returns an error which indicates failure.

---

Changes in v3: None
Changes in v2: None

  drivers/power/regulator/regulator-uclass.c | 2 +-
  1 file changed, 1 insertion(+), 1 deletion(-)
drivers/power/regulator/regulator-uclass.c +0 -0
index a2d0b9f..12e141b 100644

drivers/power/regulator/regulator-uclass.c static int regulator_post_bind(struct udevice *dev) · line 268

Quoted 8 lines
drivers/power/regulator/regulator-uclass.c +1 -1
@@ -262,7 +262,7 @@ static int regulator_post_bind(struct udevice *dev)
  	if (regulator_name_is_unique(dev, uc_pdata->name))
  		return 0;
 
-	error("\"%s\" of dev: \"%s\", has nonunique value: \"%s\"",
+	debug("\"%s\" of dev: \"%s\", has nonunique value: \"%s\"",
  	      property, dev->name, uc_pdata->name);
 
  	return -EINVAL;

Tested on:
- Odroid U3 (odroid_defconfig)
- Sandbox - ut pmic/regulator

Best regards,

Signature · 4 lines
Przemyslaw Marczak
Samsung R&D Institute Poland
Samsung Electronics
p.marczak at samsung.com
#83 lore raw

PATCH v3 38/54 dm: power: Use debug() for errors in regulator uclass

Quoted 39 lines · Przemyslaw Marczak

Hello Simon,

Quoted 20 lines · Simon Glass

To reduce unnecessary code size in an uncommon code path, use debug() where possible(). The driver returns an error which indicates failure.

---

Changes in v3: None
Changes in v2: None

  drivers/power/regulator/regulator-uclass.c | 2 +-
  1 file changed, 1 insertion(+), 1 deletion(-)
drivers/power/regulator/regulator-uclass.c +0 -0
index a2d0b9f..12e141b 100644

drivers/power/regulator/regulator-uclass.c static int regulator_post_bind(struct udevice *dev) · line 268

Quoted 8 lines
drivers/power/regulator/regulator-uclass.c +1 -1
@@ -262,7 +262,7 @@ static int regulator_post_bind(struct udevice *dev)
        if (regulator_name_is_unique(dev, uc_pdata->name))
                return 0;
 
-       error("\"%s\" of dev: \"%s\", has nonunique value: \"%s\"",
+       debug("\"%s\" of dev: \"%s\", has nonunique value: \"%s\"",
              property, dev->name, uc_pdata->name);
 
        return -EINVAL;

Tested on:
- Odroid U3 (odroid_defconfig)
- Sandbox - ut pmic/regulator

Quoted 6 lines

Best regards,
--
Przemyslaw Marczak
Samsung R&D Institute Poland
Samsung Electronics
p.marczak at samsung.com

Applied to u-boot-dm.

#84 lore raw

PATCH v3 39/54 dm: pmic: Add functions to adjust PMIC registers

In reply to Simon Glass

It is a common requirement to update some PMIC registers. Provide some simple convenience functions to do this.

---

Changes in v3: None
Changes in v2: None

 drivers/power/pmic/pmic-uclass.c | 32 ++++++++++++++++++++++++++++++++
 include/power/pmic.h             | 34 ++++++++++++++++++++++++++++++++++
 2 files changed, 66 insertions(+)
drivers/power/pmic/pmic-uclass.c +32 -0
index 40b5135..dbab3e3 100644
@@ -139,6 +139,38 @@ int pmic_write(struct udevice *dev, uint reg, const uint8_t *buffer, int len)
 	return ops->write(dev, reg, buffer, len);
 }
 
+int pmic_reg_read(struct udevice *dev, uint reg)
+{
+	u8 byte;
+	int ret;
+
+	ret = pmic_read(dev, reg, &byte, 1);
+	debug("%s: reg=%x, value=%x\n", __func__, reg, byte);
+
+	return ret ? ret : byte;
+}
+
+int pmic_reg_write(struct udevice *dev, uint reg, uint value)
+{
+	u8 byte = value;
+
+	debug("%s: reg=%x, value=%x\n", __func__, reg, value);
+	return pmic_read(dev, reg, &byte, 1);
+}
+
+int pmic_clrsetbits(struct udevice *dev, uint reg, uint clr, uint set)
+{
+	u8 byte;
+	int ret;
+
+	ret = pmic_reg_read(dev, reg);
+	if (ret < 0)
+		return ret;
+	byte = (ret & ~clr) | set;
+
+	return pmic_reg_write(dev, reg, byte);
+}
+
 UCLASS_DRIVER(pmic) = {
 	.id		= UCLASS_PMIC,
 	.name		= "pmic",
include/power/pmic.h +34 -0
index eb152ef..6ba4b6e 100644
@@ -264,6 +264,40 @@ int pmic_reg_count(struct udevice *dev);
  */
 int pmic_read(struct udevice *dev, uint reg, uint8_t *buffer, int len);
 int pmic_write(struct udevice *dev, uint reg, const uint8_t *buffer, int len);
+
+/**
+ * pmic_reg_read() - read a PMIC register value
+ *
+ * @dev:	PMIC device to read
+ * @reg:	Register to read
+ * @return value read on success or negative value of errno.
+ */
+int pmic_reg_read(struct udevice *dev, uint reg);
+
+/**
+ * pmic_reg_write() - write a PMIC register value
+ *
+ * @dev:	PMIC device to write
+ * @reg:	Register to write
+ * @value:	Value to write
+ * @return 0 on success or negative value of errno.
+ */
+int pmic_reg_write(struct udevice *dev, uint reg, uint value);
+
+/**
+ * pmic_clrsetbits() - clear and set bits in a PMIC register
+ *
+ * This reads a register, optionally clears some bits, optionally sets some
+ * bits, then writes the register.
+ *
+ * @dev:	PMIC device to update
+ * @reg:	Register to update
+ * @clr:	Bit mask to clear (set those bits that you want cleared)
+ * @set:	Bit mask to set (set those bits that you want set)
+ * @return 0 on success or negative value of errno.
+ */
+int pmic_clrsetbits(struct udevice *dev, uint reg, uint clr, uint set);
+
 #endif /* CONFIG_DM_PMIC */
 
 #ifdef CONFIG_POWER
Signature · 1 line
2.4.3.573.g4eafbef
#85 lore raw

PATCH v3 39/54 dm: pmic: Add functions to adjust PMIC registers

Hello Simon,

Quoted 92 lines · Simon Glass

It is a common requirement to update some PMIC registers. Provide some simple convenience functions to do this.

---

Changes in v3: None
Changes in v2: None

  drivers/power/pmic/pmic-uclass.c | 32 ++++++++++++++++++++++++++++++++
  include/power/pmic.h             | 34 ++++++++++++++++++++++++++++++++++
  2 files changed, 66 insertions(+)
drivers/power/pmic/pmic-uclass.c +32 -0
index 40b5135..dbab3e3 100644
@@ -139,6 +139,38 @@ int pmic_write(struct udevice *dev, uint reg, const uint8_t *buffer, int len)
  	return ops->write(dev, reg, buffer, len);
  }
 
+int pmic_reg_read(struct udevice *dev, uint reg)
+{
+	u8 byte;
+	int ret;
+
+	ret = pmic_read(dev, reg, &byte, 1);
+	debug("%s: reg=%x, value=%x\n", __func__, reg, byte);
+
+	return ret ? ret : byte;
+}
+
+int pmic_reg_write(struct udevice *dev, uint reg, uint value)
+{
+	u8 byte = value;
+
+	debug("%s: reg=%x, value=%x\n", __func__, reg, value);
+	return pmic_read(dev, reg, &byte, 1);
+}
+
+int pmic_clrsetbits(struct udevice *dev, uint reg, uint clr, uint set)
+{
+	u8 byte;
+	int ret;
+
+	ret = pmic_reg_read(dev, reg);
+	if (ret < 0)
+		return ret;
+	byte = (ret & ~clr) | set;
+
+	return pmic_reg_write(dev, reg, byte);
+}
+
  UCLASS_DRIVER(pmic) = {
  	.id		= UCLASS_PMIC,
  	.name		= "pmic",
include/power/pmic.h +27 -0
index eb152ef..6ba4b6e 100644
@@ -264,6 +264,40 @@ int pmic_reg_count(struct udevice *dev);
   */
  int pmic_read(struct udevice *dev, uint reg, uint8_t *buffer, int len);
  int pmic_write(struct udevice *dev, uint reg, const uint8_t *buffer, int len);
+
+/**
+ * pmic_reg_read() - read a PMIC register value
+ *
+ * @dev:	PMIC device to read
+ * @reg:	Register to read
+ * @return value read on success or negative value of errno.
+ */
+int pmic_reg_read(struct udevice *dev, uint reg);
+
+/**
+ * pmic_reg_write() - write a PMIC register value
+ *
+ * @dev:	PMIC device to write
+ * @reg:	Register to write
+ * @value:	Value to write
+ * @return 0 on success or negative value of errno.
+ */
+int pmic_reg_write(struct udevice *dev, uint reg, uint value);
+
+/**
+ * pmic_clrsetbits() - clear and set bits in a PMIC register
+ *
+ * This reads a register, optionally clears some bits, optionally sets some
+ * bits, then writes the register.
+ *
+ * @dev:	PMIC device to update

include/power/pmic.h int pmic_reg_count(struct udevice *dev); · line 303

Quoted 10 lines
include/power/pmic.h +7 -0
+ * @reg:	Register to update
+ * @clr:	Bit mask to clear (set those bits that you want cleared)
+ * @set:	Bit mask to set (set those bits that you want set)
+ * @return 0 on success or negative value of errno.
+ */
+int pmic_clrsetbits(struct udevice *dev, uint reg, uint clr, uint set);
+
  #endif /* CONFIG_DM_PMIC */
 
  #ifdef CONFIG_POWER

Tested on:
- Odroid U3 (odroid_defconfig)
- Sandbox - ut pmic/regulator

Best regards,

Signature · 4 lines
Przemyslaw Marczak
Samsung R&D Institute Poland
Samsung Electronics
p.marczak at samsung.com
#86 lore raw

PATCH v3 39/54 dm: pmic: Add functions to adjust PMIC registers

Quoted 119 lines · Przemyslaw Marczak

Hello Simon,

Quoted 103 lines · Simon Glass

It is a common requirement to update some PMIC registers. Provide some simple convenience functions to do this.

---

Changes in v3: None
Changes in v2: None

  drivers/power/pmic/pmic-uclass.c | 32 ++++++++++++++++++++++++++++++++
  include/power/pmic.h             | 34 ++++++++++++++++++++++++++++++++++
  2 files changed, 66 insertions(+)
drivers/power/pmic/pmic-uclass.c +32 -0
index 40b5135..dbab3e3 100644
@@ -139,6 +139,38 @@ int pmic_write(struct udevice *dev, uint reg, const
 uint8_t *buffer, int len)
        return ops->write(dev, reg, buffer, len);
  }
 
+int pmic_reg_read(struct udevice *dev, uint reg)
+{
+       u8 byte;
+       int ret;
+
+       ret = pmic_read(dev, reg, &byte, 1);
+       debug("%s: reg=%x, value=%x\n", __func__, reg, byte);
+
+       return ret ? ret : byte;
+}
+
+int pmic_reg_write(struct udevice *dev, uint reg, uint value)
+{
+       u8 byte = value;
+
+       debug("%s: reg=%x, value=%x\n", __func__, reg, value);
+       return pmic_read(dev, reg, &byte, 1);
+}
+
+int pmic_clrsetbits(struct udevice *dev, uint reg, uint clr, uint set)
+{
+       u8 byte;
+       int ret;
+
+       ret = pmic_reg_read(dev, reg);
+       if (ret < 0)
+               return ret;
+       byte = (ret & ~clr) | set;
+
+       return pmic_reg_write(dev, reg, byte);
+}
+
  UCLASS_DRIVER(pmic) = {
        .id             = UCLASS_PMIC,

.name = "pmic",

include/power/pmic.h +24 -0
index eb152ef..6ba4b6e 100644
@@ -264,6 +264,40 @@ int pmic_reg_count(struct udevice *dev);
   */
  int pmic_read(struct udevice *dev, uint reg, uint8_t *buffer, int len);
  int pmic_write(struct udevice *dev, uint reg, const uint8_t *buffer, int
 len);
+
+/**
+ * pmic_reg_read() - read a PMIC register value
+ *
+ * @dev:       PMIC device to read
+ * @reg:       Register to read
+ * @return value read on success or negative value of errno.
+ */
+int pmic_reg_read(struct udevice *dev, uint reg);
+
+/**
+ * pmic_reg_write() - write a PMIC register value
+ *
+ * @dev:       PMIC device to write
+ * @reg:       Register to write
+ * @value:     Value to write
+ * @return 0 on success or negative value of errno.
+ */
+int pmic_reg_write(struct udevice *dev, uint reg, uint value);
+
+/**
+ * pmic_clrsetbits() - clear and set bits in a PMIC register
+ *
+ * This reads a register, optionally clears some bits, optionally sets

some
+ * bits, then writes the register.
+ *

+ * @dev:       PMIC device to update
+ * @reg:       Register to update
+ * @clr:       Bit mask to clear (set those bits that you want cleared)
+ * @set:       Bit mask to set (set those bits that you want set)

+ * @return 0 on success or negative value of errno.
+ */

include/power/pmic.h int pmic_reg_count(struct udevice *dev); · line 303

Quoted 5 lines
include/power/pmic.h +2 -0
+int pmic_clrsetbits(struct udevice *dev, uint reg, uint clr, uint set);
+
  #endif /* CONFIG_DM_PMIC */
 
  #ifdef CONFIG_POWER

Tested on:
- Odroid U3 (odroid_defconfig)
- Sandbox - ut pmic/regulator

Quoted 6 lines

Best regards,
--
Przemyslaw Marczak
Samsung R&D Institute Poland
Samsung Electronics
p.marczak at samsung.com

Applied to u-boot-dm.

#87 lore raw

PATCH v3 40/54 dm: power: Allow use of regulators in SPL

In reply to Simon Glass

This functionality may be useful for setting up regulators early during boot.

---

Changes in v3: None
Changes in v2: None

 scripts/Makefile.spl | 1 +
 1 file changed, 1 insertion(+)
scripts/Makefile.spl +1 -0
index 24ca58b..1e58be9 100644
@@ -67,6 +67,7 @@ libs-y += fs/
 libs-$(CONFIG_SPL_LED_SUPPORT) += drivers/led/
 libs-$(CONFIG_SPL_LIBGENERIC_SUPPORT) += lib/
 libs-$(CONFIG_SPL_POWER_SUPPORT) += drivers/power/ drivers/power/pmic/
+libs-$(CONFIG_SPL_POWER_SUPPORT) += drivers/power/regulator/
 libs-$(CONFIG_SPL_MTD_SUPPORT) += drivers/mtd/
 libs-$(CONFIG_SPL_NAND_SUPPORT) += drivers/mtd/nand/
 libs-$(CONFIG_SPL_DRIVERS_MISC_SUPPORT) += drivers/misc/
Signature · 1 line
2.4.3.573.g4eafbef
#88 lore raw

PATCH v3 40/54 dm: power: Allow use of regulators in SPL

Quoted 11 lines · Simon Glass

his functionality may be useful for setting up regulators early during boot.

---

Changes in v3: None
Changes in v2: None

 scripts/Makefile.spl | 1 +
 1 file changed, 1 insertion(+)

Applied to u-boot-dm.

#89 lore raw

PATCH v3 41/54 Drop CONFIG_ERRNO_STR from SPL

In reply to Simon Glass

This bloats the code size quite a bit and is less useful in SPL where there is no command line.

Avoid including this code in SPL.

---

Changes in v3: None
Changes in v2: None

 lib/Makefile | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
lib/Makefile +1 -1
index ca72187..1139f9b 100644
@@ -23,6 +23,7 @@ obj-$(CONFIG_USB_TTY) += circbuf.o
 obj-y += crc7.o
 obj-y += crc8.o
 obj-y += crc16.o
+obj-$(CONFIG_ERRNO_STR) += errno_str.o
 obj-$(CONFIG_FIT) += fdtdec_common.o
 obj-$(CONFIG_OF_CONTROL) += fdtdec_common.o
 obj-$(CONFIG_OF_CONTROL) += fdtdec.o
@@ -59,7 +60,6 @@ endif
 obj-$(CONFIG_ADDR_MAP) += addr_map.o
 obj-y += hashtable.o
 obj-y += errno.o
-obj-$(CONFIG_ERRNO_STR) += errno_str.o
 obj-y += display_options.o
 obj-$(CONFIG_BCH) += bch.o
 obj-y += crc32.o
Signature · 1 line
2.4.3.573.g4eafbef
#90 lore raw

PATCH v3 41/54 Drop CONFIG_ERRNO_STR from SPL

Quoted 5 lines · Simon Glass

This bloats the code size quite a bit and is less useful in SPL where there is no command line.

Avoid including this code in SPL.

Quoted 8 lines

---

Changes in v3: None
Changes in v2: None

 lib/Makefile | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

Applied to u-boot-dm.

#91 lore raw

PATCH v3 42/54 dm: Add support for RAM drivers

In reply to Simon Glass

Add support for a driver which sets up DRAM and can return information about the amount of RAM available. This is a first step towards moving RAM init to driver model.

---

Changes in v3: None
Changes in v2: None

 drivers/Kconfig          |  2 ++
 drivers/Makefile         |  1 +
 drivers/ram/Kconfig      | 18 ++++++++++++++++++
 drivers/ram/Makefile     |  7 +++++++
 drivers/ram/ram-uclass.c | 28 ++++++++++++++++++++++++++++
 include/dm/uclass-id.h   |  1 +
 include/ram.h            | 38 ++++++++++++++++++++++++++++++++++++++
 scripts/Makefile.spl     |  1 +
 8 files changed, 96 insertions(+)
 create mode 100644 drivers/ram/Kconfig
 create mode 100644 drivers/ram/Makefile
 create mode 100644 drivers/ram/ram-uclass.c
 create mode 100644 include/ram.h
drivers/Kconfig +2 -0
index 17a61e4..7c9eefc 100644
@@ -36,6 +36,8 @@ source "drivers/pinctrl/Kconfig"
 
 source "drivers/power/Kconfig"
 
+source "drivers/ram/Kconfig"
+
 source "drivers/hwmon/Kconfig"
 
 source "drivers/watchdog/Kconfig"
drivers/Makefile +1 -0
index b68c4ee..39b7919 100644
@@ -12,6 +12,7 @@ obj-y += misc/
 obj-y += pcmcia/
 obj-y += dfu/
 obj-$(CONFIG_PINCTRL) += pinctrl/
+obj-$(CONFIG_RAM) += ram/
 obj-y += rtc/
 obj-y += sound/
 obj-y += tpm/
drivers/ram/Kconfig new file +18 -0
new file mode 100644
index 0000000..642a2d8
@@ -0,0 +1,18 @@
+config RAM
+	bool "Enable RAM drivers using Driver Model"
+	depends on DM
+	help
+	  This allows drivers to be provided for SDRAM and other RAM
+	  controllers and their type to be specified in the board's device
+	  tree. Generally some parameters are required to set up the RAM and
+	  the RAM size can either be statically defined or dynamically
+	  detected.
+
+config SPL_RAM_SUPPORT
+	bool "Enable RAM support in SPL"
+	depends on RAM
+	help
+	  The RAM subsystem adds a small amount of overhead to the image.
+	  If this is acceptable and you have a need to use RAM drivers in
+	  SPL, enable this option. It might provide a cleaner interface to
+	  setting up RAM (e.g. SDRAM / DDR) within SPL.
drivers/ram/Makefile new file +7 -0
new file mode 100644
index 0000000..4494d81
@@ -0,0 +1,7 @@
+#
+# Copyright (c) 2015 Google, Inc
+# Wolfgang Denk, DENX Software Engineering, wd at denx.de.
+#
+# SPDX-License-Identifier:      GPL-2.0+
+#
+obj-$(CONFIG_RAM) += ram-uclass.o
drivers/ram/ram-uclass.c new file +28 -0
new file mode 100644
index 0000000..2f1fbe7
@@ -0,0 +1,28 @@
+/*
+ * Copyright (C) 2015 Google, Inc
+ * Written by Simon Glass <[email protected]>
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#include <common.h>
+#include <ram.h>
+#include <dm.h>
+#include <errno.h>
+#include <dm/lists.h>
+#include <dm/root.h>
+
+int ram_get_info(struct udevice *dev, struct ram_info *info)
+{
+	struct ram_ops *ops = ram_get_ops(dev);
+
+	if (!ops->get_info)
+		return -ENOSYS;
+
+	return ops->get_info(dev, info);
+}
+
+UCLASS_DRIVER(ram) = {
+	.id		= UCLASS_RAM,
+	.name		= "ram",
+};
include/dm/uclass-id.h +1 -0
index 14a1614..5bb602f 100644
@@ -28,6 +28,7 @@ enum uclass_id {
 	UCLASS_CPU,		/* CPU, typically part of an SoC */
 	UCLASS_CROS_EC,		/* Chrome OS EC */
 	UCLASS_DISPLAY_PORT,	/* Display port video */
+	UCLASS_RAM,		/* RAM controller */
 	UCLASS_ETH,		/* Ethernet device */
 	UCLASS_GPIO,		/* Bank of general-purpose I/O pins */
 	UCLASS_I2C,		/* I2C bus */
include/ram.h new file +38 -0
new file mode 100644
index 0000000..e2172a8
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2015 Google, Inc
+ * Written by Simon Glass <[email protected]>
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#ifndef __RAM_H
+#define __RAM_H
+
+struct ram_info {
+	phys_addr_t base;
+	size_t size;
+};
+
+struct ram_ops {
+	/**
+	 * get_info() - Get basic memory info
+	 *
+	 * @dev:	Device to check (UCLASS_RAM)
+	 * @info:	Place to put info
+	 * @return 0 if OK, -ve on error
+	 */
+	int (*get_info)(struct udevice *dev, struct ram_info *info);
+};
+
+#define ram_get_ops(dev)        ((struct ram_ops *)(dev)->driver->ops)
+
+/**
+ * ram_get_info() - Get information about a RAM device
+ *
+ * @dev:	Device to check (UCLASS_RAM)
+ * @info:	Returns RAM info
+ * @return 0 if OK, -ve on error
+ */
+int ram_get_info(struct udevice *dev, struct ram_info *info);
+
+#endif
scripts/Makefile.spl +1 -0
index 1e58be9..c4e83bb 100644
@@ -79,6 +79,7 @@ libs-$(CONFIG_SPL_ETH_SUPPORT) += drivers/net/
 libs-$(CONFIG_SPL_ETH_SUPPORT) += drivers/net/phy/
 libs-$(CONFIG_SPL_USBETH_SUPPORT) += drivers/net/phy/
 libs-$(CONFIG_SPL_PINCTRL_SUPPORT) += drivers/pinctrl/
+libs-$(CONFIG_SPL_RAM_SUPPORT) += drivers/ram/
 libs-$(CONFIG_SPL_MUSB_NEW_SUPPORT) += drivers/usb/musb-new/
 libs-$(CONFIG_SPL_USBETH_SUPPORT) += drivers/usb/gadget/
 libs-$(CONFIG_SPL_WATCHDOG_SUPPORT) += drivers/watchdog/
Signature · 1 line
2.4.3.573.g4eafbef
#92 lore raw

PATCH v3 42/54 dm: Add support for RAM drivers

Quoted 10 lines · Simon Glass

Add support for a driver which sets up DRAM and can return information about the amount of RAM available. This is a first step towards moving RAM init to driver model.

---

Changes in v3: None
Changes in v2: None

Quoted 13 lines
 drivers/Kconfig          |  2 ++
 drivers/Makefile         |  1 +
 drivers/ram/Kconfig      | 18 ++++++++++++++++++
 drivers/ram/Makefile     |  7 +++++++
 drivers/ram/ram-uclass.c | 28 ++++++++++++++++++++++++++++
 include/dm/uclass-id.h   |  1 +
 include/ram.h            | 38 ++++++++++++++++++++++++++++++++++++++
 scripts/Makefile.spl     |  1 +
 8 files changed, 96 insertions(+)
 create mode 100644 drivers/ram/Kconfig
 create mode 100644 drivers/ram/Makefile
 create mode 100644 drivers/ram/ram-uclass.c
 create mode 100644 include/ram.h

Applied to u-boot-dm.

#93 lore raw

PATCH v3 43/54 dm: spi: Make local functions static

In reply to Simon Glass

Several functions in this file should be marked as static. Update them.

---

Changes in v3: None
Changes in v2: None

 drivers/spi/spi-uclass.c | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)
drivers/spi/spi-uclass.c +4 -4
index 737ae64..d666272 100644
@@ -95,13 +95,13 @@ int spi_xfer(struct spi_slave *slave, unsigned int bitlen,
 	return spi_get_ops(bus)->xfer(dev, bitlen, dout, din, flags);
 }
 
-int spi_post_bind(struct udevice *dev)
+static int spi_post_bind(struct udevice *dev)
 {
 	/* Scan the bus for devices */
 	return dm_scan_fdt_node(dev, gd->fdt_blob, dev->of_offset, false);
 }
 
-int spi_child_post_bind(struct udevice *dev)
+static int spi_child_post_bind(struct udevice *dev)
 {
 	struct dm_spi_slave_platdata *plat = dev_get_parent_platdata(dev);
 
@@ -111,7 +111,7 @@ int spi_child_post_bind(struct udevice *dev)
 	return spi_slave_ofdata_to_platdata(gd->fdt_blob, dev->of_offset, plat);
 }
 
-int spi_post_probe(struct udevice *bus)
+static int spi_post_probe(struct udevice *bus)
 {
 	struct dm_spi_bus *spi = dev_get_uclass_priv(bus);
 
@@ -121,7 +121,7 @@ int spi_post_probe(struct udevice *bus)
 	return 0;
 }
 
-int spi_child_pre_probe(struct udevice *dev)
+static int spi_child_pre_probe(struct udevice *dev)
 {
 	struct dm_spi_slave_platdata *plat = dev_get_parent_platdata(dev);
 	struct spi_slave *slave = dev_get_parentdata(dev);
Signature · 1 line
2.4.3.573.g4eafbef
#94 lore raw

PATCH v3 43/54 dm: spi: Make local functions static

Quoted 10 lines · Simon Glass

Several functions in this file should be marked as static. Update them.

---

Changes in v3: None
Changes in v2: None

 drivers/spi/spi-uclass.c | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

Applied to u-boot-dm.

#95 lore raw

PATCH v3 44/54 ns16550: Improve debug UART so it can work with 32-bit access

In reply to Simon Glass

Since Rockchip requires 32-bit serial access, add this to the driver. Refactor a little to make this easier.

---

Changes in v3: None
Changes in v2: None

 drivers/serial/ns16550.c | 36 +++++++++++++++++++++---------------
 1 file changed, 21 insertions(+), 15 deletions(-)
drivers/serial/ns16550.c +21 -15
index 9b044a3..c8a77e2 100644
@@ -246,6 +246,17 @@ int NS16550_tstc(NS16550_t com_port)
 
 #include <debug_uart.h>
 
+#define serial_dout(reg, value)	\
+	serial_out_shift((char *)com_port + \
+		((char *)reg - (char *)com_port) * \
+			(1 << CONFIG_DEBUG_UART_SHIFT), \
+		CONFIG_DEBUG_UART_SHIFT, value)
+#define serial_din(reg) \
+	serial_in_shift((char *)com_port + \
+		((char *)reg - (char *)com_port) * \
+			(1 << CONFIG_DEBUG_UART_SHIFT), \
+		CONFIG_DEBUG_UART_SHIFT)
+
 void debug_uart_init(void)
 {
 	struct NS16550 *com_port = (struct NS16550 *)CONFIG_DEBUG_UART_BASE;
@@ -259,28 +270,23 @@ void debug_uart_init(void)
 	 */
 	baud_divisor = calc_divisor(com_port, CONFIG_DEBUG_UART_CLOCK,
 				    CONFIG_BAUDRATE);
-	serial_out_shift(&com_port->ier, CONFIG_DEBUG_UART_SHIFT,
-			 CONFIG_SYS_NS16550_IER);
-	serial_out_shift(&com_port->mcr, CONFIG_DEBUG_UART_SHIFT, UART_MCRVAL);
-	serial_out_shift(&com_port->fcr, CONFIG_DEBUG_UART_SHIFT, UART_FCRVAL);
-
-	serial_out_shift(&com_port->lcr, CONFIG_DEBUG_UART_SHIFT,
-			 UART_LCR_BKSE | UART_LCRVAL);
-	serial_out_shift(&com_port->dll, CONFIG_DEBUG_UART_SHIFT,
-			 baud_divisor & 0xff);
-	serial_out_shift(&com_port->dlm, CONFIG_DEBUG_UART_SHIFT,
-			 (baud_divisor >> 8) & 0xff);
-	serial_out_shift(&com_port->lcr, CONFIG_DEBUG_UART_SHIFT,
-			 UART_LCRVAL);
+	serial_dout(&com_port->ier, CONFIG_SYS_NS16550_IER);
+	serial_dout(&com_port->mcr, UART_MCRVAL);
+	serial_dout(&com_port->fcr, UART_FCRVAL);
+
+	serial_dout(&com_port->lcr, UART_LCR_BKSE | UART_LCRVAL);
+	serial_dout(&com_port->dll, baud_divisor & 0xff);
+	serial_dout(&com_port->dlm, (baud_divisor >> 8) & 0xff);
+	serial_dout(&com_port->lcr, UART_LCRVAL);
 }
 
 static inline void _debug_uart_putc(int ch)
 {
 	struct NS16550 *com_port = (struct NS16550 *)CONFIG_DEBUG_UART_BASE;
 
-	while (!(serial_in_shift(&com_port->lsr, 0) & UART_LSR_THRE))
+	while (!(serial_din(&com_port->lsr) & UART_LSR_THRE))
 		;
-	serial_out_shift(&com_port->thr, CONFIG_DEBUG_UART_SHIFT, ch);
+	serial_dout(&com_port->thr, ch);
 }
 
 DEBUG_UART_FUNCS
Signature · 1 line
2.4.3.573.g4eafbef
#96 lore raw

PATCH v3 44/54 ns16550: Improve debug UART so it can work with 32-bit access

Quoted 11 lines · Simon Glass

Since Rockchip requires 32-bit serial access, add this to the driver. Refactor a little to make this easier.

---

Changes in v3: None
Changes in v2: None

 drivers/serial/ns16550.c | 36 +++++++++++++++++++++---------------
 1 file changed, 21 insertions(+), 15 deletions(-)

Applied to u-boot-dm.

#97 lore raw

PATCH v3 45/54 Add rivest cipher 4 (rc4) implementation

In reply to Simon Glass

Add an implementation of RC4. This will be used by Rockchip booting but may be useful in other situations.

---

Changes in v3: None
Changes in v2: None

 include/rc4.h | 21 +++++++++++++++++++++
 lib/Makefile  |  1 +
 lib/rc4.c     | 49 +++++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 71 insertions(+)
 create mode 100644 include/rc4.h
 create mode 100644 lib/rc4.c
include/rc4.h new file +21 -0
new file mode 100644
index 0000000..ea409c2
@@ -0,0 +1,21 @@
+/*
+ * (C) Copyright 2015 Google, Inc
+ *
+ * (C) Copyright 2008-2014 Rockchip Electronics
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#ifndef __RC4_H
+#define __RC4_H
+
+/**
+ * rc4_encode() - encode a buf with the RC4 cipher
+ *
+ * @buf:	Buffer to encode (it is overwrite in the process
+ * @len:	Length of buffer in bytes
+ * @key:	16-byte key to use
+ */
+void rc4_encode(unsigned char *buf, unsigned int len, unsigned char key[16]);
+
+#endif
lib/Makefile +1 -0
index 1139f9b..fd106b9 100644
@@ -37,6 +37,7 @@ obj-$(CONFIG_MD5) += md5.o
 obj-y += net_utils.o
 obj-$(CONFIG_PHYSMEM) += physmem.o
 obj-y += qsort.o
+obj-y += rc4.o
 obj-$(CONFIG_SHA1) += sha1.o
 obj-$(CONFIG_SUPPORT_EMMC_RPMB) += sha256.o
 obj-$(CONFIG_SHA256) += sha256.o
lib/rc4.c new file +49 -0

49 lines not on this page · raw message

Signature · 1 line
2.4.3.573.g4eafbef
#98 lore raw

PATCH v3 45/54 Add rivest cipher 4 (rc4) implementation

Quoted 9 lines · Simon Glass

Add an implementation of RC4. This will be used by Rockchip booting but may be useful in other situations.

---

Changes in v3: None
Changes in v2: None

Quoted 6 lines
 include/rc4.h | 21 +++++++++++++++++++++
 lib/Makefile  |  1 +
 lib/rc4.c     | 49 +++++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 71 insertions(+)
 create mode 100644 include/rc4.h
 create mode 100644 lib/rc4.c

Applied to u-boot-dm.

#99 lore raw

PATCH v3 46/54 lib: Add function to extract a number from the end of a string

In reply to Simon Glass

Split out the code in fdtdec which finds a number at the end of a string. It can be useful in other situations.

---

Changes in v3: None
Changes in v2: None

 include/vsprintf.h | 26 ++++++++++++++++++++++++++
 lib/fdtdec.c       | 14 ++++++--------
 lib/vsprintf.c     | 19 +++++++++++++++++++
 3 files changed, 51 insertions(+), 8 deletions(-)
include/vsprintf.h +26 -0
index 09c8abd..3af8a4f 100644
@@ -41,6 +41,32 @@ unsigned long long simple_strtoull(const char *cp, char **endp,
 long simple_strtol(const char *cp, char **endp, unsigned int base);
 
 /**
+ * trailing_strtol() - extract a trailing integer from a string
+ *
+ * Given a string this finds a trailing number on the string and returns it.
+ * For example, "abc123" would return 123.
+ *
+ * @str:	String to exxamine
+ * @return training number if found, else -1
+ */
+long trailing_strtol(const char *str);
+
+/**
+ * trailing_strtoln() - extract a trailing integer from a fixed-length string
+ *
+ * Given a fixed-length string this finds a trailing number on the string
+ * and returns it. For example, "abc123" would return 123. Only the
+ * characters between @str and @end - 1 are examined. If @end is NULL, it is
+ * set to str + strlen(str).
+ *
+ * @str:	String to exxamine
+ * @end:	Pointer to end of string to examine, or NULL to use the
+ *		whole string
+ * @return training number if found, else -1
+ */
+long trailing_strtoln(const char *str, const char *end);
+
+/**
  * panic() - Print a message and reset/hang
  *
  * Prints a message on the console(s) and then resets. If CONFIG_PANIC_HANG is
lib/fdtdec.c +6 -8
index 9877849..add9adc 100644
@@ -505,8 +505,7 @@ int fdtdec_get_alias_seq(const void *blob, const char *base, int offset,
 		const char *prop;
 		const char *name;
 		const char *slash;
-		const char *p;
-		int len;
+		int len, val;
 
 		prop = fdt_getprop_by_offset(blob, prop_offset, &name, &len);
 		debug("   - %s, %s\n", name, prop);
@@ -517,12 +516,11 @@ int fdtdec_get_alias_seq(const void *blob, const char *base, int offset,
 		slash = strrchr(prop, '/');
 		if (strcmp(slash + 1, find_name))
 			continue;
-		for (p = name + strlen(name) - 1; p > name; p--) {
-			if (!isdigit(*p)) {
-				*seqp = simple_strtoul(p + 1, NULL, 10);
-				debug("Found seq %d\n", *seqp);
-				return 0;
-			}
+		val = trailing_strtol(name);
+		if (val != -1) {
+			*seqp = val;
+			debug("Found seq %d\n", *seqp);
+			return 0;
 		}
 	}
 
lib/vsprintf.c +19 -0
index bedc865..e7e569e 100644
@@ -166,6 +166,25 @@ unsigned long long simple_strtoull(const char *cp, char **endp,
 	return result;
 }
 
+long trailing_strtoln(const char *str, const char *end)
+{
+	const char *p;
+
+	if (!end)
+		end = str + strlen(str);
+	for (p = end - 1; p > str; p--) {
+		if (!isdigit(*p))
+			return simple_strtoul(p + 1, NULL, 10);
+	}
+
+	return -1;
+}
+
+long trailing_strtol(const char *str)
+{
+	return trailing_strtoln(str, NULL);
+}
+
 /* we use this so that we can do without the ctype library */
 #define is_digit(c)	((c) >= '0' && (c) <= '9')
 
Signature · 1 line
2.4.3.573.g4eafbef
#100 lore raw

PATCH v3 46/54 lib: Add function to extract a number from the end of a string

Quoted 6 lines · Simon Glass

Split out the code in fdtdec which finds a number at the end of a string. It can be useful in other situations.

---

Quoted 7 lines

Changes in v3: None
Changes in v2: None

 include/vsprintf.h | 26 ++++++++++++++++++++++++++
 lib/fdtdec.c       | 14 ++++++--------
 lib/vsprintf.c     | 19 +++++++++++++++++++
 3 files changed, 51 insertions(+), 8 deletions(-)

Applied to u-boot-dm.

#101 lore raw

PATCH v3 47/54 fdt: Provide debug info when a device tree cannot be found

In reply to Simon Glass

It can be quite confusing with a new platform to figure out why the device tree cannot be located. Add some debug information for this case.

---

Changes in v3: None
Changes in v2: None

 lib/fdtdec.c | 7 +++++++
 1 file changed, 7 insertions(+)
lib/fdtdec.c +7 -0
index add9adc..a78d577 100644
@@ -568,6 +568,13 @@ int fdtdec_prepare_fdt(void)
 		puts("Missing DTB\n");
 #else
 		puts("No valid device tree binary found - please append one to U-Boot binary, use u-boot-dtb.bin or define CONFIG_OF_EMBED. For sandbox, use -d <file.dtb>\n");
+# ifdef DEBUG
+		if (gd->fdt_blob) {
+			printf("fdt_blob=%p\n", gd->fdt_blob);
+			print_buffer((ulong)gd->fdt_blob, gd->fdt_blob, 4,
+				     32, 0);
+		}
+# endif
 #endif
 		return -1;
 	}
Signature · 1 line
2.4.3.573.g4eafbef
#102 lore raw

PATCH v3 47/54 fdt: Provide debug info when a device tree cannot be found

Quoted 11 lines · Simon Glass

It can be quite confusing with a new platform to figure out why the device tree cannot be located. Add some debug information for this case.

---

Changes in v3: None
Changes in v2: None

 lib/fdtdec.c | 7 +++++++
 1 file changed, 7 insertions(+)

Applied to u-boot-dm.

#103 lore raw

PATCH v3 48/54 dm: spl: Allow device tree/driver model in board_init_f()

In reply to Simon Glass

Add an spl_init() function that does basic init such that board_init_f() can use simple malloc(), device tree and driver model. Each one is set up only if enabled for SPL.

Note: We really should refactor SPL such that there is a single board_init_f() and rename the existing weak board_init_f() functions provided by boards, calling them from the single board_init_f().

---

Changes in v3: None
Changes in v2: None

 common/spl/spl.c                  | 35 ++++++++++++++++++++++++-----------
 include/asm-generic/global_data.h |  1 +
 include/spl.h                     | 12 ++++++++++++
 3 files changed, 37 insertions(+), 11 deletions(-)
common/spl/spl.c +24 -11
index aeb0645..074c41d 100644
@@ -148,18 +148,12 @@ static void spl_ram_load_image(void)
 }
 #endif
 
-void board_init_r(gd_t *dummy1, ulong dummy2)
+int spl_init(void)
 {
-	u32 boot_device;
 	int ret;
 
-	debug(">>spl:board_init_r()\n");
-
-#if defined(CONFIG_SYS_SPL_MALLOC_START)
-	mem_malloc_init(CONFIG_SYS_SPL_MALLOC_START,
-			CONFIG_SYS_SPL_MALLOC_SIZE);
-	gd->flags |= GD_FLG_FULL_MALLOC_INIT;
-#elif defined(CONFIG_SYS_MALLOC_F_LEN)
+	debug("spl_init()\n");
+#if defined(CONFIG_SYS_MALLOC_F_LEN)
 	gd->malloc_limit = CONFIG_SYS_MALLOC_F_LEN;
 	gd->malloc_ptr = 0;
 #endif
@@ -168,17 +162,36 @@ void board_init_r(gd_t *dummy1, ulong dummy2)
 		ret = fdtdec_setup();
 		if (ret) {
 			debug("fdtdec_setup() returned error %d\n", ret);
-			hang();
+			return ret;
 		}
 	}
 	if (IS_ENABLED(CONFIG_SPL_DM)) {
 		ret = dm_init_and_scan(true);
 		if (ret) {
 			debug("dm_init_and_scan() returned error %d\n", ret);
-			hang();
+			return ret;
 		}
 	}
+	gd->flags |= GD_FLG_SPL_INIT;
+
+	return 0;
+}
 
+void board_init_r(gd_t *dummy1, ulong dummy2)
+{
+	u32 boot_device;
+
+	debug(">>spl:board_init_r()\n");
+
+#if defined(CONFIG_SYS_SPL_MALLOC_START)
+	mem_malloc_init(CONFIG_SYS_SPL_MALLOC_START,
+			CONFIG_SYS_SPL_MALLOC_SIZE);
+	gd->flags |= GD_FLG_FULL_MALLOC_INIT;
+#endif
+	if (!(gd->flags & GD_FLG_SPL_INIT)) {
+		if (spl_init())
+			hang();
+	}
 #ifndef CONFIG_PPC
 	/*
 	 * timer_init() does not exist on PPC systems. The timer is initialized
include/asm-generic/global_data.h +1 -0
index 6747619..73c61e6 100644
@@ -115,5 +115,6 @@ typedef struct global_data {
 #define GD_FLG_ENV_READY	0x00080	/* Env. imported into hash table   */
 #define GD_FLG_SERIAL_READY	0x00100	/* Pre-reloc serial console ready  */
 #define GD_FLG_FULL_MALLOC_INIT	0x00200	/* Full malloc() is ready	   */
+#define GD_FLG_SPL_INIT		0x00400	/* spl_init() has been called	   */
 
 #endif /* __ASM_GENERIC_GBL_DATA_H */
include/spl.h +12 -0
index d19940f..8e53426 100644
@@ -81,6 +81,18 @@ void __noreturn jump_to_image_no_args(struct spl_image_info *spl_image);
 int spl_load_image_ext(block_dev_desc_t *block_dev, int partition, const char *filename);
 int spl_load_image_ext_os(block_dev_desc_t *block_dev, int partition);
 
+/**
+ * spl_init() - Set up device tree and driver model in SPL if enabled
+ *
+ * Call this function in board_init_f() if you want to use device tree and
+ * driver model early, before board_init_r() is called. This function will
+ * be called from board_init_r() if not called earlier.
+ *
+ * If this is not called, then driver model will be inactive in SPL's
+ * board_init_f(), and no device tree will be available.
+ */
+int spl_init(void);
+
 #ifdef CONFIG_SPL_BOARD_INIT
 void spl_board_init(void);
 #endif
Signature · 1 line
2.4.3.573.g4eafbef
#104 lore raw

PATCH v3 48/54 dm: spl: Allow device tree/driver model in board_init_f()

Quoted 11 lines · Simon Glass

Add an spl_init() function that does basic init such that board_init_f() can use simple malloc(), device tree and driver model. Each one is set up only if enabled for SPL.

Note: We really should refactor SPL such that there is a single board_init_f() and rename the existing weak board_init_f() functions provided by boards, calling them from the single board_init_f().

---

Quoted 7 lines

Changes in v3: None
Changes in v2: None

 common/spl/spl.c                  | 35 ++++++++++++++++++++++++-----------
 include/asm-generic/global_data.h |  1 +
 include/spl.h                     | 12 ++++++++++++
 3 files changed, 37 insertions(+), 11 deletions(-)

Applied to u-boot-dm.

#105 lore raw

PATCH v3 49/54 spl: Add a debug string before the jump to U-Boot

In reply to Simon Glass

As a debug option, add positive confirmation that SPL has completed execution. This can help with diagnosing the location of unexpected hangs.

---

Changes in v3: None
Changes in v2: None

 common/spl/spl.c | 1 +
 1 file changed, 1 insertion(+)
common/spl/spl.c +1 -0
index 074c41d..94b01da 100644
@@ -298,6 +298,7 @@ void board_init_r(gd_t *dummy1, ulong dummy2)
 	      gd->malloc_ptr / 1024);
 #endif
 
+	debug("loaded - jumping to U-Boot...");
 	jump_to_image_no_args(&spl_image);
 }
 
Signature · 1 line
2.4.3.573.g4eafbef
#106 lore raw

PATCH v3 49/54 spl: Add a debug string before the jump to U-Boot

Quoted 11 lines · Simon Glass

As a debug option, add positive confirmation that SPL has completed execution. This can help with diagnosing the location of unexpected hangs.

---

Changes in v3: None
Changes in v2: None

 common/spl/spl.c | 1 +
 1 file changed, 1 insertion(+)

Applied to u-boot-dm.

#107 lore raw

PATCH v3 50/54 mkimage: Set up a file size parameter and keep it updated

In reply to Simon Glass

Some functions called by mkimage would like to know the output file size. Initially this is the same as the input file size, but it may be affected by adding headers, etc.

Add this information to the image parameters.

---

Changes in v3: None
Changes in v2: None

 tools/imagetool.h |  1 +
 tools/mkimage.c   | 18 ++++++++++++++++++
 2 files changed, 19 insertions(+)
tools/imagetool.h +1 -0
index b7874f4..99bbf2f 100644
@@ -59,6 +59,7 @@ struct image_tool_params {
 	const char *keydest;	/* Destination .dtb for public key */
 	const char *comment;	/* Comment to add to signature node */
 	int require_keys;	/* 1 to mark signing keys as 'required' */
+	int file_size;		/* Total size of output file */
 };
 
 /*
tools/mkimage.c +18 -0
index 8808d70..e81d455 100644
@@ -75,6 +75,7 @@ int main(int argc, char **argv)
 	int retval = 0;
 	struct image_type_params *tparams = NULL;
 	int pad_len = 0;
+	int dfd;
 
 	params.cmdname = *argv;
 	params.addr = params.ep = 0;
@@ -310,6 +311,22 @@ NXTARG:		;
 		exit (retval);
 	}
 
+	dfd = open(params.datafile, O_RDONLY | O_BINARY);
+	if (dfd < 0) {
+		fprintf(stderr, "%s: Can't open %s: %s\n",
+			params.cmdname, params.datafile, strerror(errno));
+		exit(EXIT_FAILURE);
+	}
+
+	if (fstat(dfd, &sbuf) < 0) {
+		fprintf(stderr, "%s: Can't stat %s: %s\n",
+			params.cmdname, params.datafile, strerror(errno));
+		exit(EXIT_FAILURE);
+	}
+
+	params.file_size = sbuf.st_size + tparams->header_size;
+	close(dfd);
+
 	/*
 	 * In case there an header with a variable
 	 * length will be added, the corresponding
@@ -409,6 +426,7 @@ NXTARG:		;
 			params.cmdname, params.imagefile, strerror(errno));
 		exit (EXIT_FAILURE);
 	}
+	params.file_size = sbuf.st_size;
 
 	ptr = mmap(0, sbuf.st_size, PROT_READ|PROT_WRITE, MAP_SHARED, ifd, 0);
 	if (ptr == MAP_FAILED) {
Signature · 1 line
2.4.3.573.g4eafbef
#108 lore raw

PATCH v3 50/54 mkimage: Set up a file size parameter and keep it updated

Hi Simon,

Quoted 8 lines · Simon Glass

Some functions called by mkimage would like to know the output file size. Initially this is the same as the input file size, but it may be affected by adding headers, etc.

Add this information to the image parameters.

---

#109 lore raw

PATCH v3 50/54 mkimage: Set up a file size parameter and keep it updated

Quoted 7 lines · Joe Hershberger

Hi Simon,

Quoted 4 lines · Simon Glass

Some functions called by mkimage would like to know the output file size. Initially this is the same as the input file size, but it may be affected by adding headers, etc.

Quoted 6 lines
Quoted 4 lines

Add this information to the image parameters.

---

Applied to u-boot-dm.

#110 lore raw

PATCH v3 50/54 mkimage: Set up a file size parameter and keep it updated

Quoted 8 lines · Simon Glass
Quoted 7 lines · Joe Hershberger

Hi Simon,

Quoted 4 lines · Simon Glass

Some functions called by mkimage would like to know the output file size. Initially this is the same as the input file size, but it may be affected by adding headers, etc.

Quoted 8 lines
Quoted 6 lines
Quoted 4 lines

Add this information to the image parameters.

---

Applied to u-boot-dm.

Hi,

This breaks all i.MX23 and i.MX28 boards, try building for example the mx28evk board, u-boot.sb target:

$ make mx28evk_defconfig
$ make u-boot.sb
[...]
  LD      spl/lib/built-in.o
  LDS     spl/u-boot-spl.lds
  LD      spl/u-boot-spl
  OBJCOPY spl/u-boot-spl.bin
  CFG     spl/u-boot-spl.cfg
  MKIMAGE u-boot.sb
./tools/mkimage: Can't open (null): Bad address
arch/arm/cpu/arm926ejs/mxs/Makefile:82: recipe for target 'u-boot.sb' failed
make[1]: *** [u-boot.sb] Error 1
Makefile:989: recipe for target 'u-boot.sb' failed
make: *** [u-boot.sb] Error 2

Shall I look into it or do you already have a patch ? :)

Best regards,
Marek Vasut

#111 lore raw

PATCH v3 50/54 mkimage: Set up a file size parameter and keep it updated

Quoted 38 lines · Marek Vasut
Quoted 8 lines · Simon Glass
Quoted 7 lines · Joe Hershberger

Hi Simon,

Quoted 4 lines · Simon Glass

Some functions called by mkimage would like to know the output file size. Initially this is the same as the input file size, but it may be affected by adding headers, etc.

Quoted 8 lines
Quoted 6 lines
Quoted 4 lines

Add this information to the image parameters.

---

Applied to u-boot-dm.

Hi,

This breaks all i.MX23 and i.MX28 boards, try building for example the mx28evk board, u-boot.sb target:

$ make mx28evk_defconfig
$ make u-boot.sb
[...]
  LD      spl/lib/built-in.o
  LDS     spl/u-boot-spl.lds
  LD      spl/u-boot-spl
  OBJCOPY spl/u-boot-spl.bin
  CFG     spl/u-boot-spl.cfg
  MKIMAGE u-boot.sb
./tools/mkimage: Can't open (null): Bad address
arch/arm/cpu/arm926ejs/mxs/Makefile:82: recipe for target 'u-boot.sb'
failed make[1]: *** [u-boot.sb] Error 1
Makefile:989: recipe for target 'u-boot.sb' failed
make: *** [u-boot.sb] Error 2
Quoted 1 line

Shall I look into it or do you already have a patch ? :)

Patch is out and the patch is most certainly correct.

On the other hand, is my understanding correct that this patch makes passing the -d option to mkimage mandatory ? It was optional before this patch I believe.

Best regards,
Marek Vasut

#112 lore raw

PATCH v3 51/54 dm: Add a system reset uclass

In reply to Simon Glass

It is common for system reset to be available at multiple levels in modern hardware. For example, an SoC may provide a reset option, and a board may provide its own reset for reasons of security or thoroughness. It is useful to be able to model this hardware without hard-coding the behaviour in the SoC or board. Also there is a distinction sometimes between resetting just the CPU (leaving GPIO state alone) and resetting all the PMICs, just cutting power.

To achieve this, add a simple system reset uclass. It allows multiple devices to provide reset functionality and provides a way to walk through them, requesting a particular reset type until is it provided.

---

Changes in v3: None
Changes in v2: None

 drivers/misc/Kconfig        |  9 +++++++
 drivers/misc/Makefile       |  1 +
 drivers/misc/reset-uclass.c | 62 +++++++++++++++++++++++++++++++++++++++++++++
 include/dm/uclass-id.h      |  1 +
 include/reset.h             | 62 +++++++++++++++++++++++++++++++++++++++++++++
 5 files changed, 135 insertions(+)
 create mode 100644 drivers/misc/reset-uclass.c
 create mode 100644 include/reset.h
drivers/misc/Kconfig +9 -0
index 64b07a3..3b7f76a 100644
@@ -73,3 +73,12 @@ config PCA9551_I2C_ADDR
 	default 0x60
 	help
 	  The I2C address of the PCA9551 LED controller.
+
+config RESET
+	bool "Enable support for reset drivers"
+	depends on DM
+	help
+	  Enable reset drivers which can be used to reset the CPU or board.
+	  Each driver can provide a reset method which will be called to
+	  effect a reset. The uclass will try all available drivers when
+	  reset_walk() is called.
drivers/misc/Makefile +1 -0
index 120babc..5da5178 100644
@@ -32,3 +32,4 @@ obj-$(CONFIG_TWL4030_LED) += twl4030_led.o
 obj-$(CONFIG_FSL_IFC) += fsl_ifc.o
 obj-$(CONFIG_FSL_SEC_MON) += fsl_sec_mon.o
 obj-$(CONFIG_PCA9551_LED) += pca9551_led.o
+obj-$(CONFIG_RESET) += reset-uclass.o
drivers/misc/reset-uclass.c new file +62 -0

62 lines not on this page · raw message

include/dm/uclass-id.h +1 -0
index 5bb602f..fc486f2 100644
@@ -45,6 +45,7 @@ enum uclass_id {
 	UCLASS_PINCTRL,		/* Pin multiplexing control */
 	UCLASS_PMIC,		/* PMIC I/O device */
 	UCLASS_REGULATOR,	/* Regulator device */
+	UCLASS_RESET,		/* Reset device */
 	UCLASS_RTC,		/* Real time clock device */
 	UCLASS_SERIAL,		/* Serial UART */
 	UCLASS_SPI,		/* SPI bus */
include/reset.h new file +62 -0

62 lines not on this page · raw message

Signature · 1 line
2.4.3.573.g4eafbef
#113 lore raw

PATCH v3 51/54 dm: Add a system reset uclass

Quoted 18 lines · Simon Glass

It is common for system reset to be available at multiple levels in modern hardware. For example, an SoC may provide a reset option, and a board may provide its own reset for reasons of security or thoroughness. It is useful to be able to model this hardware without hard-coding the behaviour in the SoC or board. Also there is a distinction sometimes between resetting just the CPU (leaving GPIO state alone) and resetting all the PMICs, just cutting power.

To achieve this, add a simple system reset uclass. It allows multiple devices to provide reset functionality and provides a way to walk through them, requesting a particular reset type until is it provided.

---

Changes in v3: None
Changes in v2: None

Quoted 8 lines
 drivers/misc/Kconfig        |  9 +++++++
 drivers/misc/Makefile       |  1 +
 drivers/misc/reset-uclass.c | 62 +++++++++++++++++++++++++++++++++++++++++++++
 include/dm/uclass-id.h      |  1 +
 include/reset.h             | 62 +++++++++++++++++++++++++++++++++++++++++++++
 5 files changed, 135 insertions(+)
 create mode 100644 drivers/misc/reset-uclass.c
 create mode 100644 include/reset.h

Applied to u-boot-dm.

#114 lore raw

PATCH v3 52/54 zynq: Rename struct clk_ops to zynq_clk_ops

In reply to Simon Glass

Since we want clk_ops to be used in U-Boot as a whole, rename the Zynq version until it can be converted to driver model.

---

Changes in v3: None
Changes in v2: None

 arch/arm/mach-zynq/clk.c | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)
arch/arm/mach-zynq/clk.c +3 -3
index d2885dc..6444be8 100644
@@ -48,11 +48,11 @@ DECLARE_GLOBAL_DATA_PTR;
 struct clk;
 
 /**
- * struct clk_ops:
+ * struct zynq_clk_ops:
  * @set_rate:	Function pointer to set_rate() implementation
  * @get_rate:	Function pointer to get_rate() implementation
  */
-struct clk_ops {
+struct zynq_clk_ops {
 	int (*set_rate)(struct clk *clk, unsigned long rate);
 	unsigned long (*get_rate)(struct clk *clk);
 };
@@ -72,7 +72,7 @@ struct clk {
 	enum zynq_clk	parent;
 	unsigned int	flags;
 	u32		*reg;
-	struct clk_ops	ops;
+	struct zynq_clk_ops	ops;
 };
 #define ZYNQ_CLK_FLAGS_HAS_2_DIVS	1
 
Signature · 1 line
2.4.3.573.g4eafbef
#115 lore raw

PATCH v3 52/54 zynq: Rename struct clk_ops to zynq_clk_ops

Quoted 11 lines · Simon Glass

Since we want clk_ops to be used in U-Boot as a whole, rename the Zynq version until it can be converted to driver model.

---

Changes in v3: None
Changes in v2: None

 arch/arm/mach-zynq/clk.c | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

Applied to u-boot-dm.

#116 lore raw

PATCH v3 53/54 dm: Add a clock uclass

In reply to Simon Glass

Clocks are an important feature of platforms and have become increasing complex with time. Most modern SoCs have multiple PLLs and dozens of clock dividers which distribute clocks to on-chip peripherals.

Some SoC implementations have a clock API which is private to that SoC family, e.g. Tegra and Exynos. This is useful but it would be better to have a common API that can be understood and used throughout U-Boot.

Add a simple clock API as a starting point. It supports querying and setting the rate of a clock. Each clock is a device. To reduce memory and processing overhead the concept of peripheral clocks is provided. These do not need to be explicit devices - it is possible to write a driver that can adjust the I2C clock (for example) without an explicit I2C clock device. This can dramatically reduce the number of devices (and associated overhead) in a complex SoC.

Clocks are referenced by a number, and it is expected that SoCs will define that numbering themselves via an enum.

---

Changes in v3: None
Changes in v2: None

 drivers/Kconfig          |  2 ++
 drivers/Makefile         |  1 +
 drivers/clk/Kconfig      | 19 ++++++++++++
 drivers/clk/Makefile     |  8 +++++
 drivers/clk/clk-uclass.c | 58 +++++++++++++++++++++++++++++++++++
 include/clk.h            | 80 ++++++++++++++++++++++++++++++++++++++++++++++++
 include/dm/uclass-id.h   |  1 +
 scripts/Makefile.spl     |  1 +
 8 files changed, 170 insertions(+)
 create mode 100644 drivers/clk/Kconfig
 create mode 100644 drivers/clk/Makefile
 create mode 100644 drivers/clk/clk-uclass.c
drivers/Kconfig +2 -0
index 7c9eefc..619d93a 100644
@@ -1,5 +1,7 @@
 menu "Device Drivers"
 
+source "drivers/clk/Kconfig"
+
 source "drivers/core/Kconfig"
 
 source "drivers/cpu/Kconfig"
drivers/Makefile +1 -0
index 39b7919..9f5cec7 100644
@@ -1,3 +1,4 @@
+obj-$(CONFIG_CLK) += clk/
 obj-$(CONFIG_DM) += core/
 obj-$(CONFIG_DM_DEMO) += demo/
 obj-$(CONFIG_BIOSEMU) += bios_emulator/
drivers/clk/Kconfig new file +19 -0
new file mode 100644
index 0000000..07eb54c
@@ -0,0 +1,19 @@
+config CLK
+	bool "Enable clock driver support"
+	depends on DM
+	help
+	  This allows drivers to be provided for clock generators, including
+	  oscillators and PLLs. Devices can use a common clock API to request
+	  a particular clock rate and check on available clocks. Clocks can
+	  feed into other clocks in a tree structure, with multiplexers to
+	  choose the source for each clock.
+
+config SPL_CLK_SUPPORT
+	bool "Enable clock support in SPL"
+	depends on CLK
+	help
+	  The clock subsystem adds a small amount of overhead to the image.
+	  If this is acceptable and you have a need to use clock drivers in
+	  SPL, enable this option. It might provide a cleaner interface to
+	  setting up clocks within SPL, and allows the same drivers to be
+	  used as U-Boot proper.
drivers/clk/Makefile new file +8 -0
new file mode 100644
index 0000000..b51cf23
@@ -0,0 +1,8 @@
+#
+# Copyright (c) 2015 Google, Inc
+# Wolfgang Denk, DENX Software Engineering, wd at denx.de.
+#
+# SPDX-License-Identifier:      GPL-2.0+
+#
+
+obj-$(CONFIG_CLK) += clk-uclass.o
drivers/clk/clk-uclass.c new file +58 -0

58 lines not on this page · raw message

include/clk.h +80 -0

86 lines not on this page · raw message

include/dm/uclass-id.h +1 -0
index fc486f2..72512b5 100644
@@ -25,6 +25,7 @@ enum uclass_id {
 	UCLASS_SIMPLE_BUS,	/* bus with child devices */
 
 	/* U-Boot uclasses start here - in alphabetical order */
+	UCLASS_CLK,		/* Clock source, e.g. used by peripherals */
 	UCLASS_CPU,		/* CPU, typically part of an SoC */
 	UCLASS_CROS_EC,		/* Chrome OS EC */
 	UCLASS_DISPLAY_PORT,	/* Display port video */
scripts/Makefile.spl +1 -0
index c4e83bb..9d7ac99 100644
@@ -54,6 +54,7 @@ libs-$(HAVE_VENDOR_COMMON_LIB) += board/$(VENDOR)/common/
 libs-$(CONFIG_SPL_FRAMEWORK) += common/spl/
 libs-$(CONFIG_SPL_LIBCOMMON_SUPPORT) += common/
 libs-$(CONFIG_SPL_LIBDISK_SUPPORT) += disk/
+libs-$(CONFIG_SPL_CLK_SUPPORT) += drivers/clk/
 libs-$(CONFIG_SPL_DM) += drivers/core/
 libs-$(CONFIG_SPL_I2C_SUPPORT) += drivers/i2c/
 libs-$(CONFIG_SPL_GPIO_SUPPORT) += drivers/gpio/
Signature · 1 line
2.4.3.573.g4eafbef
#117 lore raw

PATCH v3 53/54 dm: Add a clock uclass

Quoted 25 lines · Simon Glass

Clocks are an important feature of platforms and have become increasing complex with time. Most modern SoCs have multiple PLLs and dozens of clock dividers which distribute clocks to on-chip peripherals.

Some SoC implementations have a clock API which is private to that SoC family, e.g. Tegra and Exynos. This is useful but it would be better to have a common API that can be understood and used throughout U-Boot.

Add a simple clock API as a starting point. It supports querying and setting the rate of a clock. Each clock is a device. To reduce memory and processing overhead the concept of peripheral clocks is provided. These do not need to be explicit devices - it is possible to write a driver that can adjust the I2C clock (for example) without an explicit I2C clock device. This can dramatically reduce the number of devices (and associated overhead) in a complex SoC.

Clocks are referenced by a number, and it is expected that SoCs will define that numbering themselves via an enum.

---

Changes in v3: None
Changes in v2: None

Quoted 12 lines
 drivers/Kconfig          |  2 ++
 drivers/Makefile         |  1 +
 drivers/clk/Kconfig      | 19 ++++++++++++
 drivers/clk/Makefile     |  8 +++++
 drivers/clk/clk-uclass.c | 58 +++++++++++++++++++++++++++++++++++
 include/clk.h            | 80 ++++++++++++++++++++++++++++++++++++++++++++++++
 include/dm/uclass-id.h   |  1 +
 scripts/Makefile.spl     |  1 +
 8 files changed, 170 insertions(+)
 create mode 100644 drivers/clk/Kconfig
 create mode 100644 drivers/clk/Makefile
 create mode 100644 drivers/clk/clk-uclass.c

Applied to u-boot-dm.

#118 lore raw

PATCH v3 54/54 power: pmic: Use trailing_strtol() instead of a local function

In reply to Simon Glass

Use the common function to obtain the number from the end of the string, instead of a local function. Also tweak the position of a debug() statement.

---

Changes in v3:
- Split this series apart from the Rockchip series

Changes in v2: None

 drivers/power/pmic/pmic-uclass.c | 23 +++++------------------
 1 file changed, 5 insertions(+), 18 deletions(-)
drivers/power/pmic/pmic-uclass.c +5 -18
index dbab3e3..d99cb9a 100644
@@ -9,6 +9,7 @@
 #include <fdtdec.h>
 #include <errno.h>
 #include <dm.h>
+#include <vsprintf.h>
 #include <dm/lists.h>
 #include <dm/device-internal.h>
 #include <dm/uclass-internal.h>
@@ -17,16 +18,6 @@
 
 DECLARE_GLOBAL_DATA_PTR;
 
-static ulong str_get_num(const char *ptr, const char *maxptr)
-{
-	if (!ptr || !maxptr)
-		return 0;
-
-	while (!isdigit(*ptr) && ptr++ < maxptr);
-
-	return simple_strtoul(ptr, NULL, 0);
-}
-
 int pmic_bind_children(struct udevice *pmic, int offset,
 		       const struct pmic_child_info *child_info)
 {
@@ -35,7 +26,6 @@ int pmic_bind_children(struct udevice *pmic, int offset,
 	struct driver *drv;
 	struct udevice *child;
 	const char *node_name;
-	int node_name_len;
 	int bind_count = 0;
 	int node;
 	int prefix_len;
@@ -47,19 +37,19 @@ int pmic_bind_children(struct udevice *pmic, int offset,
 	for (node = fdt_first_subnode(blob, offset);
 	     node > 0;
 	     node = fdt_next_subnode(blob, node)) {
-		node_name = fdt_get_name(blob, node, &node_name_len);
+		node_name = fdt_get_name(blob, node, NULL);
 
 		debug("* Found child node: '%s' at offset:%d\n", node_name,
 								 node);
 
 		child = NULL;
 		for (info = child_info; info->prefix && info->driver; info++) {
+			debug("  - compatible prefix: '%s'\n", info->prefix);
+
 			prefix_len = strlen(info->prefix);
 			if (strncmp(info->prefix, node_name, prefix_len))
 				continue;
 
-			debug("  - compatible prefix: '%s'\n", info->prefix);
-
 			drv = lists_driver_lookup_name(info->driver);
 			if (!drv) {
 				debug("  - driver: '%s' not found!\n",
@@ -78,10 +68,7 @@ int pmic_bind_children(struct udevice *pmic, int offset,
 
 			debug("  - bound child device: '%s'\n", child->name);
 
-			child->driver_data = str_get_num(node_name +
-							 prefix_len,
-							 node_name +
-							 node_name_len);
+			child->driver_data = trailing_strtol(node_name);
 
 			debug("  - set 'child->driver_data': %lu\n",
 			      child->driver_data);
Signature · 1 line
2.4.3.573.g4eafbef
#119 lore raw

PATCH v3 54/54 power: pmic: Use trailing_strtol() instead of a local function

Hello Simon,

Quoted 77 lines · Simon Glass

Use the common function to obtain the number from the end of the string, instead of a local function. Also tweak the position of a debug() statement.

---

Changes in v3:
- Split this series apart from the Rockchip series

Changes in v2: None

  drivers/power/pmic/pmic-uclass.c | 23 +++++------------------
  1 file changed, 5 insertions(+), 18 deletions(-)
drivers/power/pmic/pmic-uclass.c +4 -14
index dbab3e3..d99cb9a 100644
@@ -9,6 +9,7 @@
  #include <fdtdec.h>
  #include <errno.h>
  #include <dm.h>
+#include <vsprintf.h>
  #include <dm/lists.h>
  #include <dm/device-internal.h>
  #include <dm/uclass-internal.h>
@@ -17,16 +18,6 @@
 
  DECLARE_GLOBAL_DATA_PTR;
 
-static ulong str_get_num(const char *ptr, const char *maxptr)
-{
-	if (!ptr || !maxptr)
-		return 0;
-
-	while (!isdigit(*ptr) && ptr++ < maxptr);
-
-	return simple_strtoul(ptr, NULL, 0);
-}
-
  int pmic_bind_children(struct udevice *pmic, int offset,
  		       const struct pmic_child_info *child_info)
  {
@@ -35,7 +26,6 @@ int pmic_bind_children(struct udevice *pmic, int offset,
  	struct driver *drv;
  	struct udevice *child;
  	const char *node_name;
-	int node_name_len;
  	int bind_count = 0;
  	int node;
  	int prefix_len;
@@ -47,19 +37,19 @@ int pmic_bind_children(struct udevice *pmic, int offset,
  	for (node = fdt_first_subnode(blob, offset);
  	     node > 0;
  	     node = fdt_next_subnode(blob, node)) {
-		node_name = fdt_get_name(blob, node, &node_name_len);
+		node_name = fdt_get_name(blob, node, NULL);
 
  		debug("* Found child node: '%s' at offset:%d\n", node_name,
  								 node);
 
  		child = NULL;
  		for (info = child_info; info->prefix && info->driver; info++) {
+			debug("  - compatible prefix: '%s'\n", info->prefix);
+
  			prefix_len = strlen(info->prefix);
  			if (strncmp(info->prefix, node_name, prefix_len))
  				continue;
 
-			debug("  - compatible prefix: '%s'\n", info->prefix);
-
  			drv = lists_driver_lookup_name(info->driver);
  			if (!drv) {
  				debug("  - driver: '%s' not found!\n",
@@ -78,10 +68,7 @@ int pmic_bind_children(struct udevice *pmic, int offset,
 

drivers/power/pmic/pmic-uclass.c int pmic_bind_children(struct udevice *pmic, int offset, · line 74

Quoted 10 lines
drivers/power/pmic/pmic-uclass.c +1 -4
  			debug("  - bound child device: '%s'\n", child->name);
 
-			child->driver_data = str_get_num(node_name +
-							 prefix_len,
-							 node_name +
-							 node_name_len);
+			child->driver_data = trailing_strtol(node_name);
 
  			debug("  - set 'child->driver_data': %lu\n",
  			      child->driver_data);

Tested on:
- Odroid U3 (odroid_defconfig)
- Sandbox - ut pmic/regulator

Best regards,

Signature · 4 lines
Przemyslaw Marczak
Samsung R&D Institute Poland
Samsung Electronics
p.marczak at samsung.com
#120 lore raw

PATCH v3 54/54 power: pmic: Use trailing_strtol() instead of a local function

Quoted 109 lines · Przemyslaw Marczak

Hello Simon,

Quoted 95 lines · Simon Glass

Use the common function to obtain the number from the end of the string, instead of a local function. Also tweak the position of a debug() statement.

---

Changes in v3:
- Split this series apart from the Rockchip series

Changes in v2: None

  drivers/power/pmic/pmic-uclass.c | 23 +++++------------------
  1 file changed, 5 insertions(+), 18 deletions(-)
drivers/power/pmic/pmic-uclass.c +4 -13
index dbab3e3..d99cb9a 100644
@@ -9,6 +9,7 @@
  #include <fdtdec.h>
  #include <errno.h>
  #include <dm.h>
+#include <vsprintf.h>
  #include <dm/lists.h>
  #include <dm/device-internal.h>
  #include <dm/uclass-internal.h>
@@ -17,16 +18,6 @@
 
  DECLARE_GLOBAL_DATA_PTR;
 
-static ulong str_get_num(const char *ptr, const char *maxptr)
-{
-       if (!ptr || !maxptr)
-               return 0;
-
-       while (!isdigit(*ptr) && ptr++ < maxptr);
-
-       return simple_strtoul(ptr, NULL, 0);
-}
-
  int pmic_bind_children(struct udevice *pmic, int offset,
                       const struct pmic_child_info *child_info)
  {
@@ -35,7 +26,6 @@ int pmic_bind_children(struct udevice *pmic, int offset,
        struct driver *drv;
        struct udevice *child;
        const char *node_name;
-       int node_name_len;
        int bind_count = 0;
        int node;
        int prefix_len;
@@ -47,19 +37,19 @@ int pmic_bind_children(struct udevice *pmic, int
 offset,
        for (node = fdt_first_subnode(blob, offset);
             node > 0;
             node = fdt_next_subnode(blob, node)) {
-               node_name = fdt_get_name(blob, node, &node_name_len);
+               node_name = fdt_get_name(blob, node, NULL);
 
                debug("* Found child node: '%s' at offset:%d\n",
 node_name,
                                                                 node);
 
                child = NULL;
                for (info = child_info; info->prefix && info->driver;
 info++) {
+                       debug("  - compatible prefix: '%s'\n",
 info->prefix);
+
                        prefix_len = strlen(info->prefix);
                        if (strncmp(info->prefix, node_name, prefix_len))
                                continue;
 
-                       debug("  - compatible prefix: '%s'\n",

info->prefix);

drivers/power/pmic/pmic-uclass.c +1 -5
-
                        drv = lists_driver_lookup_name(info->driver);
                        if (!drv) {
                                debug("  - driver: '%s' not found!\n",
@@ -78,10 +68,7 @@ int pmic_bind_children(struct udevice *pmic, int
 offset,
 
                        debug("  - bound child device: '%s'\n",
 child->name);
 
-                       child->driver_data = str_get_num(node_name +
-                                                        prefix_len,
-                                                        node_name +
-                                                        node_name_len);
+                       child->driver_data = trailing_strtol(node_name);
 
Quoted 3 lines
                        debug("  - set 'child->driver_data': %lu\n",
                              child->driver_data);

Tested on:
- Odroid U3 (odroid_defconfig)
- Sandbox - ut pmic/regulator

Quoted 6 lines

Best regards,
--
Przemyslaw Marczak
Samsung R&D Institute Poland
Samsung Electronics
p.marczak at samsung.com

Applied to u-boot-dm.

#121 lore raw

v3 cover dm: Introduce new driver model uclasses

In reply to Simon Glass

Simon,

Does the dm force using device tree? I was reviewing a patch set regarding SPI and found OF_CONTROL has to be selected in order to get the driver model happy.

My understanding of the driver model is both device tree and platform data are allowed, like Linux. Is that still true?

York

#122 lore raw

v3 cover dm: Introduce new driver model uclasses

Hi York,

Quoted 7 lines · York Sun

Simon,

Does the dm force using device tree? I was reviewing a patch set regarding SPI and found OF_CONTROL has to be selected in order to get the driver model happy.

My understanding of the driver model is both device tree and platform data are allowed, like Linux. Is that still true?

For buses you need device tree. I was rather hoping that we could avoid platform data on platforms that have device tree. What is the point?

Regards,
Simon

#123 lore raw

v3 cover dm: Introduce new driver model uclasses

Quoted 8 lines · Simon Glass

Hi York,

Quoted 5 lines · York Sun

Simon,

Does the dm force using device tree? I was reviewing a patch set regarding SPI and found OF_CONTROL has to be selected in order to get the driver model happy.

Quoted 7 lines
Quoted 2 lines

My understanding of the driver model is both device tree and platform data are allowed, like Linux. Is that still true?

For buses you need device tree. I was rather hoping that we could avoid platform data on platforms that have device tree. What is the point?

Simon,

It happens on a platform not using device tree, but DM will be used.

I prefer DM to have both, rather than being forced to use device tree, unless we are going to enforce using device tree on all new platforms. Since device tree is still an option, I feel it is best to support platform data, like Linux drivers do.

York

#124 lore raw

v3 cover dm: Introduce new driver model uclasses

Quoted 19 lines · York Sun
Quoted 8 lines · Simon Glass

Hi York,

Quoted 5 lines · York Sun

Simon,

Does the dm force using device tree? I was reviewing a patch set regarding SPI and found OF_CONTROL has to be selected in order to get the driver model happy.

Quoted 7 lines
Quoted 2 lines

My understanding of the driver model is both device tree and platform data are allowed, like Linux. Is that still true?

For buses you need device tree. I was rather hoping that we could avoid platform data on platforms that have device tree. What is the point?

Quoted 8 lines

Simon,

It happens on a platform not using device tree, but DM will be used.

I prefer DM to have both, rather than being forced to use device tree, unless we are going to enforce using device tree on all new platforms. Since device tree is still an option, I feel it is best to support platform data, like Linux drivers do.

Well, to what end? My recollection is that in short, the kernel has both since platform data predates device tree (and converting platform data to device tree is still a thing that happens). But we're trying to skip that intermediate step. Are there platforms where you do not plan to use a device tree, ever?

Signature · 8 lines
Tom
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 836 bytes
Desc: Digital signature
URL: <http://lists.denx.de/pipermail/u-boot/attachments/20150630/2a48a2b6/attachment.sig>
#125 lore raw

v3 cover dm: Introduce new driver model uclasses

Quoted 29 lines · Tom Rini
Quoted 19 lines · York Sun
Quoted 8 lines · Simon Glass

Hi York,

Quoted 5 lines · York Sun

Simon,

Does the dm force using device tree? I was reviewing a patch set regarding SPI and found OF_CONTROL has to be selected in order to get the driver model happy.

Quoted 7 lines
Quoted 2 lines

My understanding of the driver model is both device tree and platform data are allowed, like Linux. Is that still true?

For buses you need device tree. I was rather hoping that we could avoid platform data on platforms that have device tree. What is the point?

Quoted 8 lines

Simon,

It happens on a platform not using device tree, but DM will be used.

I prefer DM to have both, rather than being forced to use device tree, unless we are going to enforce using device tree on all new platforms. Since device tree is still an option, I feel it is best to support platform data, like Linux drivers do.

Quoted 6 lines

Well, to what end? My recollection is that in short, the kernel has both since platform data predates device tree (and converting platform data to device tree is still a thing that happens). But we're trying to skip that intermediate step. Are there platforms where you do not plan to use a device tree, ever?

Tom,

I am not against using device tree at all. It is more dynamic and flexible. But I don't see any indication that we favor device tree over pdata (except in the code). If we are skipping pdata for new drivers, a clear message will be helpful. That's what I am trying to get clarification.

York

#126 lore raw

v3 cover dm: Introduce new driver model uclasses

Quoted 39 lines · York Sun
Quoted 29 lines · Tom Rini
Quoted 19 lines · York Sun
Quoted 8 lines · Simon Glass

Hi York,

Quoted 5 lines · York Sun

Simon,

Does the dm force using device tree? I was reviewing a patch set regarding SPI and found OF_CONTROL has to be selected in order to get the driver model happy.

Quoted 7 lines
Quoted 2 lines

My understanding of the driver model is both device tree and platform data are allowed, like Linux. Is that still true?

For buses you need device tree. I was rather hoping that we could avoid platform data on platforms that have device tree. What is the point?

Quoted 8 lines

Simon,

It happens on a platform not using device tree, but DM will be used.

I prefer DM to have both, rather than being forced to use device tree, unless we are going to enforce using device tree on all new platforms. Since device tree is still an option, I feel it is best to support platform data, like Linux drivers do.

Quoted 6 lines

Well, to what end? My recollection is that in short, the kernel has both since platform data predates device tree (and converting platform data to device tree is still a thing that happens). But we're trying to skip that intermediate step. Are there platforms where you do not plan to use a device tree, ever?

Quoted 6 lines

Tom,

I am not against using device tree at all. It is more dynamic and flexible. But I don't see any indication that we favor device tree over pdata (except in the code). If we are skipping pdata for new drivers, a clear message will be helpful. That's what I am trying to get clarification.

OK. I think we'd agreed to that at ELC-E last year and it might have been in a few here-and-there emails but it's worth spelling out somewhere.

Hey Simon? doc/driver-model/README.txt has a pdata example, so maybe the answer here is it's time to update README.txt in a few ways :)

Signature · 8 lines
Tom
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 836 bytes
Desc: Digital signature
URL: <http://lists.denx.de/pipermail/u-boot/attachments/20150630/3485f1d4/attachment.sig>
#127 lore raw

v3 cover dm: Introduce new driver model uclasses

Hi Tom,

Quoted 47 lines · Tom Rini
Quoted 39 lines · York Sun
Quoted 29 lines · Tom Rini
Quoted 19 lines · York Sun
Quoted 8 lines · Simon Glass

Hi York,

Quoted 5 lines · York Sun

Simon,

Does the dm force using device tree? I was reviewing a patch set regarding SPI and found OF_CONTROL has to be selected in order to get the driver model happy.

Quoted 7 lines
Quoted 2 lines

My understanding of the driver model is both device tree and platform data are allowed, like Linux. Is that still true?

For buses you need device tree. I was rather hoping that we could avoid platform data on platforms that have device tree. What is the point?

Quoted 8 lines

Simon,

It happens on a platform not using device tree, but DM will be used.

I prefer DM to have both, rather than being forced to use device tree, unless we are going to enforce using device tree on all new platforms. Since device tree is still an option, I feel it is best to support platform data, like Linux drivers do.

Quoted 6 lines

Well, to what end? My recollection is that in short, the kernel has both since platform data predates device tree (and converting platform data to device tree is still a thing that happens). But we're trying to skip that intermediate step. Are there platforms where you do not plan to use a device tree, ever?

Quoted 6 lines

Tom,

I am not against using device tree at all. It is more dynamic and flexible. But I don't see any indication that we favor device tree over pdata (except in the code). If we are skipping pdata for new drivers, a clear message will be helpful. That's what I am trying to get clarification.

Quoted 6 lines

OK. I think we'd agreed to that at ELC-E last year and it might have been in a few here-and-there emails but it's worth spelling out somewhere.

Hey Simon? doc/driver-model/README.txt has a pdata example, so maybe the answer here is it's time to update README.txt in a few ways :)

I'll prepare a patch.

Regards,
Simon

#128 lore raw

v3 cover dm: Introduce new driver model uclasses

Quoted 41 lines · Simon Glass

Hi Tom,

Quoted 38 lines · Tom Rini
Quoted 37 lines · York Sun
Quoted 34 lines · Tom Rini
Quoted 19 lines · York Sun
Quoted 8 lines · Simon Glass

Hi York,

Quoted 5 lines · York Sun

Simon,

Does the dm force using device tree? I was reviewing a patch set regarding SPI and found OF_CONTROL has to be selected in order to get the driver model happy.

Quoted 7 lines
Quoted 2 lines

My understanding of the driver model is both device tree and platform data are allowed, like Linux. Is that still true?

For buses you need device tree. I was rather hoping that we could avoid platform data on platforms that have device tree. What is the point?

Quoted 8 lines

Simon,

It happens on a platform not using device tree, but DM will be used.

I prefer DM to have both, rather than being forced to use device tree, unless we are going to enforce using device tree on all new platforms. Since device tree is still an option, I feel it is best to support platform data, like Linux drivers do.

Well, to what end? My recollection is that in short, the kernel has both since platform data predates device tree (and converting platform data to device tree is still a thing that happens). But we're trying to skip that intermediate step. Are there platforms where you do not plan to use a device tree, ever?

My observations with this approach (dm-spi)

1. We're planning to move spi driver with dm support but many of the boards which
used spi drivers don't have dts support yet.
2. I think dm will progress only when dts support progresses.

The only solution for this - if we need to move any driver to dm then check for dts on particular board this driver uses and move that board to have dts support.

Any comments?

Quoted 9 lines
Quoted 9 lines
Quoted 8 lines
Quoted 1 line

Tom,

I am not against using device tree at all. It is more dynamic and flexible. But I don't see any indication that we favor device tree over pdata (except in the code). If we are skipping pdata for new drivers, a clear message will be helpful. That's what I am trying to get clarification.

Quoted 8 lines
Quoted 6 lines

OK. I think we'd agreed to that at ELC-E last year and it might have been in a few here-and-there emails but it's worth spelling out somewhere.

Hey Simon? doc/driver-model/README.txt has a pdata example, so maybe the answer here is it's time to update README.txt in a few ways :)

I'll prepare a patch.

thanks!

Signature · 1 line
Jagan | openedev.
#129 lore raw

v3 cover dm: Introduce new driver model uclasses

Quoted 50 lines · Jagan Teki
Quoted 41 lines · Simon Glass

Hi Tom,

Quoted 38 lines · Tom Rini
Quoted 37 lines · York Sun
Quoted 34 lines · Tom Rini
Quoted 19 lines · York Sun
Quoted 8 lines · Simon Glass

Hi York,

Quoted 5 lines · York Sun

Simon,

Does the dm force using device tree? I was reviewing a patch set regarding SPI and found OF_CONTROL has to be selected in order to get the driver model happy.

Quoted 7 lines
Quoted 2 lines

My understanding of the driver model is both device tree and platform data are allowed, like Linux. Is that still true?

For buses you need device tree. I was rather hoping that we could avoid platform data on platforms that have device tree. What is the point?

Quoted 8 lines

Simon,

It happens on a platform not using device tree, but DM will be used.

I prefer DM to have both, rather than being forced to use device tree, unless we are going to enforce using device tree on all new platforms. Since device tree is still an option, I feel it is best to support platform data, like Linux drivers do.

Well, to what end? My recollection is that in short, the kernel has both since platform data predates device tree (and converting platform data to device tree is still a thing that happens). But we're trying to skip that intermediate step. Are there platforms where you do not plan to use a device tree, ever?

My observations with this approach (dm-spi)

1. We're planning to move spi driver with dm support but many of the boards which
used spi drivers don't have dts support yet.
2. I think dm will progress only when dts support progresses.

Quoted 5 lines

The only solution for this - if we need to move any driver to dm then check for dts on particular board this driver uses and move that board to have dts support.

Any comments?

Any suggestions?

Quoted 10 lines
Quoted 10 lines
Quoted 10 lines
Quoted 9 lines
Quoted 2 lines

Tom,

I am not against using device tree at all. It is more dynamic and flexible. But I don't see any indication that we favor device tree over pdata (except in the code). If we are skipping pdata for new drivers, a clear message will be helpful. That's what I am trying to get clarification.

Quoted 8 lines
Quoted 8 lines
Quoted 6 lines

OK. I think we'd agreed to that at ELC-E last year and it might have been in a few here-and-there emails but it's worth spelling out somewhere.

Hey Simon? doc/driver-model/README.txt has a pdata example, so maybe the answer here is it's time to update README.txt in a few ways :)

I'll prepare a patch.

thanks!

Signature · 1 line
Jagan | openedev.
#130 lore raw

v3 cover dm: Introduce new driver model uclasses

Hi Jagan,

Quoted 51 lines · Jagan Teki
Quoted 50 lines · Jagan Teki
Quoted 41 lines · Simon Glass

Hi Tom,

Quoted 38 lines · Tom Rini
Quoted 37 lines · York Sun
Quoted 34 lines · Tom Rini
Quoted 19 lines · York Sun
Quoted 8 lines · Simon Glass

Hi York,

Quoted 5 lines · York Sun

Simon,

Does the dm force using device tree? I was reviewing a patch set regarding SPI and found OF_CONTROL has to be selected in order to get the driver model happy.

Quoted 7 lines
Quoted 2 lines

My understanding of the driver model is both device tree and platform data are allowed, like Linux. Is that still true?

For buses you need device tree. I was rather hoping that we could avoid platform data on platforms that have device tree. What is the point?

Quoted 8 lines

Simon,

It happens on a platform not using device tree, but DM will be used.

I prefer DM to have both, rather than being forced to use device tree, unless we are going to enforce using device tree on all new platforms. Since device tree is still an option, I feel it is best to support platform data, like Linux drivers do.

Well, to what end? My recollection is that in short, the kernel has both since platform data predates device tree (and converting platform data to device tree is still a thing that happens). But we're trying to skip that intermediate step. Are there platforms where you do not plan to use a device tree, ever?

My observations with this approach (dm-spi)

1. We're planning to move spi driver with dm support but many of the boards which
used spi drivers don't have dts support yet.
2. I think dm will progress only when dts support progresses.

Quoted 8 lines
Quoted 5 lines

The only solution for this - if we need to move any driver to dm then check for dts on particular board this driver uses and move that board to have dts support.

Any comments?

Any suggestions?

Yes, or maybe enable DTS for the board? It's not that hard. E.g. see this for Raspberry Pi:

http://patchwork.ozlabs.org/patch/492694/
http://patchwork.ozlabs.org/patch/492698/
http://patchwork.ozlabs.org/patch/492700/

Quoted 14 lines
Quoted 14 lines
Quoted 14 lines
Quoted 14 lines
Quoted 9 lines
Quoted 2 lines

Tom,

I am not against using device tree at all. It is more dynamic and flexible. But I don't see any indication that we favor device tree over pdata (except in the code). If we are skipping pdata for new drivers, a clear message will be helpful. That's what I am trying to get clarification.

OK. I think we'd agreed to that at ELC-E last year and it might have been in a few here-and-there emails but it's worth spelling out somewhere.

Quoted 8 lines
Quoted 4 lines
Quoted 4 lines
Quoted 2 lines

Hey Simon? doc/driver-model/README.txt has a pdata example, so maybe the answer here is it's time to update README.txt in a few ways :)

I'll prepare a patch.

thanks!
--
Jagan | openedev.

Regards,
Simon

#131 lore raw

v3 cover dm: Introduce new driver model uclasses

In reply to York Sun
Quoted 19 lines · York Sun
Quoted 8 lines · Simon Glass

Hi York,

Quoted 5 lines · York Sun

Simon,

Does the dm force using device tree? I was reviewing a patch set regarding SPI and found OF_CONTROL has to be selected in order to get the driver model happy.

Quoted 7 lines
Quoted 2 lines

My understanding of the driver model is both device tree and platform data are allowed, like Linux. Is that still true?

For buses you need device tree. I was rather hoping that we could avoid platform data on platforms that have device tree. What is the point?

Quoted 8 lines

Simon,

It happens on a platform not using device tree, but DM will be used.

I prefer DM to have both, rather than being forced to use device tree, unless we are going to enforce using device tree on all new platforms. Since device tree is still an option, I feel it is best to support platform data, like Linux drivers do.

I can understand your concern about pdata, but the dts is more dynamic approach to get the device data and at least some of the architecture in u-boot had a support
for it. And if we start with dts boards will turn it on to use dts instead of going back to
use legacy pdata which is so called static approach (which might increase the board
code, some times increasing configs)

Using/adding/going by dts support is more generic and dynamic instead of static, IMHO

thanks!

Signature · 1 line
Jagan | openedev.
#132 lore raw

v3 cover dm: Introduce new driver model uclasses

In reply to Simon Glass

Hi,

Quoted 12 lines · Simon Glass

This series adds several new uclasses. Some of these have been discussed for a while. All are fairly simple and just provide enough functionality for existing use cases. The following are included in this series:

- Clocks - setting and getting PLL and peripheral clocks
- Pinctrl - adjusting pin multiplexing settings
- Reset - reseting the board or SoC
- RAM - setting up RAM controllers and detecting the available RAM
- MMC - MMC controllers (using the existing block device framework)
- LEDs - turning LEDs on and off, with only a GPIO driver so far

Quoted 4 lines

Trivial support is also added for regmap and syscon controllers, modelled on how the kernel does this.

This builds on the SPL device tree support which was recently added.

I've started up a u-boot-dm/next tree again for the next release. I'm planning start applying patches from this soon, or at least the ones that don't need a respin. Please let me know if there are any more comments. I can still fix things after they are applied (basically drop patches and start again) but it is easier to get things right first time.

[snip]

Regards,
Simon