9970 lines
304 KiB
Diff
9970 lines
304 KiB
Diff
From b3ad756bcf4959e8ec4c2cfdcd8d0eeeca12a845 Mon Sep 17 00:00:00 2001
|
|
From: Romuald JEANNE <romuald.jeanne@st.com>
|
|
Date: Fri, 5 Jun 2020 13:45:13 +0200
|
|
Subject: [PATCH 3/5] ARM v2020.01-stm32mp-r1 MISC-DRIVERS
|
|
|
|
---
|
|
cmd/Kconfig | 1 +
|
|
cmd/dtimg.c | 50 ++-
|
|
cmd/mtd.c | 24 +-
|
|
cmd/nvedit.c | 39 ++-
|
|
common/board_f.c | 27 +-
|
|
common/cli_readline.c | 6 +
|
|
common/image-android-dt.c | 42 +++
|
|
configs/igep00x0_defconfig | 1 +
|
|
configs/mt8518_ap1_emmc_defconfig | 2 +
|
|
configs/odroid-xu3_defconfig | 1 +
|
|
configs/odroid_defconfig | 1 +
|
|
configs/sandbox64_defconfig | 1 +
|
|
configs/sandbox_defconfig | 1 +
|
|
configs/sandbox_flattree_defconfig | 1 +
|
|
configs/sandbox_spl_defconfig | 1 +
|
|
doc/README.gpio | 42 +++
|
|
doc/android/fastboot.txt | 3 +
|
|
doc/device-tree-bindings/clock/st,stm32-rcc.txt | 37 ++
|
|
doc/device-tree-bindings/clock/st,stm32mp1.txt | 36 +-
|
|
doc/device-tree-bindings/gpio/gpio.txt | 304 ++++++++++-------
|
|
doc/device-tree-bindings/i2c/i2c-stm32.txt | 105 +++++-
|
|
.../memory-controllers/st,stm32mp1-ddr.txt | 2 +
|
|
doc/device-tree-bindings/mtd/stm32-fmc2-nand.txt | 6 +-
|
|
doc/device-tree-bindings/phy/phy-stm32-usbphyc.txt | 55 ++-
|
|
drivers/ata/dwc_ahci.c | 4 +-
|
|
drivers/clk/Kconfig | 8 +
|
|
drivers/clk/Makefile | 1 +
|
|
drivers/clk/clk_scmi.c | 152 +++++++++
|
|
drivers/clk/clk_stm32mp1.c | 378 +++++++++++++++++----
|
|
drivers/core/of_access.c | 32 ++
|
|
drivers/core/ofnode.c | 48 +++
|
|
drivers/core/read.c | 16 +
|
|
drivers/core/root.c | 52 +--
|
|
drivers/dfu/Kconfig | 5 +
|
|
drivers/fastboot/Kconfig | 68 ++++
|
|
drivers/fastboot/fb_command.c | 72 ++++
|
|
drivers/fastboot/fb_mmc.c | 118 +++++++
|
|
drivers/gpio/gpio-uclass.c | 203 ++++++++---
|
|
drivers/gpio/mpc8xxx_gpio.c | 22 --
|
|
drivers/gpio/sandbox.c | 321 ++++++++++++++---
|
|
drivers/gpio/stm32_gpio.c | 152 ++++++++-
|
|
drivers/i2c/stm32f7_i2c.c | 128 +++----
|
|
drivers/mailbox/Kconfig | 7 +
|
|
drivers/mailbox/Makefile | 1 +
|
|
drivers/mailbox/arm-smc-mbox.c | 118 +++++++
|
|
drivers/misc/Kconfig | 12 +
|
|
drivers/misc/Makefile | 1 +
|
|
drivers/misc/scmi_agent.c | 337 ++++++++++++++++++
|
|
drivers/mmc/stm32_sdmmc2.c | 2 +-
|
|
drivers/mtd/Kconfig | 7 +
|
|
drivers/net/dwc_eth_qos.c | 73 +++-
|
|
drivers/phy/phy-stm32-usbphyc.c | 2 +-
|
|
drivers/phy/phy-uclass.c | 40 ++-
|
|
drivers/pinctrl/pinctrl-generic.c | 30 +-
|
|
drivers/pinctrl/pinctrl-sandbox.c | 44 ++-
|
|
drivers/pinctrl/pinctrl-single.c | 27 +-
|
|
drivers/pinctrl/pinctrl-stmfx.c | 232 +++++++++----
|
|
drivers/pinctrl/pinctrl_stm32.c | 27 +-
|
|
drivers/power/regulator/stm32-vrefbuf.c | 16 +-
|
|
drivers/ram/stm32mp1/stm32mp1_ddr.c | 54 ++-
|
|
drivers/ram/stm32mp1/stm32mp1_ddr.h | 1 +
|
|
drivers/ram/stm32mp1/stm32mp1_ddr_regs.h | 1 +
|
|
drivers/ram/stm32mp1/stm32mp1_interactive.c | 17 +-
|
|
drivers/ram/stm32mp1/stm32mp1_ram.c | 34 +-
|
|
drivers/ram/stm32mp1/stm32mp1_tests.c | 31 +-
|
|
drivers/ram/stm32mp1/stm32mp1_tuning.c | 223 ++++++++++--
|
|
drivers/remoteproc/rproc-elf-loader.c | 269 +++++++++++++++
|
|
drivers/remoteproc/stm32_copro.c | 61 +++-
|
|
drivers/reset/Kconfig | 8 +
|
|
drivers/reset/Makefile | 1 +
|
|
drivers/reset/reset-scmi.c | 86 +++++
|
|
drivers/tee/optee/core.c | 13 +-
|
|
drivers/usb/dwc3/core.c | 12 +-
|
|
drivers/usb/gadget/dwc2_udc_otg.c | 6 +-
|
|
drivers/usb/gadget/g_dnl.c | 8 +
|
|
drivers/usb/host/dwc2.c | 118 ++++++-
|
|
drivers/usb/host/ehci-hcd.c | 8 +-
|
|
drivers/usb/host/ohci-generic.c | 8 +-
|
|
drivers/usb/musb-new/sunxi.c | 8 +-
|
|
drivers/video/orisetech_otm8009a.c | 20 +-
|
|
drivers/video/raydium-rm68200.c | 20 +-
|
|
drivers/video/stm32/stm32_dsi.c | 15 +-
|
|
env/mmc.c | 26 +-
|
|
include/asm-generic/gpio.h | 102 +++---
|
|
include/clk.h | 104 +++++-
|
|
include/configs/odroid.h | 1 -
|
|
include/configs/odroid_xu3.h | 1 -
|
|
include/configs/omap3_igep00x0.h | 2 -
|
|
include/configs/stm32f429-evaluation.h | 15 +-
|
|
include/configs/stm32f469-discovery.h | 15 +-
|
|
include/configs/stm32f746-disco.h | 15 +-
|
|
include/configs/stm32h743-disco.h | 14 +-
|
|
include/configs/stm32h743-eval.h | 14 +-
|
|
include/configs/stm32mp1.h | 208 +++++++-----
|
|
include/dfu.h | 3 +
|
|
include/dm/of_access.h | 40 +++
|
|
include/dm/ofnode.h | 63 +++-
|
|
include/dm/read.h | 67 ++++
|
|
include/dt-bindings/clock/stm32mp1-clks.h | 33 ++
|
|
include/dt-bindings/gpio/gpio.h | 6 +
|
|
include/dt-bindings/gpio/sandbox-gpio.h | 24 ++
|
|
include/dt-bindings/mfd/stm32h7-rcc.h | 1 -
|
|
include/dt-bindings/pinctrl/stm32-pinfunc.h | 1 +
|
|
include/dt-bindings/reset/stm32mp1-resets.h | 13 +
|
|
include/dt-bindings/rtc/rtc-stm32.h | 13 +
|
|
include/dt-bindings/soc/stm32-hdp.h | 108 ++++++
|
|
include/env_internal.h | 31 ++
|
|
include/fastboot.h | 6 +
|
|
include/g_dnl.h | 1 +
|
|
include/i2c.h | 26 ++
|
|
include/image-android-dt.h | 2 +
|
|
include/mipi_dsi.h | 6 +
|
|
include/mtd.h | 2 +
|
|
include/power/stpmic1.h | 1 +
|
|
include/remoteproc.h | 70 ++++
|
|
include/scmi_agent.h | 82 +++++
|
|
lib/libfdt/fdt_ro.c | 20 +-
|
|
lib/optee/optee.c | 2 +-
|
|
scripts/config_whitelist.txt | 2 -
|
|
scripts/dtc/libfdt/fdt_ro.c | 20 +-
|
|
scripts/dtc/libfdt/libfdt.h | 33 +-
|
|
test/dm/Makefile | 1 +
|
|
test/dm/gpio.c | 69 +++-
|
|
test/dm/ofread.c | 50 +++
|
|
test/dm/remoteproc.c | 91 ++++-
|
|
test/dm/test-fdt.c | 4 +-
|
|
test/py/tests/test_env.py | 44 +++
|
|
test/py/tests/test_pinmux.py | 38 ++-
|
|
tools/fdtgrep.c | 6 +-
|
|
tools/stm32image.c | 5 +-
|
|
130 files changed, 5029 insertions(+), 1038 deletions(-)
|
|
create mode 100644 doc/README.gpio
|
|
create mode 100644 drivers/clk/clk_scmi.c
|
|
create mode 100644 drivers/mailbox/arm-smc-mbox.c
|
|
create mode 100644 drivers/misc/scmi_agent.c
|
|
create mode 100644 drivers/reset/reset-scmi.c
|
|
create mode 100644 include/dt-bindings/gpio/sandbox-gpio.h
|
|
create mode 100644 include/dt-bindings/rtc/rtc-stm32.h
|
|
create mode 100644 include/dt-bindings/soc/stm32-hdp.h
|
|
create mode 100644 include/scmi_agent.h
|
|
create mode 100644 test/dm/ofread.c
|
|
|
|
diff --git a/cmd/Kconfig b/cmd/Kconfig
|
|
index 1e4cf14..8a44461 100644
|
|
--- a/cmd/Kconfig
|
|
+++ b/cmd/Kconfig
|
|
@@ -551,6 +551,7 @@ config CMD_NVEDIT_INFO
|
|
This command can be optionally used for evaluation in scripts:
|
|
[-d] : evaluate whether default environment is used
|
|
[-p] : evaluate whether environment can be persisted
|
|
+ [-q] : quiet output
|
|
The result of multiple evaluations will be combined with AND.
|
|
|
|
endmenu
|
|
diff --git a/cmd/dtimg.c b/cmd/dtimg.c
|
|
index 6c5d53c..cd221b2 100644
|
|
--- a/cmd/dtimg.c
|
|
+++ b/cmd/dtimg.c
|
|
@@ -99,10 +99,52 @@ static int do_dtimg_size(cmd_tbl_t *cmdtp, int flag, int argc,
|
|
return dtimg_get_fdt(argc, argv, CMD_DTIMG_SIZE);
|
|
}
|
|
|
|
+static int do_dtimg_getindex(cmd_tbl_t *cmdtp, int flag, int argc,
|
|
+ char * const argv[])
|
|
+{
|
|
+ char *endp;
|
|
+ ulong hdr_addr;
|
|
+ int index;
|
|
+ char buf[512] = { 0 };
|
|
+
|
|
+ if (argc < 4)
|
|
+ return CMD_RET_USAGE;
|
|
+
|
|
+ hdr_addr = simple_strtoul(argv[1], &endp, 16);
|
|
+ if (*endp != '\0') {
|
|
+ printf("Error: Wrong image address\n");
|
|
+ return CMD_RET_FAILURE;
|
|
+ }
|
|
+
|
|
+ if (!android_dt_check_header(hdr_addr)) {
|
|
+ printf("Error: DT image header is incorrect\n");
|
|
+ return CMD_RET_FAILURE;
|
|
+ }
|
|
+
|
|
+ index = android_dt_get_index(hdr_addr, strtoul(argv[2], NULL, 0),
|
|
+ strtoul(argv[3], NULL, 0));
|
|
+
|
|
+ if (index < 0) {
|
|
+ printf("Error: board id %04lx not found in DT table\n",
|
|
+ strtoul(argv[2], NULL, 0));
|
|
+ return CMD_RET_FAILURE;
|
|
+ }
|
|
+
|
|
+ snprintf(buf, sizeof(buf), "%i", index);
|
|
+
|
|
+ if (argc == 5)
|
|
+ env_set(argv[4], buf);
|
|
+ else
|
|
+ printf("%s\n", buf);
|
|
+
|
|
+ return CMD_RET_SUCCESS;
|
|
+}
|
|
+
|
|
static cmd_tbl_t cmd_dtimg_sub[] = {
|
|
U_BOOT_CMD_MKENT(dump, 2, 0, do_dtimg_dump, "", ""),
|
|
U_BOOT_CMD_MKENT(start, 4, 0, do_dtimg_start, "", ""),
|
|
U_BOOT_CMD_MKENT(size, 4, 0, do_dtimg_size, "", ""),
|
|
+ U_BOOT_CMD_MKENT(getindex, 5, 0, do_dtimg_getindex, "", ""),
|
|
};
|
|
|
|
static int do_dtimg(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
|
|
@@ -138,5 +180,11 @@ U_BOOT_CMD(
|
|
" - get size (hex, bytes) of FDT in the image, by index\n"
|
|
" <addr>: image address in RAM, in hex\n"
|
|
" <index>: index of desired FDT in the image\n"
|
|
- " <varname>: name of variable where to store size of FDT"
|
|
+ " <varname>: name of variable where to store size of FDT\n"
|
|
+ "dtimg getindex <addr> <board_id> <board_rev> [varname]\n"
|
|
+ " - get index of FDT in the image, by board identifier and revision\n"
|
|
+ " <addr>: image address in RAM, in hex\n"
|
|
+ " <board_id>: board identifier\n"
|
|
+ " <board_rev>: board revision (0 if not used)\n"
|
|
+ " [varname]: name of variable where to store index of FDT"
|
|
);
|
|
diff --git a/cmd/mtd.c b/cmd/mtd.c
|
|
index 1b6b8dd..a559b5a 100644
|
|
--- a/cmd/mtd.c
|
|
+++ b/cmd/mtd.c
|
|
@@ -387,7 +387,7 @@ static int do_mtd_erase(cmd_tbl_t *cmdtp, int flag, int argc,
|
|
struct mtd_info *mtd;
|
|
u64 off, len;
|
|
bool scrub;
|
|
- int ret;
|
|
+ int ret = 0;
|
|
|
|
if (argc < 2)
|
|
return CMD_RET_USAGE;
|
|
@@ -423,22 +423,22 @@ static int do_mtd_erase(cmd_tbl_t *cmdtp, int flag, int argc,
|
|
|
|
erase_op.mtd = mtd;
|
|
erase_op.addr = off;
|
|
- erase_op.len = len;
|
|
+ erase_op.len = mtd->erasesize;
|
|
erase_op.scrub = scrub;
|
|
|
|
- while (erase_op.len) {
|
|
+ while (len) {
|
|
ret = mtd_erase(mtd, &erase_op);
|
|
|
|
- /* Abort if its not a bad block error */
|
|
- if (ret != -EIO)
|
|
- break;
|
|
-
|
|
- printf("Skipping bad block at 0x%08llx\n", erase_op.fail_addr);
|
|
+ if (ret) {
|
|
+ /* Abort if its not a bad block error */
|
|
+ if (ret != -EIO)
|
|
+ break;
|
|
+ printf("Skipping bad block at 0x%08llx\n",
|
|
+ erase_op.addr);
|
|
+ }
|
|
|
|
- /* Skip bad block and continue behind it */
|
|
- erase_op.len -= erase_op.fail_addr - erase_op.addr;
|
|
- erase_op.len -= mtd->erasesize;
|
|
- erase_op.addr = erase_op.fail_addr + mtd->erasesize;
|
|
+ len -= mtd->erasesize;
|
|
+ erase_op.addr += mtd->erasesize;
|
|
}
|
|
|
|
if (ret && ret != -EIO)
|
|
diff --git a/cmd/nvedit.c b/cmd/nvedit.c
|
|
index 81d94cd..218fdfb 100644
|
|
--- a/cmd/nvedit.c
|
|
+++ b/cmd/nvedit.c
|
|
@@ -1219,12 +1219,18 @@ static int print_env_info(void)
|
|
* env info - display environment information
|
|
* env info [-d] - evaluate whether default environment is used
|
|
* env info [-p] - evaluate whether environment can be persisted
|
|
+ * Add [-q] - quiet mode, use only for command result, for test by example:
|
|
+ * test env info -p -d -q
|
|
*/
|
|
static int do_env_info(cmd_tbl_t *cmdtp, int flag,
|
|
int argc, char * const argv[])
|
|
{
|
|
int eval_flags = 0;
|
|
int eval_results = 0;
|
|
+ bool quiet = false;
|
|
+#if defined(CONFIG_CMD_SAVEENV) && defined(ENV_IS_IN_DEVICE)
|
|
+ enum env_location loc;
|
|
+#endif
|
|
|
|
/* display environment information */
|
|
if (argc <= 1)
|
|
@@ -1242,6 +1248,9 @@ static int do_env_info(cmd_tbl_t *cmdtp, int flag,
|
|
case 'p':
|
|
eval_flags |= ENV_INFO_IS_PERSISTED;
|
|
break;
|
|
+ case 'q':
|
|
+ quiet = true;
|
|
+ break;
|
|
default:
|
|
return CMD_RET_USAGE;
|
|
}
|
|
@@ -1251,20 +1260,30 @@ static int do_env_info(cmd_tbl_t *cmdtp, int flag,
|
|
/* evaluate whether default environment is used */
|
|
if (eval_flags & ENV_INFO_IS_DEFAULT) {
|
|
if (gd->flags & GD_FLG_ENV_DEFAULT) {
|
|
- printf("Default environment is used\n");
|
|
+ if (!quiet)
|
|
+ printf("Default environment is used\n");
|
|
eval_results |= ENV_INFO_IS_DEFAULT;
|
|
} else {
|
|
- printf("Environment was loaded from persistent storage\n");
|
|
+ if (!quiet)
|
|
+ printf("Environment was loaded from persistent storage\n");
|
|
}
|
|
}
|
|
|
|
/* evaluate whether environment can be persisted */
|
|
if (eval_flags & ENV_INFO_IS_PERSISTED) {
|
|
-#if defined(CONFIG_CMD_SAVEENV) && !defined(CONFIG_ENV_IS_NOWHERE)
|
|
- printf("Environment can be persisted\n");
|
|
- eval_results |= ENV_INFO_IS_PERSISTED;
|
|
+#if defined(CONFIG_CMD_SAVEENV) && defined(ENV_IS_IN_DEVICE)
|
|
+ loc = env_get_location(ENVOP_SAVE, gd->env_load_prio);
|
|
+ if (ENVL_NOWHERE != loc && ENVL_UNKNOWN != loc) {
|
|
+ if (!quiet)
|
|
+ printf("Environment can be persisted\n");
|
|
+ eval_results |= ENV_INFO_IS_PERSISTED;
|
|
+ } else {
|
|
+ if (!quiet)
|
|
+ printf("Environment cannot be persisted\n");
|
|
+ }
|
|
#else
|
|
- printf("Environment cannot be persisted\n");
|
|
+ if (!quiet)
|
|
+ printf("Environment cannot be persisted\n");
|
|
#endif
|
|
}
|
|
|
|
@@ -1321,7 +1340,7 @@ static cmd_tbl_t cmd_env_sub[] = {
|
|
U_BOOT_CMD_MKENT(import, 5, 0, do_env_import, "", ""),
|
|
#endif
|
|
#if defined(CONFIG_CMD_NVEDIT_INFO)
|
|
- U_BOOT_CMD_MKENT(info, 2, 0, do_env_info, "", ""),
|
|
+ U_BOOT_CMD_MKENT(info, 3, 0, do_env_info, "", ""),
|
|
#endif
|
|
U_BOOT_CMD_MKENT(print, CONFIG_SYS_MAXARGS, 1, do_env_print, "", ""),
|
|
#if defined(CONFIG_CMD_RUN)
|
|
@@ -1400,8 +1419,10 @@ static char env_help_text[] =
|
|
#endif
|
|
#if defined(CONFIG_CMD_NVEDIT_INFO)
|
|
"env info - display environment information\n"
|
|
- "env info [-d] - whether default environment is used\n"
|
|
- "env info [-p] - whether environment can be persisted\n"
|
|
+ "env info [-d] [-p] [-q] - evaluate environment information\n"
|
|
+ " \"-d\": default environment is used\n"
|
|
+ " \"-p\": environment can be persisted\n"
|
|
+ " \"-q\": quiet output\n"
|
|
#endif
|
|
"env print [-a | name ...] - print environment\n"
|
|
#if defined(CONFIG_CMD_NVEDIT_EFI)
|
|
diff --git a/common/board_f.c b/common/board_f.c
|
|
index d66afb3..ef59630 100644
|
|
--- a/common/board_f.c
|
|
+++ b/common/board_f.c
|
|
@@ -470,6 +470,17 @@ static int reserve_uboot(void)
|
|
return 0;
|
|
}
|
|
|
|
+/*
|
|
+ * reserve after start_addr_sp the requested size and make the stack pointer
|
|
+ * 16-byte aligned, this alignment is needed for cast on the reserved memory
|
|
+ * ref = x86_64 ABI: https://reviews.llvm.org/D30049: 16 bytes
|
|
+ * = ARMv8 Instruction Set Overview: quad word, 16 bytes
|
|
+ */
|
|
+static unsigned long reserve_stack_aligned(size_t size)
|
|
+{
|
|
+ return ALIGN_DOWN(gd->start_addr_sp - size, 16);
|
|
+}
|
|
+
|
|
#ifdef CONFIG_SYS_NONCACHED_MEMORY
|
|
static int reserve_noncached(void)
|
|
{
|
|
@@ -495,7 +506,7 @@ static int reserve_noncached(void)
|
|
/* reserve memory for malloc() area */
|
|
static int reserve_malloc(void)
|
|
{
|
|
- gd->start_addr_sp = gd->start_addr_sp - TOTAL_MALLOC_LEN;
|
|
+ gd->start_addr_sp = reserve_stack_aligned(TOTAL_MALLOC_LEN);
|
|
debug("Reserving %dk for malloc() at: %08lx\n",
|
|
TOTAL_MALLOC_LEN >> 10, gd->start_addr_sp);
|
|
#ifdef CONFIG_SYS_NONCACHED_MEMORY
|
|
@@ -509,7 +520,7 @@ static int reserve_malloc(void)
|
|
static int reserve_board(void)
|
|
{
|
|
if (!gd->bd) {
|
|
- gd->start_addr_sp -= sizeof(bd_t);
|
|
+ gd->start_addr_sp = reserve_stack_aligned(sizeof(bd_t));
|
|
gd->bd = (bd_t *)map_sysmem(gd->start_addr_sp, sizeof(bd_t));
|
|
memset(gd->bd, '\0', sizeof(bd_t));
|
|
debug("Reserving %zu Bytes for Board Info at: %08lx\n",
|
|
@@ -528,7 +539,7 @@ static int setup_machine(void)
|
|
|
|
static int reserve_global_data(void)
|
|
{
|
|
- gd->start_addr_sp -= sizeof(gd_t);
|
|
+ gd->start_addr_sp = reserve_stack_aligned(sizeof(gd_t));
|
|
gd->new_gd = (gd_t *)map_sysmem(gd->start_addr_sp, sizeof(gd_t));
|
|
debug("Reserving %zu Bytes for Global Data at: %08lx\n",
|
|
sizeof(gd_t), gd->start_addr_sp);
|
|
@@ -546,7 +557,7 @@ static int reserve_fdt(void)
|
|
if (gd->fdt_blob) {
|
|
gd->fdt_size = ALIGN(fdt_totalsize(gd->fdt_blob) + 0x1000, 32);
|
|
|
|
- gd->start_addr_sp -= gd->fdt_size;
|
|
+ gd->start_addr_sp = reserve_stack_aligned(gd->fdt_size);
|
|
gd->new_fdt = map_sysmem(gd->start_addr_sp, gd->fdt_size);
|
|
debug("Reserving %lu Bytes for FDT at: %08lx\n",
|
|
gd->fdt_size, gd->start_addr_sp);
|
|
@@ -561,7 +572,7 @@ static int reserve_bootstage(void)
|
|
#ifdef CONFIG_BOOTSTAGE
|
|
int size = bootstage_get_size();
|
|
|
|
- gd->start_addr_sp -= size;
|
|
+ gd->start_addr_sp = reserve_stack_aligned(size);
|
|
gd->new_bootstage = map_sysmem(gd->start_addr_sp, size);
|
|
debug("Reserving %#x Bytes for bootstage at: %08lx\n", size,
|
|
gd->start_addr_sp);
|
|
@@ -578,8 +589,7 @@ __weak int arch_reserve_stacks(void)
|
|
static int reserve_stacks(void)
|
|
{
|
|
/* make stack pointer 16-byte aligned */
|
|
- gd->start_addr_sp -= 16;
|
|
- gd->start_addr_sp &= ~0xf;
|
|
+ gd->start_addr_sp = reserve_stack_aligned(16);
|
|
|
|
/*
|
|
* let the architecture-specific code tailor gd->start_addr_sp and
|
|
@@ -591,8 +601,7 @@ static int reserve_stacks(void)
|
|
static int reserve_bloblist(void)
|
|
{
|
|
#ifdef CONFIG_BLOBLIST
|
|
- gd->start_addr_sp &= ~0xf;
|
|
- gd->start_addr_sp -= CONFIG_BLOBLIST_SIZE;
|
|
+ gd->start_addr_sp = reserve_stack_aligned(CONFIG_BLOBLIST_SIZE);
|
|
gd->new_bloblist = map_sysmem(gd->start_addr_sp, CONFIG_BLOBLIST_SIZE);
|
|
#endif
|
|
|
|
diff --git a/common/cli_readline.c b/common/cli_readline.c
|
|
index 6ef7a3e..a0ae778 100644
|
|
--- a/common/cli_readline.c
|
|
+++ b/common/cli_readline.c
|
|
@@ -14,6 +14,12 @@
|
|
#include <time.h>
|
|
#include <watchdog.h>
|
|
|
|
+#ifdef CONFIG_SPL_BUILD
|
|
+#undef CONFIG_CMDLINE_EDITING
|
|
+#undef CONFIG_AUTO_COMPLETE
|
|
+#undef CONFIG_SHOW_ACTIVITY
|
|
+#endif
|
|
+
|
|
DECLARE_GLOBAL_DATA_PTR;
|
|
|
|
static const char erase_seq[] = "\b \b"; /* erase sequence */
|
|
diff --git a/common/image-android-dt.c b/common/image-android-dt.c
|
|
index a2d52df..a325e67 100644
|
|
--- a/common/image-android-dt.c
|
|
+++ b/common/image-android-dt.c
|
|
@@ -154,4 +154,46 @@ void android_dt_print_contents(ulong hdr_addr)
|
|
unmap_sysmem(fdt);
|
|
}
|
|
}
|
|
+
|
|
#endif
|
|
+
|
|
+/**
|
|
+ * Get dtb index based on board identifier and revision.
|
|
+ *
|
|
+ * @param hdr_addr Start address of DT image
|
|
+ * @param board_id board identifier
|
|
+ * @param board_rev board revision (0 if not used)
|
|
+ *
|
|
+ * @return index in dt table
|
|
+ */
|
|
+int android_dt_get_index(ulong hdr_addr, u32 board_id, u32 board_rev)
|
|
+{
|
|
+ const struct dt_table_header *hdr;
|
|
+ u32 entry_count, entries_offset, entry_size;
|
|
+ u32 i;
|
|
+ int ret = -1;
|
|
+
|
|
+ hdr = map_sysmem(hdr_addr, sizeof(*hdr));
|
|
+ entry_count = fdt32_to_cpu(hdr->dt_entry_count);
|
|
+ entries_offset = fdt32_to_cpu(hdr->dt_entries_offset);
|
|
+ entry_size = fdt32_to_cpu(hdr->dt_entry_size);
|
|
+ unmap_sysmem(hdr);
|
|
+
|
|
+ for (i = 0; i < entry_count; ++i) {
|
|
+ const ulong e_addr = hdr_addr + entries_offset + i * entry_size;
|
|
+ const struct dt_table_entry *e;
|
|
+
|
|
+ e = map_sysmem(e_addr, sizeof(*e));
|
|
+
|
|
+ if ((fdt32_to_cpu(e->id) == board_id) &&
|
|
+ (board_rev == 0 || fdt32_to_cpu(e->rev) == board_rev)) {
|
|
+ ret = i;
|
|
+ unmap_sysmem(e);
|
|
+ break;
|
|
+ }
|
|
+
|
|
+ unmap_sysmem(e);
|
|
+ }
|
|
+
|
|
+ return ret;
|
|
+}
|
|
diff --git a/configs/igep00x0_defconfig b/configs/igep00x0_defconfig
|
|
index cb72a01..483f37c 100644
|
|
--- a/configs/igep00x0_defconfig
|
|
+++ b/configs/igep00x0_defconfig
|
|
@@ -52,6 +52,7 @@ CONFIG_NET_RANDOM_ETHADDR=y
|
|
CONFIG_DM_MMC=y
|
|
CONFIG_MMC_OMAP_HS=y
|
|
CONFIG_MTD=y
|
|
+CONFIG_SYS_MTDPARTS_RUNTIME=y
|
|
CONFIG_MTD_RAW_NAND=y
|
|
CONFIG_SYS_NAND_BUSWIDTH_16BIT=y
|
|
CONFIG_SPL_NAND_SIMPLE=y
|
|
diff --git a/configs/mt8518_ap1_emmc_defconfig b/configs/mt8518_ap1_emmc_defconfig
|
|
index 6d824cc..be5ab64 100644
|
|
--- a/configs/mt8518_ap1_emmc_defconfig
|
|
+++ b/configs/mt8518_ap1_emmc_defconfig
|
|
@@ -16,6 +16,8 @@ CONFIG_DEFAULT_DEVICE_TREE="mt8518-ap1-emmc"
|
|
CONFIG_REGMAP=y
|
|
CONFIG_SYSCON=y
|
|
CONFIG_CLK=y
|
|
+CONFIG_FASTBOOT_MMC_BOOT_SUPPORT=y
|
|
+CONFIG_FASTBOOT_MMC_USER_SUPPORT=y
|
|
CONFIG_DM_MMC=y
|
|
CONFIG_MMC_HS200_SUPPORT=y
|
|
CONFIG_MMC_MTK=y
|
|
diff --git a/configs/odroid-xu3_defconfig b/configs/odroid-xu3_defconfig
|
|
index 20038d4..ff0bdc3 100644
|
|
--- a/configs/odroid-xu3_defconfig
|
|
+++ b/configs/odroid-xu3_defconfig
|
|
@@ -38,6 +38,7 @@ CONFIG_ENV_VARS_UBOOT_RUNTIME_CONFIG=y
|
|
CONFIG_ADC=y
|
|
CONFIG_ADC_EXYNOS=y
|
|
CONFIG_DFU_MMC=y
|
|
+CONFIG_SET_DFU_ALT_INFO=y
|
|
CONFIG_SUPPORT_EMMC_BOOT=y
|
|
CONFIG_MMC_DW=y
|
|
CONFIG_MTD=y
|
|
diff --git a/configs/odroid_defconfig b/configs/odroid_defconfig
|
|
index be914e4..c77541c 100644
|
|
--- a/configs/odroid_defconfig
|
|
+++ b/configs/odroid_defconfig
|
|
@@ -39,6 +39,7 @@ CONFIG_DEFAULT_DEVICE_TREE="exynos4412-odroid"
|
|
CONFIG_SYS_RELOC_GD_ENV_ADDR=y
|
|
CONFIG_ENV_VARS_UBOOT_RUNTIME_CONFIG=y
|
|
CONFIG_DFU_MMC=y
|
|
+CONFIG_SET_DFU_ALT_INFO=y
|
|
CONFIG_SYS_I2C_S3C24X0=y
|
|
CONFIG_MMC_DW=y
|
|
CONFIG_MMC_SDHCI=y
|
|
diff --git a/configs/sandbox64_defconfig b/configs/sandbox64_defconfig
|
|
index cc536ff..f3565a9 100644
|
|
--- a/configs/sandbox64_defconfig
|
|
+++ b/configs/sandbox64_defconfig
|
|
@@ -27,6 +27,7 @@ CONFIG_CMD_ASKENV=y
|
|
CONFIG_CMD_GREPENV=y
|
|
CONFIG_CMD_ENV_CALLBACK=y
|
|
CONFIG_CMD_ENV_FLAGS=y
|
|
+CONFIG_CMD_NVEDIT_INFO=y
|
|
CONFIG_LOOPW=y
|
|
CONFIG_CMD_MD5SUM=y
|
|
CONFIG_CMD_MEMINFO=y
|
|
diff --git a/configs/sandbox_defconfig b/configs/sandbox_defconfig
|
|
index 64245f7..8a2d397 100644
|
|
--- a/configs/sandbox_defconfig
|
|
+++ b/configs/sandbox_defconfig
|
|
@@ -30,6 +30,7 @@ CONFIG_CMD_ASKENV=y
|
|
CONFIG_CMD_GREPENV=y
|
|
CONFIG_CMD_ENV_CALLBACK=y
|
|
CONFIG_CMD_ENV_FLAGS=y
|
|
+CONFIG_CMD_NVEDIT_INFO=y
|
|
CONFIG_LOOPW=y
|
|
CONFIG_CMD_MD5SUM=y
|
|
CONFIG_CMD_MEMINFO=y
|
|
diff --git a/configs/sandbox_flattree_defconfig b/configs/sandbox_flattree_defconfig
|
|
index bb31b00..ffd0dfa 100644
|
|
--- a/configs/sandbox_flattree_defconfig
|
|
+++ b/configs/sandbox_flattree_defconfig
|
|
@@ -22,6 +22,7 @@ CONFIG_CMD_BOOTZ=y
|
|
# CONFIG_CMD_ELF is not set
|
|
CONFIG_CMD_ASKENV=y
|
|
CONFIG_CMD_GREPENV=y
|
|
+CONFIG_CMD_NVEDIT_INFO=y
|
|
CONFIG_LOOPW=y
|
|
CONFIG_CMD_MD5SUM=y
|
|
CONFIG_CMD_MEMINFO=y
|
|
diff --git a/configs/sandbox_spl_defconfig b/configs/sandbox_spl_defconfig
|
|
index 61a8ffd..ab2c29a 100644
|
|
--- a/configs/sandbox_spl_defconfig
|
|
+++ b/configs/sandbox_spl_defconfig
|
|
@@ -33,6 +33,7 @@ CONFIG_CMD_ASKENV=y
|
|
CONFIG_CMD_GREPENV=y
|
|
CONFIG_CMD_ENV_CALLBACK=y
|
|
CONFIG_CMD_ENV_FLAGS=y
|
|
+CONFIG_CMD_NVEDIT_INFO=y
|
|
CONFIG_LOOPW=y
|
|
CONFIG_CMD_MD5SUM=y
|
|
CONFIG_CMD_MEMINFO=y
|
|
diff --git a/doc/README.gpio b/doc/README.gpio
|
|
new file mode 100644
|
|
index 0000000..548ff37
|
|
--- /dev/null
|
|
+++ b/doc/README.gpio
|
|
@@ -0,0 +1,42 @@
|
|
+
|
|
+GPIO hog (CONFIG_GPIO_HOG)
|
|
+--------
|
|
+
|
|
+All the GPIO hog are initialized in gpio_hog_probe_all() function called in
|
|
+board_r.c just before board_late_init() but you can also acces directly to
|
|
+the gpio with gpio_hog_lookup_name().
|
|
+
|
|
+
|
|
+Example, for the device tree:
|
|
+
|
|
+ tca6416@20 {
|
|
+ compatible = "ti,tca6416";
|
|
+ reg = <0x20>;
|
|
+ #gpio-cells = <2>;
|
|
+ gpio-controller;
|
|
+
|
|
+ env_reset {
|
|
+ gpio-hog;
|
|
+ input;
|
|
+ gpios = <6 GPIO_ACTIVE_LOW>;
|
|
+ };
|
|
+ boot_rescue {
|
|
+ gpio-hog;
|
|
+ input;
|
|
+ line-name = "foo-bar-gpio";
|
|
+ gpios = <7 GPIO_ACTIVE_LOW>;
|
|
+ };
|
|
+ };
|
|
+
|
|
+You can than access the gpio in your board code with:
|
|
+
|
|
+ struct gpio_desc *desc;
|
|
+ int ret;
|
|
+
|
|
+ ret = gpio_hog_lookup_name("boot_rescue", &desc);
|
|
+ if (ret)
|
|
+ return;
|
|
+ if (dm_gpio_get_value(desc) == 1)
|
|
+ printf("\nBooting into Rescue System\n");
|
|
+ else if (dm_gpio_get_value(desc) == 0)
|
|
+ printf("\nBoot normal\n");
|
|
diff --git a/doc/android/fastboot.txt b/doc/android/fastboot.txt
|
|
index 9de1322..e01eec6 100644
|
|
--- a/doc/android/fastboot.txt
|
|
+++ b/doc/android/fastboot.txt
|
|
@@ -23,6 +23,9 @@ The current implementation supports the following standard commands:
|
|
The following OEM commands are supported (if enabled):
|
|
|
|
- oem format - this executes ``gpt write mmc %x $partitions``
|
|
+- oem partconf - this executes - ``mmc partconf %x <arg> 0`` to configure eMMC
|
|
+ with <arg> = boot_ack boot_partition
|
|
+- oem bootbus - this executes - ``mmc bootbus %x %s`` to configure eMMC
|
|
|
|
Support for both eMMC and NAND devices is included.
|
|
|
|
diff --git a/doc/device-tree-bindings/clock/st,stm32-rcc.txt b/doc/device-tree-bindings/clock/st,stm32-rcc.txt
|
|
index 0532d81..b240121 100644
|
|
--- a/doc/device-tree-bindings/clock/st,stm32-rcc.txt
|
|
+++ b/doc/device-tree-bindings/clock/st,stm32-rcc.txt
|
|
@@ -10,6 +10,7 @@ Required properties:
|
|
- compatible: Should be:
|
|
"st,stm32f42xx-rcc"
|
|
"st,stm32f469-rcc"
|
|
+ "st,stm32f746-rcc"
|
|
- reg: should be register base and length as documented in the
|
|
datasheet
|
|
- #reset-cells: 1, see below
|
|
@@ -17,6 +18,9 @@ Required properties:
|
|
property, containing a phandle to the clock device node, an index selecting
|
|
between gated clocks and other clocks and an index specifying the clock to
|
|
use.
|
|
+- clocks: External oscillator clock phandle
|
|
+ - high speed external clock signal (HSE)
|
|
+ - external I2S clock (I2S_CKIN)
|
|
|
|
Example:
|
|
|
|
@@ -25,6 +29,7 @@ Example:
|
|
#clock-cells = <2>
|
|
compatible = "st,stm32f42xx-rcc", "st,stm32-rcc";
|
|
reg = <0x40023800 0x400>;
|
|
+ clocks = <&clk_hse>, <&clk_i2s_ckin>;
|
|
};
|
|
|
|
Specifying gated clocks
|
|
@@ -66,6 +71,38 @@ The secondary index is bound with the following magic numbers:
|
|
|
|
0 SYSTICK
|
|
1 FCLK
|
|
+ 2 CLK_LSI (low-power clock source)
|
|
+ 3 CLK_LSE (generated from a 32.768 kHz low-speed external
|
|
+ crystal or ceramic resonator)
|
|
+ 4 CLK_HSE_RTC (HSE division factor for RTC clock)
|
|
+ 5 CLK_RTC (real-time clock)
|
|
+ 6 PLL_VCO_I2S (vco frequency of I2S pll)
|
|
+ 7 PLL_VCO_SAI (vco frequency of SAI pll)
|
|
+ 8 CLK_LCD (LCD-TFT)
|
|
+ 9 CLK_I2S (I2S clocks)
|
|
+ 10 CLK_SAI1 (audio clocks)
|
|
+ 11 CLK_SAI2
|
|
+ 12 CLK_I2SQ_PDIV (post divisor of pll i2s q divisor)
|
|
+ 13 CLK_SAIQ_PDIV (post divisor of pll sai q divisor)
|
|
+
|
|
+ 14 CLK_HSI (Internal ocscillator clock)
|
|
+ 15 CLK_SYSCLK (System Clock)
|
|
+ 16 CLK_HDMI_CEC (HDMI-CEC clock)
|
|
+ 17 CLK_SPDIF (SPDIF-Rx clock)
|
|
+ 18 CLK_USART1 (U(s)arts clocks)
|
|
+ 19 CLK_USART2
|
|
+ 20 CLK_USART3
|
|
+ 21 CLK_UART4
|
|
+ 22 CLK_UART5
|
|
+ 23 CLK_USART6
|
|
+ 24 CLK_UART7
|
|
+ 25 CLK_UART8
|
|
+ 26 CLK_I2C1 (I2S clocks)
|
|
+ 27 CLK_I2C2
|
|
+ 28 CLK_I2C3
|
|
+ 29 CLK_I2C4
|
|
+ 30 CLK_LPTIMER (LPTimer1 clock)
|
|
+)
|
|
|
|
Example:
|
|
|
|
diff --git a/doc/device-tree-bindings/clock/st,stm32mp1.txt b/doc/device-tree-bindings/clock/st,stm32mp1.txt
|
|
index ec1d703..4d4136d 100644
|
|
--- a/doc/device-tree-bindings/clock/st,stm32mp1.txt
|
|
+++ b/doc/device-tree-bindings/clock/st,stm32mp1.txt
|
|
@@ -12,6 +12,9 @@ describes the fields added for clock tree initialization which are not present
|
|
in Linux binding for compatible "st,stm32mp1-rcc" defined in st,stm32mp1-rcc.txt
|
|
file.
|
|
|
|
+This parent node may optionally have additional children nodes which define
|
|
+specific init values for RCC elements.
|
|
+
|
|
The added properties for clock tree initialization are:
|
|
|
|
Required properties:
|
|
@@ -78,13 +81,20 @@ Required properties:
|
|
>;
|
|
|
|
Optional Properties:
|
|
-- st,pll : A specific PLL configuration, including frequency.
|
|
+- children for a PLL configuration with "st,stm32mp1-pll" compatible
|
|
+
|
|
+ each PLL children nodes for PLL1 to PLL4 (see ref manual for details)
|
|
+ are listed with associated reg 0 to 3.
|
|
+ PLLx is off when the associated node is absent or deactivated.
|
|
|
|
- PLL children nodes for PLL1 to PLL4 (see ref manual for details)
|
|
- are listed with associated index 0 to 3 (st,pll@0 to st,pll@3).
|
|
- PLLx is off when the associated node is absent.
|
|
+ For PLL1, when the node is absent, the frequency of the OPP node is used
|
|
+ to compute the PLL setting (see compatible "operating-points-v2" in
|
|
+ opp/opp.txt for details).
|
|
|
|
Here are the available properties for each PLL node:
|
|
+ - compatible: should be "st,stm32mp1-pll"
|
|
+
|
|
+ - reg: index of the pll instance
|
|
|
|
- cfg: The parameters for PLL configuration in the following order:
|
|
DIVM DIVN DIVP DIVQ DIVR Output.
|
|
@@ -118,18 +128,26 @@ Optional Properties:
|
|
|
|
Example:
|
|
st,pll@0 {
|
|
+ compatible = "st,stm32mp1-pll";
|
|
+ reg = <0>;
|
|
cfg = < 1 53 0 0 0 1 >;
|
|
frac = < 0x810 >;
|
|
};
|
|
st,pll@1 {
|
|
+ compatible = "st,stm32mp1-pll";
|
|
+ reg = <1>;
|
|
cfg = < 1 43 1 0 0 PQR(0,1,1) >;
|
|
csg = < 10 20 1 >;
|
|
};
|
|
st,pll@2 {
|
|
+ compatible = "st,stm32mp1-pll";
|
|
+ reg = <2>;
|
|
cfg = < 2 85 3 13 3 0 >;
|
|
csg = < 10 20 SSCG_MODE_CENTER_SPREAD >;
|
|
};
|
|
st,pll@3 {
|
|
+ compatible = "st,stm32mp1-pll";
|
|
+ reg = <3>;
|
|
cfg = < 2 78 4 7 9 3 >;
|
|
};
|
|
|
|
@@ -277,6 +295,8 @@ Example of clock tree initialization
|
|
u-boot,dm-pre-reloc;
|
|
compatible = "st,stm32mp1-rcc", "syscon";
|
|
reg = <0x50000000 0x1000>;
|
|
+ #address-cells = <1>;
|
|
+ #size-cells = <0>;
|
|
#clock-cells = <1>;
|
|
#reset-cells = <1>;
|
|
interrupts = <GIC_SPI 5 IRQ_TYPE_LEVEL_HIGH>;
|
|
@@ -347,6 +367,8 @@ Example of clock tree initialization
|
|
|
|
/* VCO = 1300.0 MHz => P = 650 (CPU) */
|
|
pll1: st,pll@0 {
|
|
+ compatible = "st,stm32mp1-pll";
|
|
+ reg = <0>;
|
|
cfg = < 2 80 0 0 0 PQR(1,0,0) >;
|
|
frac = < 0x800 >;
|
|
u-boot,dm-pre-reloc;
|
|
@@ -355,6 +377,8 @@ Example of clock tree initialization
|
|
/* VCO = 1066.0 MHz => P = 266 (AXI), Q = 533 (GPU),
|
|
R = 533 (DDR) */
|
|
pll2: st,pll@1 {
|
|
+ compatible = "st,stm32mp1-pll";
|
|
+ reg = <1>;
|
|
cfg = < 2 65 1 0 0 PQR(1,1,1) >;
|
|
frac = < 0x1400 >;
|
|
u-boot,dm-pre-reloc;
|
|
@@ -362,6 +386,8 @@ Example of clock tree initialization
|
|
|
|
/* VCO = 417.8 MHz => P = 209, Q = 24, R = 11 */
|
|
pll3: st,pll@2 {
|
|
+ compatible = "st,stm32mp1-pll";
|
|
+ reg = <2>;
|
|
cfg = < 1 33 1 16 36 PQR(1,1,1) >;
|
|
frac = < 0x1a04 >;
|
|
u-boot,dm-pre-reloc;
|
|
@@ -369,6 +395,8 @@ Example of clock tree initialization
|
|
|
|
/* VCO = 594.0 MHz => P = 99, Q = 74, R = 74 */
|
|
pll4: st,pll@3 {
|
|
+ compatible = "st,stm32mp1-pll";
|
|
+ reg = <3>;
|
|
cfg = < 3 98 5 7 7 PQR(1,1,1) >;
|
|
u-boot,dm-pre-reloc;
|
|
};
|
|
diff --git a/doc/device-tree-bindings/gpio/gpio.txt b/doc/device-tree-bindings/gpio/gpio.txt
|
|
index e146917..1481ed6 100644
|
|
--- a/doc/device-tree-bindings/gpio/gpio.txt
|
|
+++ b/doc/device-tree-bindings/gpio/gpio.txt
|
|
@@ -4,19 +4,12 @@ Specifying GPIO information for devices
|
|
1) gpios property
|
|
-----------------
|
|
|
|
-Nodes that makes use of GPIOs should specify them using one or more
|
|
-properties, each containing a 'gpio-list':
|
|
-
|
|
- gpio-list ::= <single-gpio> [gpio-list]
|
|
- single-gpio ::= <gpio-phandle> <gpio-specifier>
|
|
- gpio-phandle : phandle to gpio controller node
|
|
- gpio-specifier : Array of #gpio-cells specifying specific gpio
|
|
- (controller specific)
|
|
-
|
|
GPIO properties should be named "[<name>-]gpios", with <name> being the purpose
|
|
of this GPIO for the device. While a non-existent <name> is considered valid
|
|
for compatibility reasons (resolving to the "gpios" property), it is not allowed
|
|
-for new bindings.
|
|
+for new bindings. Also, GPIO properties named "[<name>-]gpio" are valid and old
|
|
+bindings use it, but are only supported for compatibility reasons and should not
|
|
+be used for newer bindings since it has been deprecated.
|
|
|
|
GPIO properties can contain one or more GPIO phandles, but only in exceptional
|
|
cases should they contain more than one. If your device uses several GPIOs with
|
|
@@ -31,30 +24,28 @@ The following example could be used to describe GPIO pins used as device enable
|
|
and bit-banged data signals:
|
|
|
|
gpio1: gpio1 {
|
|
- gpio-controller
|
|
- #gpio-cells = <2>;
|
|
- };
|
|
- gpio2: gpio2 {
|
|
- gpio-controller
|
|
- #gpio-cells = <1>;
|
|
+ gpio-controller;
|
|
+ #gpio-cells = <2>;
|
|
};
|
|
[...]
|
|
|
|
- enable-gpios = <&gpio2 2>;
|
|
data-gpios = <&gpio1 12 0>,
|
|
<&gpio1 13 0>,
|
|
<&gpio1 14 0>,
|
|
<&gpio1 15 0>;
|
|
|
|
-Note that gpio-specifier length is controller dependent. In the
|
|
-above example, &gpio1 uses 2 cells to specify a gpio, while &gpio2
|
|
-only uses one.
|
|
+In the above example, &gpio1 uses 2 cells to specify a gpio. The first cell is
|
|
+a local offset to the GPIO line and the second cell represent consumer flags,
|
|
+such as if the consumer desire the line to be active low (inverted) or open
|
|
+drain. This is the recommended practice.
|
|
|
|
-gpio-specifier may encode: bank, pin position inside the bank,
|
|
-whether pin is open-drain and whether pin is logically inverted.
|
|
-Exact meaning of each specifier cell is controller specific, and must
|
|
-be documented in the device tree binding for the device. Use the macros
|
|
-defined in include/dt-bindings/gpio/gpio.h whenever possible:
|
|
+The exact meaning of each specifier cell is controller specific, and must be
|
|
+documented in the device tree binding for the device, but it is strongly
|
|
+recommended to use the two-cell approach.
|
|
+
|
|
+Most controllers are specifying a generic flag bitfield in the last cell, so
|
|
+for these, use the macros defined in
|
|
+include/dt-bindings/gpio/gpio.h whenever possible:
|
|
|
|
Example of a node using GPIOs:
|
|
|
|
@@ -65,6 +56,30 @@ Example of a node using GPIOs:
|
|
GPIO_ACTIVE_HIGH is 0, so in this example gpio-specifier is "18 0" and encodes
|
|
GPIO pin number, and GPIO flags as accepted by the "qe_pio_e" gpio-controller.
|
|
|
|
+Optional standard bitfield specifiers for the last cell:
|
|
+
|
|
+- Bit 0: 0 means active high, 1 means active low
|
|
+- Bit 1: 0 mean push-pull wiring, see:
|
|
+ https://en.wikipedia.org/wiki/Push-pull_output
|
|
+ 1 means single-ended wiring, see:
|
|
+ https://en.wikipedia.org/wiki/Single-ended_triode
|
|
+- Bit 2: 0 means open-source, 1 means open drain, see:
|
|
+ https://en.wikipedia.org/wiki/Open_collector
|
|
+- Bit 3: 0 means the output should be maintained during sleep/low-power mode
|
|
+ 1 means the output state can be lost during sleep/low-power mode
|
|
+- Bit 4: 0 means no pull-up resistor should be enabled
|
|
+ 1 means a pull-up resistor should be enabled
|
|
+ This setting only applies to hardware with a simple on/off
|
|
+ control for pull-up configuration. If the hardware has more
|
|
+ elaborate pull-up configuration, it should be represented
|
|
+ using a pin control binding.
|
|
+- Bit 5: 0 means no pull-down resistor should be enabled
|
|
+ 1 means a pull-down resistor should be enabled
|
|
+ This setting only applies to hardware with a simple on/off
|
|
+ control for pull-down configuration. If the hardware has more
|
|
+ elaborate pull-down configuration, it should be represented
|
|
+ using a pin control binding.
|
|
+
|
|
1.1) GPIO specifier best practices
|
|
----------------------------------
|
|
|
|
@@ -116,6 +131,80 @@ Every GPIO controller node must contain both an empty "gpio-controller"
|
|
property, and a #gpio-cells integer property, which indicates the number of
|
|
cells in a gpio-specifier.
|
|
|
|
+Some system-on-chips (SoCs) use the concept of GPIO banks. A GPIO bank is an
|
|
+instance of a hardware IP core on a silicon die, usually exposed to the
|
|
+programmer as a coherent range of I/O addresses. Usually each such bank is
|
|
+exposed in the device tree as an individual gpio-controller node, reflecting
|
|
+the fact that the hardware was synthesized by reusing the same IP block a
|
|
+few times over.
|
|
+
|
|
+Optionally, a GPIO controller may have a "ngpios" property. This property
|
|
+indicates the number of in-use slots of available slots for GPIOs. The
|
|
+typical example is something like this: the hardware register is 32 bits
|
|
+wide, but only 18 of the bits have a physical counterpart. The driver is
|
|
+generally written so that all 32 bits can be used, but the IP block is reused
|
|
+in a lot of designs, some using all 32 bits, some using 18 and some using
|
|
+12. In this case, setting "ngpios = <18>;" informs the driver that only the
|
|
+first 18 GPIOs, at local offset 0 .. 17, are in use.
|
|
+
|
|
+If these GPIOs do not happen to be the first N GPIOs at offset 0...N-1, an
|
|
+additional set of tuples is needed to specify which GPIOs are unusable, with
|
|
+the gpio-reserved-ranges binding. This property indicates the start and size
|
|
+of the GPIOs that can't be used.
|
|
+
|
|
+Optionally, a GPIO controller may have a "gpio-line-names" property. This is
|
|
+an array of strings defining the names of the GPIO lines going out of the
|
|
+GPIO controller. This name should be the most meaningful producer name
|
|
+for the system, such as a rail name indicating the usage. Package names
|
|
+such as pin name are discouraged: such lines have opaque names (since they
|
|
+are by definition generic purpose) and such names are usually not very
|
|
+helpful. For example "MMC-CD", "Red LED Vdd" and "ethernet reset" are
|
|
+reasonable line names as they describe what the line is used for. "GPIO0"
|
|
+is not a good name to give to a GPIO line. Placeholders are discouraged:
|
|
+rather use the "" (blank string) if the use of the GPIO line is undefined
|
|
+in your design. The names are assigned starting from line offset 0 from
|
|
+left to right from the passed array. An incomplete array (where the number
|
|
+of passed named are less than ngpios) will still be used up until the last
|
|
+provided valid line index.
|
|
+
|
|
+Example:
|
|
+
|
|
+gpio-controller@00000000 {
|
|
+ compatible = "foo";
|
|
+ reg = <0x00000000 0x1000>;
|
|
+ gpio-controller;
|
|
+ #gpio-cells = <2>;
|
|
+ ngpios = <18>;
|
|
+ gpio-reserved-ranges = <0 4>, <12 2>;
|
|
+ gpio-line-names = "MMC-CD", "MMC-WP", "VDD eth", "RST eth", "LED R",
|
|
+ "LED G", "LED B", "Col A", "Col B", "Col C", "Col D",
|
|
+ "Row A", "Row B", "Row C", "Row D", "NMI button",
|
|
+ "poweroff", "reset";
|
|
+}
|
|
+
|
|
+The GPIO chip may contain GPIO hog definitions. GPIO hogging is a mechanism
|
|
+providing automatic GPIO request and configuration as part of the
|
|
+gpio-controller's driver probe function.
|
|
+
|
|
+Each GPIO hog definition is represented as a child node of the GPIO controller.
|
|
+Required properties:
|
|
+- gpio-hog: A property specifying that this child node represents a GPIO hog.
|
|
+- gpios: Store the GPIO information (id, flags, ...) for each GPIO to
|
|
+ affect. Shall contain an integer multiple of the number of cells
|
|
+ specified in its parent node (GPIO controller node).
|
|
+Only one of the following properties scanned in the order shown below.
|
|
+This means that when multiple properties are present they will be searched
|
|
+in the order presented below and the first match is taken as the intended
|
|
+configuration.
|
|
+- input: A property specifying to set the GPIO direction as input.
|
|
+- output-low A property specifying to set the GPIO direction as output with
|
|
+ the value low.
|
|
+- output-high A property specifying to set the GPIO direction as output with
|
|
+ the value high.
|
|
+
|
|
+Optional properties:
|
|
+- line-name: The GPIO label name. If not present the node name is used.
|
|
+
|
|
Example of two SOC GPIO banks defined as gpio-controller nodes:
|
|
|
|
qe_pio_a: gpio-controller@1400 {
|
|
@@ -137,46 +226,40 @@ Example of two SOC GPIO banks defined as gpio-controller nodes:
|
|
|
|
Some or all of the GPIOs provided by a GPIO controller may be routed to pins
|
|
on the package via a pin controller. This allows muxing those pins between
|
|
-GPIO and other functions.
|
|
+GPIO and other functions. It is a fairly common practice among silicon
|
|
+engineers.
|
|
+
|
|
+2.2) Ordinary (numerical) GPIO ranges
|
|
+-------------------------------------
|
|
|
|
It is useful to represent which GPIOs correspond to which pins on which pin
|
|
-controllers. The gpio-ranges property described below represents this, and
|
|
-contains information structures as follows:
|
|
-
|
|
- gpio-range-list ::= <single-gpio-range> [gpio-range-list]
|
|
- single-gpio-range ::= <numeric-gpio-range> | <named-gpio-range>
|
|
- numeric-gpio-range ::=
|
|
- <pinctrl-phandle> <gpio-base> <pinctrl-base> <count>
|
|
- named-gpio-range ::= <pinctrl-phandle> <gpio-base> '<0 0>'
|
|
- pinctrl-phandle : phandle to pin controller node
|
|
- gpio-base : Base GPIO ID in the GPIO controller
|
|
- pinctrl-base : Base pinctrl pin ID in the pin controller
|
|
- count : The number of GPIOs/pins in this range
|
|
-
|
|
-The "pin controller node" mentioned above must conform to the bindings
|
|
-described in ../pinctrl/pinctrl-bindings.txt.
|
|
-
|
|
-In case named gpio ranges are used (ranges with both <pinctrl-base> and
|
|
-<count> set to 0), the property gpio-ranges-group-names contains one string
|
|
-for every single-gpio-range in gpio-ranges:
|
|
- gpiorange-names-list ::= <gpiorange-name> [gpiorange-names-list]
|
|
- gpiorange-name : Name of the pingroup associated to the GPIO range in
|
|
- the respective pin controller.
|
|
-
|
|
-Elements of gpiorange-names-list corresponding to numeric ranges contain
|
|
-the empty string. Elements of gpiorange-names-list corresponding to named
|
|
-ranges contain the name of a pin group defined in the respective pin
|
|
-controller. The number of pins/GPIOs in the range is the number of pins in
|
|
-that pin group.
|
|
+controllers. The gpio-ranges property described below represents this with
|
|
+a discrete set of ranges mapping pins from the pin controller local number space
|
|
+to pins in the GPIO controller local number space.
|
|
|
|
-Previous versions of this binding required all pin controller nodes that
|
|
-were referenced by any gpio-ranges property to contain a property named
|
|
-#gpio-range-cells with value <3>. This requirement is now deprecated.
|
|
-However, that property may still exist in older device trees for
|
|
-compatibility reasons, and would still be required even in new device
|
|
-trees that need to be compatible with older software.
|
|
+The format is: <[pin controller phandle], [GPIO controller offset],
|
|
+ [pin controller offset], [number of pins]>;
|
|
+
|
|
+The GPIO controller offset pertains to the GPIO controller node containing the
|
|
+range definition.
|
|
+
|
|
+The pin controller node referenced by the phandle must conform to the bindings
|
|
+described in pinctrl/pinctrl-bindings.txt.
|
|
+
|
|
+Each offset runs from 0 to N. It is perfectly fine to pile any number of
|
|
+ranges with just one pin-to-GPIO line mapping if the ranges are concocted, but
|
|
+in practice these ranges are often lumped in discrete sets.
|
|
+
|
|
+Example:
|
|
+
|
|
+ gpio-ranges = <&foo 0 20 10>, <&bar 10 50 20>;
|
|
+
|
|
+This means:
|
|
+- pins 20..29 on pin controller "foo" is mapped to GPIO line 0..9 and
|
|
+- pins 50..69 on pin controller "bar" is mapped to GPIO line 10..29
|
|
|
|
-Example 1:
|
|
+
|
|
+Verbose example:
|
|
|
|
qe_pio_e: gpio-controller@1460 {
|
|
#gpio-cells = <2>;
|
|
@@ -187,12 +270,33 @@ Example 1:
|
|
};
|
|
|
|
Here, a single GPIO controller has GPIOs 0..9 routed to pin controller
|
|
-pinctrl1's pins 20..29, and GPIOs 10..19 routed to pin controller pinctrl2's
|
|
-pins 50..59.
|
|
+pinctrl1's pins 20..29, and GPIOs 10..29 routed to pin controller pinctrl2's
|
|
+pins 50..69.
|
|
+
|
|
+
|
|
+2.3) GPIO ranges from named pin groups
|
|
+--------------------------------------
|
|
+
|
|
+It is also possible to use pin groups for gpio ranges when pin groups are the
|
|
+easiest and most convenient mapping.
|
|
+
|
|
+Both both <pinctrl-base> and <count> must set to 0 when using named pin groups
|
|
+names.
|
|
+
|
|
+The property gpio-ranges-group-names must contain exactly one string for each
|
|
+range.
|
|
+
|
|
+Elements of gpio-ranges-group-names must contain the name of a pin group
|
|
+defined in the respective pin controller. The number of pins/GPIO lines in the
|
|
+range is the number of pins in that pin group. The number of pins of that
|
|
+group is defined int the implementation and not in the device tree.
|
|
|
|
-Example 2:
|
|
+If numerical and named pin groups are mixed, the string corresponding to a
|
|
+numerical pin range in gpio-ranges-group-names must be empty.
|
|
|
|
- gpio_pio_i: gpio-controller@14B0 {
|
|
+Example:
|
|
+
|
|
+ gpio_pio_i: gpio-controller@14b0 {
|
|
#gpio-cells = <2>;
|
|
compatible = "fsl,qe-pario-bank-e", "fsl,qe-pario-bank";
|
|
reg = <0x1480 0x18>;
|
|
@@ -207,66 +311,14 @@ Example 2:
|
|
"bar";
|
|
};
|
|
|
|
-Here, three GPIO ranges are defined wrt. two pin controllers. pinctrl1 GPIO
|
|
-ranges are defined using pin numbers whereas the GPIO ranges wrt. pinctrl2
|
|
-are named "foo" and "bar".
|
|
-
|
|
-3) GPIO hog definitions
|
|
------------------------
|
|
-
|
|
-The GPIO chip may contain GPIO hog definitions. GPIO hogging is a mechanism
|
|
-providing automatic GPIO request and configuration as part of the
|
|
-gpio-controller's driver probe function.
|
|
+Here, three GPIO ranges are defined referring to two pin controllers.
|
|
|
|
-Each GPIO hog definition is represented as a child node of the GPIO controller.
|
|
-Required properties:
|
|
-- gpio-hog: A property specifying that this child node represents a GPIO hog.
|
|
-- gpios: Store the GPIO information (id, flags) for the GPIO to
|
|
- affect.
|
|
+pinctrl1 GPIO ranges are defined using pin numbers whereas the GPIO ranges
|
|
+in pinctrl2 are defined using the pin groups named "foo" and "bar".
|
|
|
|
- ! Not yet support more than one gpio !
|
|
-
|
|
-Only one of the following properties scanned in the order shown below.
|
|
-- input: A property specifying to set the GPIO direction as input.
|
|
-- output-low A property specifying to set the GPIO direction as output with
|
|
- the value low.
|
|
-- output-high A property specifying to set the GPIO direction as output with
|
|
- the value high.
|
|
-
|
|
-Optional properties:
|
|
-- line-name: The GPIO label name. If not present the node name is used.
|
|
-
|
|
-Example:
|
|
-
|
|
- tca6416@20 {
|
|
- compatible = "ti,tca6416";
|
|
- reg = <0x20>;
|
|
- #gpio-cells = <2>;
|
|
- gpio-controller;
|
|
-
|
|
- env_reset {
|
|
- gpio-hog;
|
|
- input;
|
|
- gpios = <6 GPIO_ACTIVE_LOW>;
|
|
- };
|
|
- boot_rescue {
|
|
- gpio-hog;
|
|
- input;
|
|
- line-name = "foo-bar-gpio";
|
|
- gpios = <7 GPIO_ACTIVE_LOW>;
|
|
- };
|
|
- };
|
|
-
|
|
-For the above Example you can than access the gpio in your boardcode
|
|
-with:
|
|
-
|
|
- struct gpio_desc *desc;
|
|
- int ret;
|
|
-
|
|
- ret = gpio_hog_lookup_name("boot_rescue", &desc);
|
|
- if (ret)
|
|
- return;
|
|
- if (dm_gpio_get_value(desc) == 1)
|
|
- printf("\nBooting into Rescue System\n");
|
|
- else if (dm_gpio_get_value(desc) == 0)
|
|
- printf("\nBoot normal\n");
|
|
+Previous versions of this binding required all pin controller nodes that
|
|
+were referenced by any gpio-ranges property to contain a property named
|
|
+#gpio-range-cells with value <3>. This requirement is now deprecated.
|
|
+However, that property may still exist in older device trees for
|
|
+compatibility reasons, and would still be required even in new device
|
|
+trees that need to be compatible with older software.
|
|
diff --git a/doc/device-tree-bindings/i2c/i2c-stm32.txt b/doc/device-tree-bindings/i2c/i2c-stm32.txt
|
|
index df03743..7f7686e 100644
|
|
--- a/doc/device-tree-bindings/i2c/i2c-stm32.txt
|
|
+++ b/doc/device-tree-bindings/i2c/i2c-stm32.txt
|
|
@@ -1,30 +1,109 @@
|
|
-* I2C controller embedded in STMicroelectronis STM32 platforms
|
|
+* I2C controller embedded in STMicroelectronics STM32 I2C platform
|
|
|
|
Required properties :
|
|
-- compatible : Must be "st,stm32f7-i2c"
|
|
+- compatible : Must be one of the following
|
|
+ - "st,stm32f4-i2c"
|
|
+ - "st,stm32f7-i2c"
|
|
- reg : Offset and length of the register set for the device
|
|
-- resets: Must contain the phandle to the reset controller
|
|
-- clocks: Must contain the input clock of the I2C instance
|
|
+- interrupts : Must contain the interrupt id for I2C event and then the
|
|
+ interrupt id for I2C error.
|
|
+ Optionnaly a wakeup interrupt may be specified.
|
|
+- resets: Must contain the phandle to the reset controller.
|
|
+- clocks: Must contain the input clock of the I2C instance.
|
|
- A pinctrl state named "default" must be defined to set pins in mode of
|
|
- operation for I2C transfer
|
|
+ operation for I2C transfer. An optional pinctrl state named "sleep" has to
|
|
+ be defined as well as to put I2C in low power mode in suspend mode.
|
|
- #address-cells = <1>;
|
|
- #size-cells = <0>;
|
|
|
|
Optional properties :
|
|
- clock-frequency : Desired I2C bus clock frequency in Hz. If not specified,
|
|
- the default 100 kHz frequency will be used. As only Normal, Fast and Fast+
|
|
- modes are implemented, possible values are 100000, 400000 and 1000000.
|
|
+ the default 100 kHz frequency will be used.
|
|
+ For STM32F4 SoC Standard-mode and Fast-mode are supported, possible values are
|
|
+ 100000 and 400000.
|
|
+ For STM32F7, STM32H7 and STM32MP1 SoCs, Standard-mode, Fast-mode and Fast-mode
|
|
+ Plus are supported, possible values are 100000, 400000 and 1000000.
|
|
+- i2c-scl-rising-time-ns: I2C SCL Rising time for the board (default: 25)
|
|
+ For STM32F7, STM32H7 and STM32MP1 only.
|
|
+- i2c-scl-falling-time-ns: I2C SCL Falling time for the board (default: 10)
|
|
+ For STM32F7, STM32H7 and STM32MP1 only.
|
|
+ I2C Timings are derived from these 2 values
|
|
+- st,syscfg-fmp: Use to set Fast Mode Plus bit within SYSCFG when Fast Mode
|
|
+ Plus speed is selected by slave.
|
|
+ 1st cell : phandle to syscfg
|
|
+ 2nd cell : register offset within SYSCFG
|
|
+ 3rd cell : register bitmask for FMP bit
|
|
+ For STM32F7, STM32H7 and STM32MP1 only.
|
|
+- st,syscfg-fmp-clr: Use to clear Fast Mode Plus bit within SYSCFG when Fast
|
|
+ Mode Plus speed is selected by slave.
|
|
+ 1st cell: phandle to syscfg
|
|
+ 2nd cell: clear register offset within SYSCFG
|
|
+ 3rd cell: register bitmask for FMP clear bit
|
|
+ For STM32MP1 family only.
|
|
|
|
Example :
|
|
|
|
- i2c1: i2c@40005400 {
|
|
- compatible = "st,stm32f7-i2c";
|
|
+ i2c@40005400 {
|
|
+ compatible = "st,stm32f4-i2c";
|
|
+ #address-cells = <1>;
|
|
+ #size-cells = <0>;
|
|
reg = <0x40005400 0x400>;
|
|
- resets = <&rcc 181>;
|
|
- clocks = <&clk_pclk1>;
|
|
+ interrupts = <31>,
|
|
+ <32>;
|
|
+ resets = <&rcc 277>;
|
|
+ clocks = <&rcc 0 149>;
|
|
+ pinctrl-0 = <&i2c1_sda_pin>, <&i2c1_scl_pin>;
|
|
pinctrl-names = "default";
|
|
- pinctrl-0 = <&pinctrl_i2c1>;
|
|
- clock-frequency = <400000>;
|
|
+ };
|
|
+
|
|
+ i2c@40005400 {
|
|
+ compatible = "st,stm32f7-i2c";
|
|
#address-cells = <1>;
|
|
#size-cells = <0>;
|
|
+ reg = <0x40005400 0x400>;
|
|
+ interrupts = <31>,
|
|
+ <32>;
|
|
+ resets = <&rcc STM32F7_APB1_RESET(I2C1)>;
|
|
+ clocks = <&rcc 1 CLK_I2C1>;
|
|
+ pinctrl-0 = <&i2c1_sda_pin>, <&i2c1_scl_pin>;
|
|
+ pinctrl-1 = <&i2c1_sda_pin_sleep>, <&i2c1_scl_pin_sleep>;
|
|
+ pinctrl-names = "default", "sleep";
|
|
+ st,syscfg-fmp = <&syscfg 0x4 0x1>;
|
|
+ st,syscfg-fmp-clr = <&syscfg 0x44 0x1>;
|
|
+ };
|
|
+
|
|
+ i2c@40013000 {
|
|
+ compatible = "st,stm32f7-i2c";
|
|
+ #address-cells = <1>;
|
|
+ #size-cells = <0>;
|
|
+ reg = <0x40013000 0x400>;
|
|
+ interrupt-names = "event", "error", "wakeup";
|
|
+ interrupts-extended = <&intc GIC_SPI 33 IRQ_TYPE_LEVEL_HIGH>,
|
|
+ <&intc GIC_SPI 34 IRQ_TYPE_LEVEL_HIGH>,
|
|
+ <&exti 22 1>;
|
|
+ clocks = <&rcc I2C2_K>;
|
|
+ resets = <&rcc I2C2_R>;
|
|
+ st,syscfg-fmp = <&syscfg 0x4 0x2>;
|
|
+ st,syscfg-fmp-clr = <&syscfg 0x44 0x2>;
|
|
+ };
|
|
+
|
|
+
|
|
+* I2C Devices
|
|
+
|
|
+An I2C device connected onto STM32 I2C controller must use a format described by
|
|
+i2c.txt file.
|
|
+
|
|
+Required properties :
|
|
+- compatible
|
|
+ Device driver compatible name
|
|
+- reg
|
|
+ I2C slave addresses (see i2c.txt for more details)
|
|
+
|
|
+Optional properties :
|
|
+
|
|
+ i2c@40013000 {
|
|
+ camera@3c {
|
|
+ compatible = "ovti,ov5640";
|
|
+ reg = <0x3c>;
|
|
+ };
|
|
};
|
|
diff --git a/doc/device-tree-bindings/memory-controllers/st,stm32mp1-ddr.txt b/doc/device-tree-bindings/memory-controllers/st,stm32mp1-ddr.txt
|
|
index ee708ce..ac6a7df 100644
|
|
--- a/doc/device-tree-bindings/memory-controllers/st,stm32mp1-ddr.txt
|
|
+++ b/doc/device-tree-bindings/memory-controllers/st,stm32mp1-ddr.txt
|
|
@@ -129,6 +129,8 @@ phyc attributes:
|
|
MR3
|
|
|
|
- st,phy-cal : phy cal depending of calibration or tuning of DDR
|
|
+ This parameter is optional; when it is absent the built-in PHY
|
|
+ calibration is done.
|
|
for STM32MP15x: 12 values are requested in this order
|
|
DX0DLLCR
|
|
DX0DQTR
|
|
diff --git a/doc/device-tree-bindings/mtd/stm32-fmc2-nand.txt b/doc/device-tree-bindings/mtd/stm32-fmc2-nand.txt
|
|
index 70e76be..ad2bef8 100644
|
|
--- a/doc/device-tree-bindings/mtd/stm32-fmc2-nand.txt
|
|
+++ b/doc/device-tree-bindings/mtd/stm32-fmc2-nand.txt
|
|
@@ -18,8 +18,10 @@ Optional properties:
|
|
- dmas: DMA specifiers (see: dma/stm32-mdma.txt)
|
|
- dma-names: Must be "tx", "rx" and "ecc"
|
|
|
|
-Optional children nodes:
|
|
-Children nodes represent the available NAND chips.
|
|
+* NAND device bindings:
|
|
+
|
|
+Required properties:
|
|
+- reg: describes the CS lines assigned to the NAND device.
|
|
|
|
Optional properties:
|
|
- nand-on-flash-bbt: see nand.txt
|
|
diff --git a/doc/device-tree-bindings/phy/phy-stm32-usbphyc.txt b/doc/device-tree-bindings/phy/phy-stm32-usbphyc.txt
|
|
index da98407..156229b 100644
|
|
--- a/doc/device-tree-bindings/phy/phy-stm32-usbphyc.txt
|
|
+++ b/doc/device-tree-bindings/phy/phy-stm32-usbphyc.txt
|
|
@@ -27,6 +27,7 @@ Required properties:
|
|
- vdda1v8-supply: phandle to the regulator providing 1V8 power to the PHY
|
|
- #address-cells: number of address cells for phys sub-nodes, must be <1>
|
|
- #size-cells: number of size cells for phys sub-nodes, must be <0>
|
|
+- #clock-cells: number of clock cells for ck_usbo_48m consumer, must be <0>
|
|
|
|
Optional properties:
|
|
- assigned-clocks: phandle + clock specifier for the PLL phy clock
|
|
@@ -36,7 +37,7 @@ Optional properties:
|
|
Required nodes: one sub-node per port the controller provides.
|
|
|
|
Phy sub-nodes
|
|
-==============
|
|
+=============
|
|
|
|
Required properties:
|
|
- reg: phy port index
|
|
@@ -45,29 +46,73 @@ Required properties:
|
|
- #phy-cells: see phy-bindings.txt in the same directory, must be <0> for PHY
|
|
port#1 and must be <1> for PHY port#2, to select USB controller
|
|
|
|
+Optional properties:
|
|
+- st,phy-tuning : phandle to the usb phy tuning node, see Phy tuning node below
|
|
+
|
|
+Phy tuning node
|
|
+===============
|
|
+
|
|
+It may be necessary to adjust the phy settings to compensate parasitics, which
|
|
+can be due to USB connector/receptacle, routing, ESD protection component, ...
|
|
+
|
|
+Here is the list of all optional parameters to tune the interface of the phy
|
|
+(HS for High-Speed, FS for Full-Speed, LS for Low-Speed)
|
|
+
|
|
+Optional properties:
|
|
+- st,current-boost: <1> current boosting of 1mA
|
|
+ <2> current boosting of 2mA
|
|
+- st,no-lsfs-fb-cap: disables the LS/FS feedback capacitor
|
|
+- st,hs-slew-ctrl: slows the HS driver slew rate by 10%
|
|
+- st,hs-dc-level: <0> decreases the HS driver DC level by 5 to 7mV
|
|
+ <1> increases the HS driver DC level by 5 to 7mV
|
|
+ <2> increases the HS driver DC level by 10 to 14mV
|
|
+- st,fs-rftime-tuning: enables the FS rise/fall tuning option
|
|
+- st,hs-rftime-reduction: enables the HS rise/fall reduction feature
|
|
+- st,hs-current-trim: controls HS driver current trimming for choke
|
|
+- st,hs-impedance-trim: controls HS driver impedance tuning for choke
|
|
+- st,squelch-level: adjusts the squelch DC threshold value
|
|
+- st,hs-rx-gain-eq: enables the HS Rx gain equalizer
|
|
+- st,hs-rx-offset: adjusts the HS Rx offset
|
|
+- st,no-hs-ftime-ctrl: disables the HS fall time control of single
|
|
+ ended signals during pre-emphasis
|
|
+- st,no-lsfs-sc: disables the short circuit protection in LS/FS driver
|
|
+- st,hs-tx-staggering: enables the basic staggering in HS Tx mode
|
|
+
|
|
|
|
Example:
|
|
+ usb_phy_tuning: usb-phy-tuning {
|
|
+ st,current-boost = <2>;
|
|
+ st,no-lfs-fb-cap;
|
|
+ st,hs-dc-level = <2>;
|
|
+ st,hs-rftime-reduction;
|
|
+ st,hs-current-trim = <5>;
|
|
+ st,hs-impedance-trim = <0>;
|
|
+ st,squelch-level = <1>;
|
|
+ st,no-hs-ftime-ctrl;
|
|
+ st,hs-tx-staggering;
|
|
+ };
|
|
+
|
|
usbphyc: usb-phy@5a006000 {
|
|
compatible = "st,stm32mp1-usbphyc";
|
|
reg = <0x5a006000 0x1000>;
|
|
clocks = <&rcc_clk USBPHY_K>;
|
|
resets = <&rcc_rst USBPHY_R>;
|
|
+ vdda1v1-supply = <®11>;
|
|
+ vdda1v8-supply = <®18>;
|
|
#address-cells = <1>;
|
|
#size-cells = <0>;
|
|
+ #clock-cells = <0>;
|
|
|
|
usbphyc_port0: usb-phy@0 {
|
|
reg = <0>;
|
|
phy-supply = <&vdd_usb>;
|
|
- vdda1v1-supply = <®11>;
|
|
- vdda1v8-supply = <®18>
|
|
#phy-cells = <0>;
|
|
};
|
|
|
|
usbphyc_port1: usb-phy@1 {
|
|
reg = <1>;
|
|
phy-supply = <&vdd_usb>;
|
|
- vdda1v1-supply = <®11>;
|
|
- vdda1v8-supply = <®18>
|
|
#phy-cells = <1>;
|
|
+ st,phy-tuning = <&usb_phy_tuning>;
|
|
};
|
|
};
|
|
diff --git a/drivers/ata/dwc_ahci.c b/drivers/ata/dwc_ahci.c
|
|
index 017650a..3c2a3ac 100644
|
|
--- a/drivers/ata/dwc_ahci.c
|
|
+++ b/drivers/ata/dwc_ahci.c
|
|
@@ -62,13 +62,13 @@ static int dwc_ahci_probe(struct udevice *dev)
|
|
|
|
ret = generic_phy_init(&phy);
|
|
if (ret) {
|
|
- pr_err("unable to initialize the sata phy\n");
|
|
+ pr_debug("unable to initialize the sata phy\n");
|
|
return ret;
|
|
}
|
|
|
|
ret = generic_phy_power_on(&phy);
|
|
if (ret) {
|
|
- pr_err("unable to power on the sata phy\n");
|
|
+ pr_debug("unable to power on the sata phy\n");
|
|
return ret;
|
|
}
|
|
|
|
diff --git a/drivers/clk/Kconfig b/drivers/clk/Kconfig
|
|
index 16d4237..322f02a 100644
|
|
--- a/drivers/clk/Kconfig
|
|
+++ b/drivers/clk/Kconfig
|
|
@@ -141,6 +141,14 @@ config CLK_CDCE9XX
|
|
Enable the clock synthesizer driver for CDCE913/925/937/949
|
|
series of chips.
|
|
|
|
+config CLK_SCMI
|
|
+ bool "Enable SCMI clock driver"
|
|
+ select SCMI_AGENT
|
|
+ help
|
|
+ Enable this option if you want to support clock devices exposed
|
|
+ by a SCMI agent based on SCMI clock protocol communication
|
|
+ with a SCMI server.
|
|
+
|
|
source "drivers/clk/analogbits/Kconfig"
|
|
source "drivers/clk/at91/Kconfig"
|
|
source "drivers/clk/exynos/Kconfig"
|
|
diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile
|
|
index 06131ed..b732852 100644
|
|
--- a/drivers/clk/Makefile
|
|
+++ b/drivers/clk/Makefile
|
|
@@ -29,6 +29,7 @@ obj-$(CONFIG_CLK_HSDK) += clk-hsdk-cgu.o
|
|
obj-$(CONFIG_CLK_MPC83XX) += mpc83xx_clk.o
|
|
obj-$(CONFIG_CLK_OWL) += owl/
|
|
obj-$(CONFIG_CLK_RENESAS) += renesas/
|
|
+obj-$(CONFIG_CLK_SCMI) += clk_scmi.o
|
|
obj-$(CONFIG_CLK_SIFIVE) += sifive/
|
|
obj-$(CONFIG_ARCH_SUNXI) += sunxi/
|
|
obj-$(CONFIG_CLK_STM32F) += clk_stm32f.o
|
|
diff --git a/drivers/clk/clk_scmi.c b/drivers/clk/clk_scmi.c
|
|
new file mode 100644
|
|
index 0000000..f24b8b0
|
|
--- /dev/null
|
|
+++ b/drivers/clk/clk_scmi.c
|
|
@@ -0,0 +1,152 @@
|
|
+// SPDX-License-Identifier: GPL-2.0+
|
|
+/*
|
|
+ * Copyright (C) 2019 Linaro Limited
|
|
+ */
|
|
+#include <asm/types.h>
|
|
+#include <common.h>
|
|
+#include <clk-uclass.h>
|
|
+#include <dm.h>
|
|
+#include <scmi_agent.h>
|
|
+
|
|
+enum scmi_clock_message_id {
|
|
+ SCMI_CLOCK_RATE_SET = 0x5,
|
|
+ SCMI_CLOCK_RATE_GET = 0x6,
|
|
+ SCMI_CLOCK_CONFIG_SET = 0x7,
|
|
+};
|
|
+
|
|
+#define SCMI_CLK_RATE_ASYNC_NOTIFY BIT(0)
|
|
+#define SCMI_CLK_RATE_ASYNC_NORESP (BIT(0) | BIT(1))
|
|
+#define SCMI_CLK_RATE_ROUND_DOWN 0
|
|
+#define SCMI_CLK_RATE_ROUND_UP BIT(2)
|
|
+#define SCMI_CLK_RATE_ROUND_CLOSEST BIT(3)
|
|
+
|
|
+struct scmi_clk_state_in {
|
|
+ u32 clock_id;
|
|
+ u32 attributes;
|
|
+};
|
|
+
|
|
+struct scmi_clk_state_out {
|
|
+ s32 status;
|
|
+};
|
|
+
|
|
+static int scmi_clk_gate(struct clk *clk, int enable)
|
|
+{
|
|
+ struct scmi_clk_state_in in = {
|
|
+ .clock_id = clk->id,
|
|
+ .attributes = enable,
|
|
+ };
|
|
+ struct scmi_clk_state_out out;
|
|
+ struct scmi_msg scmi_msg = {
|
|
+ .protocol_id = SCMI_PROTOCOL_ID_CLOCK,
|
|
+ .message_id = SCMI_CLOCK_CONFIG_SET,
|
|
+ .in_msg = (u8 *)&in,
|
|
+ .in_msg_sz = sizeof(in),
|
|
+ .out_msg = (u8 *)&out,
|
|
+ .out_msg_sz = sizeof(out),
|
|
+ };
|
|
+ int rc;
|
|
+
|
|
+ rc = scmi_agent_process_msg(clk->dev->parent, &scmi_msg);
|
|
+ if (rc)
|
|
+ return rc;
|
|
+
|
|
+ return scmi_to_linux_errno(out.status);
|
|
+}
|
|
+
|
|
+static int scmi_clk_enable(struct clk *clk)
|
|
+{
|
|
+ return scmi_clk_gate(clk, 1);
|
|
+}
|
|
+
|
|
+static int scmi_clk_disable(struct clk *clk)
|
|
+{
|
|
+ return scmi_clk_gate(clk, 0);
|
|
+}
|
|
+
|
|
+struct scmi_clk_rate_get_in {
|
|
+ u32 clock_id;
|
|
+};
|
|
+
|
|
+struct scmi_clk_rate_get_out {
|
|
+ s32 status;
|
|
+ u32 rate_lsb;
|
|
+ u32 rate_msb;
|
|
+};
|
|
+
|
|
+static ulong scmi_clk_get_rate(struct clk *clk)
|
|
+{
|
|
+ struct scmi_clk_rate_get_in in = {
|
|
+ .clock_id = clk->id,
|
|
+ };
|
|
+ struct scmi_clk_rate_get_out out;
|
|
+ struct scmi_msg scmi_msg = {
|
|
+ .protocol_id = SCMI_PROTOCOL_ID_CLOCK,
|
|
+ .message_id = SCMI_CLOCK_RATE_GET,
|
|
+ .in_msg = (u8 *)&in,
|
|
+ .in_msg_sz = sizeof(in),
|
|
+ .out_msg = (u8 *)&out,
|
|
+ .out_msg_sz = sizeof(out),
|
|
+ };
|
|
+ int rc;
|
|
+
|
|
+ rc = scmi_agent_process_msg(clk->dev->parent, &scmi_msg);
|
|
+ if (rc)
|
|
+ return 0;
|
|
+
|
|
+ rc = scmi_to_linux_errno(out.status);
|
|
+ if (rc)
|
|
+ return 0;
|
|
+
|
|
+ return (ulong)(((u64)out.rate_msb << 32) | out.rate_lsb);
|
|
+}
|
|
+
|
|
+struct scmi_clk_rate_set_in {
|
|
+ u32 clock_id;
|
|
+ u32 flags;
|
|
+ u32 rate_lsb;
|
|
+ u32 rate_msb;
|
|
+};
|
|
+
|
|
+struct scmi_clk_rate_set_out {
|
|
+ s32 status;
|
|
+};
|
|
+
|
|
+static ulong scmi_clk_set_rate(struct clk *clk, ulong rate)
|
|
+{
|
|
+ struct scmi_clk_rate_set_in in = {
|
|
+ .clock_id = clk->id,
|
|
+ .flags = SCMI_CLK_RATE_ASYNC_NORESP |
|
|
+ SCMI_CLK_RATE_ROUND_CLOSEST,
|
|
+ .rate_lsb = (u32)rate,
|
|
+ .rate_msb = (u32)((u64)rate >> 32),
|
|
+ };
|
|
+ struct scmi_clk_rate_set_out out;
|
|
+ struct scmi_msg scmi_msg = {
|
|
+ .protocol_id = SCMI_PROTOCOL_ID_CLOCK,
|
|
+ .message_id = SCMI_CLOCK_RATE_SET,
|
|
+ .in_msg = (u8 *)&in,
|
|
+ .in_msg_sz = sizeof(in),
|
|
+ .out_msg = (u8 *)&out,
|
|
+ .out_msg_sz = sizeof(out),
|
|
+ };
|
|
+ int rc;
|
|
+
|
|
+ rc = scmi_agent_process_msg(clk->dev->parent, &scmi_msg);
|
|
+ if (rc)
|
|
+ return 0;
|
|
+
|
|
+ return scmi_to_linux_errno(out.status);
|
|
+}
|
|
+
|
|
+static const struct clk_ops scmi_clk_ops = {
|
|
+ .enable = scmi_clk_enable,
|
|
+ .disable = scmi_clk_disable,
|
|
+ .get_rate = scmi_clk_get_rate,
|
|
+ .set_rate = scmi_clk_set_rate,
|
|
+};
|
|
+
|
|
+U_BOOT_DRIVER(scmi_clock) = {
|
|
+ .name = "scmi_clk",
|
|
+ .id = UCLASS_CLK,
|
|
+ .ops = &scmi_clk_ops,
|
|
+};
|
|
diff --git a/drivers/clk/clk_stm32mp1.c b/drivers/clk/clk_stm32mp1.c
|
|
index 3718970..76fddcc 100644
|
|
--- a/drivers/clk/clk_stm32mp1.c
|
|
+++ b/drivers/clk/clk_stm32mp1.c
|
|
@@ -14,6 +14,7 @@
|
|
#include <vsprintf.h>
|
|
#include <linux/io.h>
|
|
#include <linux/iopoll.h>
|
|
+#include <asm/arch/sys_proto.h>
|
|
#include <dt-bindings/clock/stm32mp1-clks.h>
|
|
#include <dt-bindings/clock/stm32mp1-clksrc.h>
|
|
|
|
@@ -95,6 +96,7 @@ DECLARE_GLOBAL_DATA_PTR;
|
|
#define RCC_I2C12CKSELR 0x8C0
|
|
#define RCC_I2C35CKSELR 0x8C4
|
|
#define RCC_SPI2S1CKSELR 0x8D8
|
|
+#define RCC_SPI45CKSELR 0x8E0
|
|
#define RCC_UART6CKSELR 0x8E4
|
|
#define RCC_UART24CKSELR 0x8E8
|
|
#define RCC_UART35CKSELR 0x8EC
|
|
@@ -241,7 +243,7 @@ DECLARE_GLOBAL_DATA_PTR;
|
|
enum stm32mp1_parent_id {
|
|
/*
|
|
* _HSI, _HSE, _CSI, _LSI, _LSE should not be moved
|
|
- * they are used as index in osc[] as entry point
|
|
+ * they are used as index in osc_clk[] as clock reference
|
|
*/
|
|
_HSI,
|
|
_HSE,
|
|
@@ -304,6 +306,7 @@ enum stm32mp1_parent_sel {
|
|
_DSI_SEL,
|
|
_ADC12_SEL,
|
|
_SPI1_SEL,
|
|
+ _SPI45_SEL,
|
|
_RTC_SEL,
|
|
_PARENT_SEL_NB,
|
|
_UNKNOWN_SEL = 0xff,
|
|
@@ -420,8 +423,7 @@ struct stm32mp1_clk_data {
|
|
struct stm32mp1_clk_priv {
|
|
fdt_addr_t base;
|
|
const struct stm32mp1_clk_data *data;
|
|
- ulong osc[NB_OSC];
|
|
- struct udevice *osc_dev[NB_OSC];
|
|
+ struct clk osc_clk[NB_OSC];
|
|
};
|
|
|
|
#define STM32MP1_CLK(off, b, idx, s) \
|
|
@@ -527,6 +529,7 @@ static const struct stm32mp1_clk_gate stm32mp1_clk_gate[] = {
|
|
STM32MP1_CLK_SET_CLR(RCC_MP_APB1ENSETR, 24, I2C5_K, _I2C35_SEL),
|
|
|
|
STM32MP1_CLK_SET_CLR(RCC_MP_APB2ENSETR, 8, SPI1_K, _SPI1_SEL),
|
|
+ STM32MP1_CLK_SET_CLR(RCC_MP_APB2ENSETR, 10, SPI5_K, _SPI45_SEL),
|
|
STM32MP1_CLK_SET_CLR(RCC_MP_APB2ENSETR, 13, USART6_K, _UART6_SEL),
|
|
|
|
STM32MP1_CLK_SET_CLR_F(RCC_MP_APB3ENSETR, 13, VREF, _PCLK3),
|
|
@@ -602,6 +605,8 @@ static const u8 dsi_parents[] = {_DSI_PHY, _PLL4_P};
|
|
static const u8 adc_parents[] = {_PLL4_R, _CK_PER, _PLL3_Q};
|
|
static const u8 spi_parents[] = {_PLL4_P, _PLL3_Q, _I2S_CKIN, _CK_PER,
|
|
_PLL3_R};
|
|
+static const u8 spi45_parents[] = {_PCLK2, _PLL4_Q, _HSI_KER, _CSI_KER,
|
|
+ _HSE_KER};
|
|
static const u8 rtc_parents[] = {_UNKNOWN_ID, _LSE, _LSI, _HSE};
|
|
|
|
static const struct stm32mp1_clk_sel stm32mp1_clk_sel[_PARENT_SEL_NB] = {
|
|
@@ -620,22 +625,33 @@ static const struct stm32mp1_clk_sel stm32mp1_clk_sel[_PARENT_SEL_NB] = {
|
|
STM32MP1_CLK_PARENT(_SDMMC3_SEL, RCC_SDMMC3CKSELR, 0, 0x7,
|
|
sdmmc3_parents),
|
|
STM32MP1_CLK_PARENT(_ETH_SEL, RCC_ETHCKSELR, 0, 0x3, eth_parents),
|
|
- STM32MP1_CLK_PARENT(_QSPI_SEL, RCC_QSPICKSELR, 0, 0xf, qspi_parents),
|
|
- STM32MP1_CLK_PARENT(_FMC_SEL, RCC_FMCCKSELR, 0, 0xf, fmc_parents),
|
|
+ STM32MP1_CLK_PARENT(_QSPI_SEL, RCC_QSPICKSELR, 0, 0x3, qspi_parents),
|
|
+ STM32MP1_CLK_PARENT(_FMC_SEL, RCC_FMCCKSELR, 0, 0x3, fmc_parents),
|
|
STM32MP1_CLK_PARENT(_USBPHY_SEL, RCC_USBCKSELR, 0, 0x3, usbphy_parents),
|
|
STM32MP1_CLK_PARENT(_USBO_SEL, RCC_USBCKSELR, 4, 0x1, usbo_parents),
|
|
STM32MP1_CLK_PARENT(_STGEN_SEL, RCC_STGENCKSELR, 0, 0x3, stgen_parents),
|
|
STM32MP1_CLK_PARENT(_DSI_SEL, RCC_DSICKSELR, 0, 0x1, dsi_parents),
|
|
- STM32MP1_CLK_PARENT(_ADC12_SEL, RCC_ADCCKSELR, 0, 0x1, adc_parents),
|
|
+ STM32MP1_CLK_PARENT(_ADC12_SEL, RCC_ADCCKSELR, 0, 0x3, adc_parents),
|
|
STM32MP1_CLK_PARENT(_SPI1_SEL, RCC_SPI2S1CKSELR, 0, 0x7, spi_parents),
|
|
+ STM32MP1_CLK_PARENT(_SPI45_SEL, RCC_SPI45CKSELR, 0, 0x7, spi45_parents),
|
|
STM32MP1_CLK_PARENT(_RTC_SEL, RCC_BDCR, RCC_BDCR_RTCSRC_SHIFT,
|
|
(RCC_BDCR_RTCSRC_MASK >> RCC_BDCR_RTCSRC_SHIFT),
|
|
rtc_parents),
|
|
};
|
|
|
|
#ifdef STM32MP1_CLOCK_TREE_INIT
|
|
+
|
|
/* define characteristic of PLL according type */
|
|
+#define DIVM_MIN 0
|
|
+#define DIVM_MAX 63
|
|
#define DIVN_MIN 24
|
|
+#define DIVP_MIN 0
|
|
+#define DIVP_MAX 127
|
|
+#define FRAC_MAX 8192
|
|
+
|
|
+#define PLL1600_VCO_MIN 800000000
|
|
+#define PLL1600_VCO_MAX 1600000000
|
|
+
|
|
static const struct stm32mp1_pll stm32mp1_pll[PLL_TYPE_NB] = {
|
|
[PLL_800] = {
|
|
.refclk_min = 4,
|
|
@@ -746,6 +762,7 @@ char * const stm32mp1_clk_parent_sel_name[_PARENT_SEL_NB] = {
|
|
[_DSI_SEL] = "DSI",
|
|
[_ADC12_SEL] = "ADC12",
|
|
[_SPI1_SEL] = "SPI1",
|
|
+ [_SPI45_SEL] = "SPI45",
|
|
[_RTC_SEL] = "RTC",
|
|
};
|
|
|
|
@@ -763,7 +780,7 @@ static ulong stm32mp1_clk_get_fixed(struct stm32mp1_clk_priv *priv, int idx)
|
|
return 0;
|
|
}
|
|
|
|
- return priv->osc[idx];
|
|
+ return clk_get_rate(&priv->osc_clk[idx]);
|
|
}
|
|
|
|
static int stm32mp1_clk_get_id(struct stm32mp1_clk_priv *priv, unsigned long id)
|
|
@@ -946,10 +963,11 @@ static ulong stm32mp1_clk_get(struct stm32mp1_clk_priv *priv, int p)
|
|
case RCC_MPCKSELR_PLL:
|
|
case RCC_MPCKSELR_PLL_MPUDIV:
|
|
clock = stm32mp1_read_pll_freq(priv, _PLL1, _DIV_P);
|
|
- if (p == RCC_MPCKSELR_PLL_MPUDIV) {
|
|
+ if ((reg & RCC_SELR_SRC_MASK) ==
|
|
+ RCC_MPCKSELR_PLL_MPUDIV) {
|
|
reg = readl(priv->base + RCC_MPCKDIVR);
|
|
- clock /= stm32mp1_mpu_div[reg &
|
|
- RCC_MPUDIV_MASK];
|
|
+ clock >>= stm32mp1_mpu_div[reg &
|
|
+ RCC_MPUDIV_MASK];
|
|
}
|
|
break;
|
|
}
|
|
@@ -1178,6 +1196,213 @@ static ulong stm32mp1_clk_get_rate(struct clk *clk)
|
|
}
|
|
|
|
#ifdef STM32MP1_CLOCK_TREE_INIT
|
|
+
|
|
+bool stm32mp1_supports_opp(u32 opp_id, u32 cpu_type)
|
|
+{
|
|
+ unsigned int id;
|
|
+
|
|
+ switch (opp_id) {
|
|
+ case 1:
|
|
+ case 2:
|
|
+ id = opp_id;
|
|
+ break;
|
|
+ default:
|
|
+ id = 1; /* default value */
|
|
+ break;
|
|
+ }
|
|
+
|
|
+ switch (cpu_type) {
|
|
+ case CPU_STM32MP157Fxx:
|
|
+ case CPU_STM32MP157Dxx:
|
|
+ case CPU_STM32MP153Fxx:
|
|
+ case CPU_STM32MP153Dxx:
|
|
+ case CPU_STM32MP151Fxx:
|
|
+ case CPU_STM32MP151Dxx:
|
|
+ return true;
|
|
+ default:
|
|
+ return id == 1;
|
|
+ }
|
|
+}
|
|
+
|
|
+__weak void board_vddcore_init(u32 voltage_mv)
|
|
+{
|
|
+}
|
|
+
|
|
+/*
|
|
+ * gets OPP parameters (frequency in KHz and voltage in mV) from
|
|
+ * an OPP table subnode. Platform HW support capabilities are also checked.
|
|
+ * Returns 0 on success and a negative FDT error code on failure.
|
|
+ */
|
|
+static int stm32mp1_get_opp(u32 cpu_type, ofnode subnode,
|
|
+ u32 *freq_khz, u32 *voltage_mv)
|
|
+{
|
|
+ u32 opp_hw;
|
|
+ u64 read_freq_64;
|
|
+ u32 read_voltage_32;
|
|
+
|
|
+ *freq_khz = 0;
|
|
+ *voltage_mv = 0;
|
|
+
|
|
+ opp_hw = ofnode_read_u32_default(subnode, "opp-supported-hw", 0);
|
|
+ if (opp_hw)
|
|
+ if (!stm32mp1_supports_opp(opp_hw, cpu_type))
|
|
+ return -FDT_ERR_BADVALUE;
|
|
+
|
|
+ read_freq_64 = ofnode_read_u64_default(subnode, "opp-hz", 0) /
|
|
+ 1000ULL;
|
|
+ read_voltage_32 = ofnode_read_u32_default(subnode, "opp-microvolt", 0) /
|
|
+ 1000U;
|
|
+
|
|
+ if (!read_voltage_32 || !read_freq_64)
|
|
+ return -FDT_ERR_NOTFOUND;
|
|
+
|
|
+ /* Frequency value expressed in KHz must fit on 32 bits */
|
|
+ if (read_freq_64 > U32_MAX)
|
|
+ return -FDT_ERR_BADVALUE;
|
|
+
|
|
+ /* Millivolt value must fit on 16 bits */
|
|
+ if (read_voltage_32 > U16_MAX)
|
|
+ return -FDT_ERR_BADVALUE;
|
|
+
|
|
+ *freq_khz = (u32)read_freq_64;
|
|
+ *voltage_mv = read_voltage_32;
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+/*
|
|
+ * parses OPP table in DT and finds the parameters for the
|
|
+ * highest frequency supported by the HW platform.
|
|
+ * Returns 0 on success and a negative FDT error code on failure.
|
|
+ */
|
|
+int stm32mp1_get_max_opp_freq(struct stm32mp1_clk_priv *priv, u64 *freq_hz)
|
|
+{
|
|
+ ofnode node, subnode;
|
|
+ int ret;
|
|
+ u32 freq = 0U, voltage = 0U;
|
|
+ u32 cpu_type = get_cpu_type();
|
|
+
|
|
+ node = ofnode_by_compatible(ofnode_null(), "operating-points-v2");
|
|
+ if (!ofnode_valid(node))
|
|
+ return -FDT_ERR_NOTFOUND;
|
|
+
|
|
+ ofnode_for_each_subnode(subnode, node) {
|
|
+ unsigned int read_freq;
|
|
+ unsigned int read_voltage;
|
|
+
|
|
+ ret = stm32mp1_get_opp(cpu_type, subnode,
|
|
+ &read_freq, &read_voltage);
|
|
+ if (ret)
|
|
+ continue;
|
|
+
|
|
+ if (read_freq > freq) {
|
|
+ freq = read_freq;
|
|
+ voltage = read_voltage;
|
|
+ }
|
|
+ }
|
|
+
|
|
+ if (!freq || !voltage)
|
|
+ return -FDT_ERR_NOTFOUND;
|
|
+
|
|
+ *freq_hz = (u64)1000U * freq;
|
|
+ board_vddcore_init(voltage);
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+static int stm32mp1_pll1_opp(struct stm32mp1_clk_priv *priv, int clksrc,
|
|
+ u32 *pllcfg, u32 *fracv)
|
|
+{
|
|
+ u32 post_divm;
|
|
+ u32 input_freq;
|
|
+ u64 output_freq;
|
|
+ u64 freq;
|
|
+ u64 vco;
|
|
+ u32 divm, divn, divp, frac;
|
|
+ int i, ret;
|
|
+ u32 diff;
|
|
+ u32 best_diff = U32_MAX;
|
|
+
|
|
+ /* PLL1 is 1600 */
|
|
+ const u32 DIVN_MAX = stm32mp1_pll[PLL_1600].divn_max;
|
|
+ const u32 POST_DIVM_MIN = stm32mp1_pll[PLL_1600].refclk_min * 1000000U;
|
|
+ const u32 POST_DIVM_MAX = stm32mp1_pll[PLL_1600].refclk_max * 1000000U;
|
|
+
|
|
+ ret = stm32mp1_get_max_opp_freq(priv, &output_freq);
|
|
+ if (ret) {
|
|
+ debug("PLL1 OPP configuraton not found (%d).\n", ret);
|
|
+ return ret;
|
|
+ }
|
|
+
|
|
+ switch (clksrc) {
|
|
+ case CLK_PLL12_HSI:
|
|
+ input_freq = stm32mp1_clk_get_fixed(priv, _HSI);
|
|
+ break;
|
|
+ case CLK_PLL12_HSE:
|
|
+ input_freq = stm32mp1_clk_get_fixed(priv, _HSE);
|
|
+ break;
|
|
+ default:
|
|
+ return -EINTR;
|
|
+ }
|
|
+
|
|
+ /* Following parameters have always the same value */
|
|
+ pllcfg[PLLCFG_Q] = 0;
|
|
+ pllcfg[PLLCFG_R] = 0;
|
|
+ pllcfg[PLLCFG_O] = PQR(1, 0, 0);
|
|
+
|
|
+ for (divm = DIVM_MAX; divm >= DIVM_MIN; divm--) {
|
|
+ post_divm = (u32)(input_freq / (divm + 1));
|
|
+ if (post_divm < POST_DIVM_MIN || post_divm > POST_DIVM_MAX)
|
|
+ continue;
|
|
+
|
|
+ for (divp = DIVP_MIN; divp <= DIVP_MAX; divp++) {
|
|
+ freq = output_freq * (divm + 1) * (divp + 1);
|
|
+ divn = (u32)((freq / input_freq) - 1);
|
|
+ if (divn < DIVN_MIN || divn > DIVN_MAX)
|
|
+ continue;
|
|
+
|
|
+ frac = (u32)(((freq * FRAC_MAX) / input_freq) -
|
|
+ ((divn + 1) * FRAC_MAX));
|
|
+ /* 2 loops to refine the fractional part */
|
|
+ for (i = 2; i != 0; i--) {
|
|
+ if (frac > FRAC_MAX)
|
|
+ break;
|
|
+
|
|
+ vco = (post_divm * (divn + 1)) +
|
|
+ ((post_divm * (u64)frac) /
|
|
+ FRAC_MAX);
|
|
+ if (vco < (PLL1600_VCO_MIN / 2) ||
|
|
+ vco > (PLL1600_VCO_MAX / 2)) {
|
|
+ frac++;
|
|
+ continue;
|
|
+ }
|
|
+ freq = vco / (divp + 1);
|
|
+ if (output_freq < freq)
|
|
+ diff = (u32)(freq - output_freq);
|
|
+ else
|
|
+ diff = (u32)(output_freq - freq);
|
|
+ if (diff < best_diff) {
|
|
+ pllcfg[PLLCFG_M] = divm;
|
|
+ pllcfg[PLLCFG_N] = divn;
|
|
+ pllcfg[PLLCFG_P] = divp;
|
|
+ *fracv = frac;
|
|
+
|
|
+ if (diff == 0)
|
|
+ return 0;
|
|
+
|
|
+ best_diff = diff;
|
|
+ }
|
|
+ frac++;
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+
|
|
+ if (best_diff == U32_MAX)
|
|
+ return -1;
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+
|
|
static void stm32mp1_ls_osc_set(int enable, fdt_addr_t rcc, u32 offset,
|
|
u32 mask_on)
|
|
{
|
|
@@ -1217,7 +1442,7 @@ static int stm32mp1_osc_wait(int enable, fdt_addr_t rcc, u32 offset,
|
|
}
|
|
|
|
static void stm32mp1_lse_enable(fdt_addr_t rcc, int bypass, int digbyp,
|
|
- int lsedrv)
|
|
+ u32 lsedrv)
|
|
{
|
|
u32 value;
|
|
|
|
@@ -1316,7 +1541,7 @@ static int stm32mp1_hsidiv(fdt_addr_t rcc, ulong hsifreq)
|
|
break;
|
|
|
|
if (hsidiv == 4) {
|
|
- pr_err("clk-hsi frequency invalid");
|
|
+ pr_err("hsi frequency invalid");
|
|
return -1;
|
|
}
|
|
|
|
@@ -1649,7 +1874,10 @@ static int stm32mp1_clktree(struct udevice *dev)
|
|
unsigned int clksrc[CLKSRC_NB];
|
|
unsigned int clkdiv[CLKDIV_NB];
|
|
unsigned int pllcfg[_PLL_NB][PLLCFG_NB];
|
|
- ofnode plloff[_PLL_NB];
|
|
+ unsigned int pllfracv[_PLL_NB];
|
|
+ unsigned int pllcsg[_PLL_NB][PLLCSG_NB];
|
|
+ bool pllcfg_valid[_PLL_NB];
|
|
+ bool pllcsg_set[_PLL_NB];
|
|
int ret;
|
|
int i, len;
|
|
int lse_css = 0;
|
|
@@ -1671,16 +1899,43 @@ static int stm32mp1_clktree(struct udevice *dev)
|
|
/* check mandatory field in each pll */
|
|
for (i = 0; i < _PLL_NB; i++) {
|
|
char name[12];
|
|
+ ofnode node;
|
|
|
|
sprintf(name, "st,pll@%d", i);
|
|
- plloff[i] = dev_read_subnode(dev, name);
|
|
- if (!ofnode_valid(plloff[i]))
|
|
- continue;
|
|
- ret = ofnode_read_u32_array(plloff[i], "cfg",
|
|
- pllcfg[i], PLLCFG_NB);
|
|
- if (ret < 0) {
|
|
- debug("field cfg invalid: error %d\n", ret);
|
|
- return -FDT_ERR_NOTFOUND;
|
|
+ node = dev_read_subnode(dev, name);
|
|
+ pllcfg_valid[i] = ofnode_valid(node);
|
|
+ pllcsg_set[i] = false;
|
|
+ if (pllcfg_valid[i]) {
|
|
+ debug("DT for PLL %d @ %s\n", i, name);
|
|
+ ret = ofnode_read_u32_array(node, "cfg",
|
|
+ pllcfg[i], PLLCFG_NB);
|
|
+ if (ret < 0) {
|
|
+ debug("field cfg invalid: error %d\n", ret);
|
|
+ return -FDT_ERR_NOTFOUND;
|
|
+ }
|
|
+ pllfracv[i] = ofnode_read_u32_default(node, "frac", 0);
|
|
+
|
|
+ ret = ofnode_read_u32_array(node, "csg", pllcsg[i],
|
|
+ PLLCSG_NB);
|
|
+ if (!ret) {
|
|
+ pllcsg_set[i] = true;
|
|
+ } else if (ret != -FDT_ERR_NOTFOUND) {
|
|
+ debug("invalid csg node for pll@%d res=%d\n",
|
|
+ i, ret);
|
|
+ return ret;
|
|
+ }
|
|
+ } else if (i == _PLL1) {
|
|
+ /* use OPP for PLL1 for A7 CPU */
|
|
+ debug("DT for PLL %d with OPP\n", i);
|
|
+ ret = stm32mp1_pll1_opp(priv,
|
|
+ clksrc[CLKSRC_PLL12],
|
|
+ pllcfg[i],
|
|
+ &pllfracv[i]);
|
|
+ if (ret) {
|
|
+ debug("PLL %d with OPP error = %d\n", i, ret);
|
|
+ return ret;
|
|
+ }
|
|
+ pllcfg_valid[i] = true;
|
|
}
|
|
}
|
|
|
|
@@ -1693,12 +1948,13 @@ static int stm32mp1_clktree(struct udevice *dev)
|
|
* switch ON oscillator found in device-tree,
|
|
* HSI already ON after bootrom
|
|
*/
|
|
- if (priv->osc[_LSI])
|
|
+ if (clk_valid(&priv->osc_clk[_LSI]))
|
|
stm32mp1_lsi_set(rcc, 1);
|
|
|
|
- if (priv->osc[_LSE]) {
|
|
- int bypass, digbyp, lsedrv;
|
|
- struct udevice *dev = priv->osc_dev[_LSE];
|
|
+ if (clk_valid(&priv->osc_clk[_LSE])) {
|
|
+ int bypass, digbyp;
|
|
+ u32 lsedrv;
|
|
+ struct udevice *dev = priv->osc_clk[_LSE].dev;
|
|
|
|
bypass = dev_read_bool(dev, "st,bypass");
|
|
digbyp = dev_read_bool(dev, "st,digbypass");
|
|
@@ -1709,9 +1965,9 @@ static int stm32mp1_clktree(struct udevice *dev)
|
|
stm32mp1_lse_enable(rcc, bypass, digbyp, lsedrv);
|
|
}
|
|
|
|
- if (priv->osc[_HSE]) {
|
|
+ if (clk_valid(&priv->osc_clk[_HSE])) {
|
|
int bypass, digbyp, css;
|
|
- struct udevice *dev = priv->osc_dev[_HSE];
|
|
+ struct udevice *dev = priv->osc_clk[_HSE].dev;
|
|
|
|
bypass = dev_read_bool(dev, "st,bypass");
|
|
digbyp = dev_read_bool(dev, "st,digbypass");
|
|
@@ -1736,8 +1992,8 @@ static int stm32mp1_clktree(struct udevice *dev)
|
|
|
|
/* configure HSIDIV */
|
|
debug("configure HSIDIV\n");
|
|
- if (priv->osc[_HSI]) {
|
|
- stm32mp1_hsidiv(rcc, priv->osc[_HSI]);
|
|
+ if (clk_valid(&priv->osc_clk[_HSI])) {
|
|
+ stm32mp1_hsidiv(rcc, clk_get_rate(&priv->osc_clk[_HSI]));
|
|
stgen_config(priv);
|
|
}
|
|
|
|
@@ -1765,36 +2021,25 @@ static int stm32mp1_clktree(struct udevice *dev)
|
|
/* configure and start PLLs */
|
|
debug("configure PLLs\n");
|
|
for (i = 0; i < _PLL_NB; i++) {
|
|
- u32 fracv;
|
|
- u32 csg[PLLCSG_NB];
|
|
-
|
|
- debug("configure PLL %d @ %d\n", i,
|
|
- ofnode_to_offset(plloff[i]));
|
|
- if (!ofnode_valid(plloff[i]))
|
|
+ if (!pllcfg_valid[i])
|
|
continue;
|
|
-
|
|
- fracv = ofnode_read_u32_default(plloff[i], "frac", 0);
|
|
- pll_config(priv, i, pllcfg[i], fracv);
|
|
- ret = ofnode_read_u32_array(plloff[i], "csg", csg, PLLCSG_NB);
|
|
- if (!ret) {
|
|
- pll_csg(priv, i, csg);
|
|
- } else if (ret != -FDT_ERR_NOTFOUND) {
|
|
- debug("invalid csg node for pll@%d res=%d\n", i, ret);
|
|
- return ret;
|
|
- }
|
|
+ debug("configure PLL %d\n", i);
|
|
+ pll_config(priv, i, pllcfg[i], pllfracv[i]);
|
|
+ if (pllcsg_set[i])
|
|
+ pll_csg(priv, i, pllcsg[i]);
|
|
pll_start(priv, i);
|
|
}
|
|
|
|
/* wait and start PLLs ouptut when ready */
|
|
for (i = 0; i < _PLL_NB; i++) {
|
|
- if (!ofnode_valid(plloff[i]))
|
|
+ if (!pllcfg_valid[i])
|
|
continue;
|
|
debug("output PLL %d\n", i);
|
|
pll_output(priv, i, pllcfg[i][PLLCFG_O]);
|
|
}
|
|
|
|
/* wait LSE ready before to use it */
|
|
- if (priv->osc[_LSE])
|
|
+ if (clk_valid(&priv->osc_clk[_LSE]))
|
|
stm32mp1_lse_wait(rcc);
|
|
|
|
/* configure with expected clock source */
|
|
@@ -1833,7 +2078,7 @@ static int stm32mp1_clktree(struct udevice *dev)
|
|
|
|
debug("oscillator off\n");
|
|
/* switch OFF HSI if not found in device-tree */
|
|
- if (!priv->osc[_HSI])
|
|
+ if (!clk_valid(&priv->osc_clk[_HSI]))
|
|
stm32mp1_hsi_set(rcc, 0);
|
|
|
|
/* Software Self-Refresh mode (SSR) during DDR initilialization */
|
|
@@ -1931,40 +2176,25 @@ static ulong stm32mp1_clk_set_rate(struct clk *clk, unsigned long clk_rate)
|
|
return -EINVAL;
|
|
}
|
|
|
|
-static void stm32mp1_osc_clk_init(const char *name,
|
|
- struct stm32mp1_clk_priv *priv,
|
|
- int index)
|
|
-{
|
|
- struct clk clk;
|
|
- struct udevice *dev = NULL;
|
|
-
|
|
- priv->osc[index] = 0;
|
|
- clk.id = 0;
|
|
- if (!uclass_get_device_by_name(UCLASS_CLK, name, &dev)) {
|
|
- if (clk_request(dev, &clk))
|
|
- pr_err("%s request", name);
|
|
- else
|
|
- priv->osc[index] = clk_get_rate(&clk);
|
|
- }
|
|
- priv->osc_dev[index] = dev;
|
|
-}
|
|
-
|
|
static void stm32mp1_osc_init(struct udevice *dev)
|
|
{
|
|
struct stm32mp1_clk_priv *priv = dev_get_priv(dev);
|
|
int i;
|
|
const char *name[NB_OSC] = {
|
|
- [_LSI] = "clk-lsi",
|
|
- [_LSE] = "clk-lse",
|
|
- [_HSI] = "clk-hsi",
|
|
- [_HSE] = "clk-hse",
|
|
- [_CSI] = "clk-csi",
|
|
+ [_LSI] = "lsi",
|
|
+ [_LSE] = "lse",
|
|
+ [_HSI] = "hsi",
|
|
+ [_HSE] = "hse",
|
|
+ [_CSI] = "csi",
|
|
[_I2S_CKIN] = "i2s_ckin",
|
|
};
|
|
|
|
for (i = 0; i < NB_OSC; i++) {
|
|
- stm32mp1_osc_clk_init(name[i], priv, i);
|
|
- debug("%d: %s => %x\n", i, name[i], (u32)priv->osc[i]);
|
|
+ if (clk_get_by_name(dev, name[i], &priv->osc_clk[i]))
|
|
+ dev_dbg(dev, "No source clock \"%s\"", name[i]);
|
|
+ else
|
|
+ dev_dbg(dev, "%s clock rate: %luHz\n",
|
|
+ name[i], clk_get_rate(&priv->osc_clk[i]));
|
|
}
|
|
}
|
|
|
|
@@ -2037,6 +2267,8 @@ static int stm32mp1_clk_probe(struct udevice *dev)
|
|
/* clock tree init is done only one time, before relocation */
|
|
if (!(gd->flags & GD_FLG_RELOC))
|
|
result = stm32mp1_clktree(dev);
|
|
+ if (result)
|
|
+ printf("clock tree initialization failed (%d)\n", result);
|
|
#endif
|
|
|
|
#ifndef CONFIG_SPL_BUILD
|
|
diff --git a/drivers/core/of_access.c b/drivers/core/of_access.c
|
|
index 945b814..86fe42a 100644
|
|
--- a/drivers/core/of_access.c
|
|
+++ b/drivers/core/of_access.c
|
|
@@ -170,6 +170,38 @@ const void *of_get_property(const struct device_node *np, const char *name,
|
|
return pp ? pp->value : NULL;
|
|
}
|
|
|
|
+const struct property *of_get_first_property(const struct device_node *np)
|
|
+{
|
|
+ if (!np)
|
|
+ return NULL;
|
|
+
|
|
+ return np->properties;
|
|
+}
|
|
+
|
|
+const struct property *of_get_next_property(const struct device_node *np,
|
|
+ const struct property *property)
|
|
+{
|
|
+ if (!np)
|
|
+ return NULL;
|
|
+
|
|
+ return property->next;
|
|
+}
|
|
+
|
|
+const void *of_get_property_by_prop(const struct device_node *np,
|
|
+ const struct property *property,
|
|
+ const char **name,
|
|
+ int *lenp)
|
|
+{
|
|
+ if (!np || !property)
|
|
+ return NULL;
|
|
+ if (name)
|
|
+ *name = property->name;
|
|
+ if (lenp)
|
|
+ *lenp = property->length;
|
|
+
|
|
+ return property->value;
|
|
+}
|
|
+
|
|
static const char *of_prop_next_string(struct property *prop, const char *cur)
|
|
{
|
|
const void *curv = cur;
|
|
diff --git a/drivers/core/ofnode.c b/drivers/core/ofnode.c
|
|
index 8f0eab2..cb27562 100644
|
|
--- a/drivers/core/ofnode.c
|
|
+++ b/drivers/core/ofnode.c
|
|
@@ -536,6 +536,54 @@ const void *ofnode_get_property(ofnode node, const char *propname, int *lenp)
|
|
propname, lenp);
|
|
}
|
|
|
|
+int ofnode_get_first_property(ofnode node, struct ofprop *prop)
|
|
+{
|
|
+ prop->node = node;
|
|
+
|
|
+ if (ofnode_is_np(node)) {
|
|
+ prop->prop = of_get_first_property(ofnode_to_np(prop->node));
|
|
+ if (!prop->prop)
|
|
+ return -FDT_ERR_NOTFOUND;
|
|
+ } else {
|
|
+ prop->offset =
|
|
+ fdt_first_property_offset(gd->fdt_blob,
|
|
+ ofnode_to_offset(prop->node));
|
|
+ if (prop->offset < 0)
|
|
+ return prop->offset;
|
|
+ }
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+int ofnode_get_next_property(struct ofprop *prop)
|
|
+{
|
|
+ if (ofnode_is_np(prop->node)) {
|
|
+ prop->prop = of_get_next_property(ofnode_to_np(prop->node),
|
|
+ prop->prop);
|
|
+ if (!prop->prop)
|
|
+ return -FDT_ERR_NOTFOUND;
|
|
+ } else {
|
|
+ prop->offset = fdt_next_property_offset(gd->fdt_blob,
|
|
+ prop->offset);
|
|
+ if (prop->offset < 0)
|
|
+ return prop->offset;
|
|
+ }
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+const void *ofnode_get_property_by_prop(const struct ofprop *prop,
|
|
+ const char **propname, int *lenp)
|
|
+{
|
|
+ if (ofnode_is_np(prop->node))
|
|
+ return of_get_property_by_prop(ofnode_to_np(prop->node),
|
|
+ prop->prop, propname, lenp);
|
|
+ else
|
|
+ return fdt_getprop_by_offset(gd->fdt_blob,
|
|
+ prop->offset,
|
|
+ propname, lenp);
|
|
+}
|
|
+
|
|
bool ofnode_is_available(ofnode node)
|
|
{
|
|
if (ofnode_is_np(node))
|
|
diff --git a/drivers/core/read.c b/drivers/core/read.c
|
|
index 9602e52..a9f5d14 100644
|
|
--- a/drivers/core/read.c
|
|
+++ b/drivers/core/read.c
|
|
@@ -238,6 +238,22 @@ const void *dev_read_prop(struct udevice *dev, const char *propname, int *lenp)
|
|
return ofnode_get_property(dev_ofnode(dev), propname, lenp);
|
|
}
|
|
|
|
+int dev_read_first_prop(struct udevice *dev, struct ofprop *prop)
|
|
+{
|
|
+ return ofnode_get_first_property(dev_ofnode(dev), prop);
|
|
+}
|
|
+
|
|
+int dev_read_next_prop(struct ofprop *prop)
|
|
+{
|
|
+ return ofnode_get_next_property(prop);
|
|
+}
|
|
+
|
|
+const void *dev_read_prop_by_prop(struct ofprop *prop,
|
|
+ const char **propname, int *lenp)
|
|
+{
|
|
+ return ofnode_get_property_by_prop(prop, propname, lenp);
|
|
+}
|
|
+
|
|
int dev_read_alias_seq(struct udevice *dev, int *devnump)
|
|
{
|
|
ofnode node = dev_ofnode(dev);
|
|
diff --git a/drivers/core/root.c b/drivers/core/root.c
|
|
index e856438..14df16c 100644
|
|
--- a/drivers/core/root.c
|
|
+++ b/drivers/core/root.c
|
|
@@ -203,15 +203,6 @@ static int dm_scan_fdt_live(struct udevice *parent,
|
|
int ret = 0, err;
|
|
|
|
for (np = node_parent->child; np; np = np->sibling) {
|
|
- /* "chosen" node isn't a device itself but may contain some: */
|
|
- if (!strcmp(np->name, "chosen")) {
|
|
- pr_debug("parsing subnodes of \"chosen\"\n");
|
|
-
|
|
- err = dm_scan_fdt_live(parent, np, pre_reloc_only);
|
|
- if (err && !ret)
|
|
- ret = err;
|
|
- continue;
|
|
- }
|
|
|
|
if (!of_device_is_available(np)) {
|
|
pr_debug(" - ignoring disabled device\n");
|
|
@@ -256,21 +247,6 @@ static int dm_scan_fdt_node(struct udevice *parent, const void *blob,
|
|
offset = fdt_next_subnode(blob, offset)) {
|
|
const char *node_name = fdt_get_name(blob, offset, NULL);
|
|
|
|
- /*
|
|
- * The "chosen" and "firmware" nodes aren't devices
|
|
- * themselves but may contain some:
|
|
- */
|
|
- if (!strcmp(node_name, "chosen") ||
|
|
- !strcmp(node_name, "firmware")) {
|
|
- pr_debug("parsing subnodes of \"%s\"\n", node_name);
|
|
-
|
|
- err = dm_scan_fdt_node(parent, blob, offset,
|
|
- pre_reloc_only);
|
|
- if (err && !ret)
|
|
- ret = err;
|
|
- continue;
|
|
- }
|
|
-
|
|
if (!fdtdec_get_is_enabled(blob, offset)) {
|
|
pr_debug(" - ignoring disabled device\n");
|
|
continue;
|
|
@@ -315,7 +291,8 @@ int dm_scan_fdt(const void *blob, bool pre_reloc_only)
|
|
return dm_scan_fdt_node(gd->dm_root, blob, 0, pre_reloc_only);
|
|
}
|
|
|
|
-static int dm_scan_fdt_ofnode_path(const char *path, bool pre_reloc_only)
|
|
+static int dm_scan_fdt_ofnode_path(const void *blob, const char *path,
|
|
+ bool pre_reloc_only)
|
|
{
|
|
ofnode node;
|
|
|
|
@@ -327,13 +304,18 @@ static int dm_scan_fdt_ofnode_path(const char *path, bool pre_reloc_only)
|
|
if (of_live_active())
|
|
return dm_scan_fdt_live(gd->dm_root, node.np, pre_reloc_only);
|
|
#endif
|
|
- return dm_scan_fdt_node(gd->dm_root, gd->fdt_blob, node.of_offset,
|
|
+ return dm_scan_fdt_node(gd->dm_root, blob, node.of_offset,
|
|
pre_reloc_only);
|
|
}
|
|
|
|
int dm_extended_scan_fdt(const void *blob, bool pre_reloc_only)
|
|
{
|
|
- int ret;
|
|
+ int ret, i;
|
|
+ const char * const nodes[] = {
|
|
+ "/chosen",
|
|
+ "/clocks",
|
|
+ "/firmware"
|
|
+ };
|
|
|
|
ret = dm_scan_fdt(blob, pre_reloc_only);
|
|
if (ret) {
|
|
@@ -341,16 +323,16 @@ int dm_extended_scan_fdt(const void *blob, bool pre_reloc_only)
|
|
return ret;
|
|
}
|
|
|
|
- ret = dm_scan_fdt_ofnode_path("/clocks", pre_reloc_only);
|
|
- if (ret) {
|
|
- debug("scan for /clocks failed: %d\n", ret);
|
|
- return ret;
|
|
+ /* Some nodes aren't devices themselves but may contain some */
|
|
+ for (i = 0; i < ARRAY_SIZE(nodes); i++) {
|
|
+ ret = dm_scan_fdt_ofnode_path(blob, nodes[i], pre_reloc_only);
|
|
+ if (ret) {
|
|
+ debug("dm_scan_fdt() scan for %s failed: %d\n",
|
|
+ nodes[i], ret);
|
|
+ return ret;
|
|
+ }
|
|
}
|
|
|
|
- ret = dm_scan_fdt_ofnode_path("/firmware", pre_reloc_only);
|
|
- if (ret)
|
|
- debug("scan for /firmware failed: %d\n", ret);
|
|
-
|
|
return ret;
|
|
}
|
|
#endif
|
|
diff --git a/drivers/dfu/Kconfig b/drivers/dfu/Kconfig
|
|
index 75fe0a1..1783656 100644
|
|
--- a/drivers/dfu/Kconfig
|
|
+++ b/drivers/dfu/Kconfig
|
|
@@ -68,5 +68,10 @@ config DFU_VIRT
|
|
used at board level to manage specific behavior
|
|
(OTP update for example).
|
|
|
|
+config SET_DFU_ALT_INFO
|
|
+ bool "Dynamic set of DFU alternate information"
|
|
+ help
|
|
+ This option allows to call the function set_dfu_alt_info to
|
|
+ dynamically build dfu_alt_info in board.
|
|
endif
|
|
endmenu
|
|
diff --git a/drivers/fastboot/Kconfig b/drivers/fastboot/Kconfig
|
|
index 9f85054..a17e488 100644
|
|
--- a/drivers/fastboot/Kconfig
|
|
+++ b/drivers/fastboot/Kconfig
|
|
@@ -104,6 +104,60 @@ config FASTBOOT_FLASH_NAND_TRIMFFS
|
|
When flashing NAND enable the DROP_FFS flag to drop trailing all-0xff
|
|
pages.
|
|
|
|
+config FASTBOOT_MMC_BOOT_SUPPORT
|
|
+ bool "Enable EMMC_BOOT flash/erase"
|
|
+ depends on FASTBOOT_FLASH_MMC
|
|
+ help
|
|
+ The fastboot "flash" and "erase" commands normally does operations
|
|
+ on eMMC userdata. Define this to enable the special commands to
|
|
+ flash/erase eMMC boot partition.
|
|
+ The default target name for updating eMMC boot partition 1/2 is
|
|
+ CONFIG_FASTBOOT_MMC_BOOT1_NAME/CONFIG_FASTBOOT_MMC_BOOT2_NAME.
|
|
+
|
|
+config FASTBOOT_MMC_BOOT1_NAME
|
|
+ string "Target name for updating EMMC_BOOT1"
|
|
+ depends on FASTBOOT_MMC_BOOT_SUPPORT
|
|
+ default "mmc0boot0"
|
|
+ help
|
|
+ The fastboot "flash" and "erase" commands support operations on
|
|
+ EMMC_BOOT1. This occurs when the specified "EMMC_BOOT1 name" on
|
|
+ the "fastboot flash" and "fastboot erase" commands match the value
|
|
+ defined here.
|
|
+ The default target name for updating EMMC_BOOT1 is "mmc0boot0".
|
|
+
|
|
+config FASTBOOT_MMC_BOOT2_NAME
|
|
+ string "Target name for updating EMMC_BOOT2"
|
|
+ depends on FASTBOOT_MMC_BOOT_SUPPORT
|
|
+ default "mmc0boot1"
|
|
+ help
|
|
+ The fastboot "flash" and "erase" commands support operations on
|
|
+ EMMC_BOOT2. This occurs when the specified "EMMC_BOOT2 name" on
|
|
+ the "fastboot flash" and "fastboot erase" commands match the value
|
|
+ defined here.
|
|
+ The default target name for updating EMMC_BOOT2 is "mmc0boot1".
|
|
+
|
|
+config FASTBOOT_MMC_USER_SUPPORT
|
|
+ bool "Enable eMMC userdata partition flash/erase"
|
|
+ depends on FASTBOOT_FLASH_MMC
|
|
+ help
|
|
+ Define this to enable the support "flash" and "erase" command on
|
|
+ eMMC userdata. The "flash" command only update the MBR and GPT
|
|
+ header when CONFIG_EFI_PARTITION is supported.
|
|
+ The "erase" command erase all the userdata.
|
|
+ This occurs when the specified "partition name" on the
|
|
+ fastboot command line matches the value CONFIG_FASTBOOT_MMC_USER_NAME.
|
|
+
|
|
+config FASTBOOT_MMC_USER_NAME
|
|
+ string "Target name for updating EMMC_USER"
|
|
+ depends on FASTBOOT_MMC_USER_SUPPORT
|
|
+ default "mmc0"
|
|
+ help
|
|
+ The fastboot "flash" and "erase" command supports EMMC_USER.
|
|
+ This occurs when the specified "EMMC_USER name" on the
|
|
+ "fastboot flash" and the "fastboot erase" commands match the value
|
|
+ defined here.
|
|
+ The default target name for erasing EMMC_USER is "mmc0".
|
|
+
|
|
config FASTBOOT_GPT_NAME
|
|
string "Target name for updating GPT"
|
|
depends on FASTBOOT_FLASH_MMC && EFI_PARTITION
|
|
@@ -135,6 +189,20 @@ config FASTBOOT_CMD_OEM_FORMAT
|
|
relies on the env variable partitions to contain the list of
|
|
partitions as required by the gpt command.
|
|
|
|
+config FASTBOOT_CMD_OEM_PARTCONF
|
|
+ bool "Enable the 'oem partconf' command"
|
|
+ depends on FASTBOOT_FLASH_MMC && SUPPORT_EMMC_BOOT
|
|
+ help
|
|
+ Add support for the "oem partconf" command from a client. This set
|
|
+ the mmc boot-partition for the selecting eMMC device.
|
|
+
|
|
+config FASTBOOT_CMD_OEM_BOOTBUS
|
|
+ bool "Enable the 'oem bootbus' command"
|
|
+ depends on FASTBOOT_FLASH_MMC && SUPPORT_EMMC_BOOT
|
|
+ help
|
|
+ Add support for the "oem bootbus" command from a client. This set
|
|
+ the mmc boot configuration for the selecting eMMC device.
|
|
+
|
|
endif # FASTBOOT
|
|
|
|
endmenu
|
|
diff --git a/drivers/fastboot/fb_command.c b/drivers/fastboot/fb_command.c
|
|
index 3c4acfe..842aa5e 100644
|
|
--- a/drivers/fastboot/fb_command.c
|
|
+++ b/drivers/fastboot/fb_command.c
|
|
@@ -39,6 +39,12 @@ static void reboot_bootloader(char *, char *);
|
|
#if CONFIG_IS_ENABLED(FASTBOOT_CMD_OEM_FORMAT)
|
|
static void oem_format(char *, char *);
|
|
#endif
|
|
+#if CONFIG_IS_ENABLED(FASTBOOT_CMD_OEM_PARTCONF)
|
|
+static void oem_partconf(char *, char *);
|
|
+#endif
|
|
+#if CONFIG_IS_ENABLED(FASTBOOT_CMD_OEM_BOOTBUS)
|
|
+static void oem_bootbus(char *, char *);
|
|
+#endif
|
|
|
|
static const struct {
|
|
const char *command;
|
|
@@ -88,6 +94,18 @@ static const struct {
|
|
.dispatch = oem_format,
|
|
},
|
|
#endif
|
|
+#if CONFIG_IS_ENABLED(FASTBOOT_CMD_OEM_PARTCONF)
|
|
+ [FASTBOOT_COMMAND_OEM_PARTCONF] = {
|
|
+ .command = "oem partconf",
|
|
+ .dispatch = oem_partconf,
|
|
+ },
|
|
+#endif
|
|
+#if CONFIG_IS_ENABLED(FASTBOOT_CMD_OEM_BOOTBUS)
|
|
+ [FASTBOOT_COMMAND_OEM_BOOTBUS] = {
|
|
+ .command = "oem bootbus",
|
|
+ .dispatch = oem_bootbus,
|
|
+ },
|
|
+#endif
|
|
};
|
|
|
|
/**
|
|
@@ -335,3 +353,57 @@ static void oem_format(char *cmd_parameter, char *response)
|
|
}
|
|
}
|
|
#endif
|
|
+
|
|
+#if CONFIG_IS_ENABLED(FASTBOOT_CMD_OEM_PARTCONF)
|
|
+/**
|
|
+ * oem_partconf() - Execute the OEM partconf command
|
|
+ *
|
|
+ * @cmd_parameter: Pointer to command parameter
|
|
+ * @response: Pointer to fastboot response buffer
|
|
+ */
|
|
+static void oem_partconf(char *cmd_parameter, char *response)
|
|
+{
|
|
+ char cmdbuf[32];
|
|
+
|
|
+ if (!cmd_parameter) {
|
|
+ fastboot_fail("Expected command parameter", response);
|
|
+ return;
|
|
+ }
|
|
+
|
|
+ /* execute 'mmc partconfg' command with cmd_parameter arguments*/
|
|
+ snprintf(cmdbuf, sizeof(cmdbuf), "mmc partconf %x %s 0",
|
|
+ CONFIG_FASTBOOT_FLASH_MMC_DEV, cmd_parameter);
|
|
+ printf("Execute: %s\n", cmdbuf);
|
|
+ if (run_command(cmdbuf, 0))
|
|
+ fastboot_fail("Cannot set oem partconf", response);
|
|
+ else
|
|
+ fastboot_okay(NULL, response);
|
|
+}
|
|
+#endif
|
|
+
|
|
+#if CONFIG_IS_ENABLED(FASTBOOT_CMD_OEM_BOOTBUS)
|
|
+/**
|
|
+ * oem_bootbus() - Execute the OEM bootbus command
|
|
+ *
|
|
+ * @cmd_parameter: Pointer to command parameter
|
|
+ * @response: Pointer to fastboot response buffer
|
|
+ */
|
|
+static void oem_bootbus(char *cmd_parameter, char *response)
|
|
+{
|
|
+ char cmdbuf[32];
|
|
+
|
|
+ if (!cmd_parameter) {
|
|
+ fastboot_fail("Expected command parameter", response);
|
|
+ return;
|
|
+ }
|
|
+
|
|
+ /* execute 'mmc bootbus' command with cmd_parameter arguments*/
|
|
+ snprintf(cmdbuf, sizeof(cmdbuf), "mmc bootbus %x %s",
|
|
+ CONFIG_FASTBOOT_FLASH_MMC_DEV, cmd_parameter);
|
|
+ printf("Execute: %s\n", cmdbuf);
|
|
+ if (run_command(cmdbuf, 0))
|
|
+ fastboot_fail("Cannot set oem bootbus", response);
|
|
+ else
|
|
+ fastboot_okay(NULL, response);
|
|
+}
|
|
+#endif
|
|
diff --git a/drivers/fastboot/fb_mmc.c b/drivers/fastboot/fb_mmc.c
|
|
index b0b19c5..09ba2f2 100644
|
|
--- a/drivers/fastboot/fb_mmc.c
|
|
+++ b/drivers/fastboot/fb_mmc.c
|
|
@@ -129,6 +129,82 @@ static void write_raw_image(struct blk_desc *dev_desc, disk_partition_t *info,
|
|
fastboot_okay(NULL, response);
|
|
}
|
|
|
|
+#if defined(CONFIG_FASTBOOT_MMC_BOOT_SUPPORT) || \
|
|
+ defined(CONFIG_FASTBOOT_MMC_USER_SUPPORT)
|
|
+static int fb_mmc_erase_mmc_hwpart(struct blk_desc *dev_desc)
|
|
+{
|
|
+ lbaint_t blks;
|
|
+
|
|
+ debug("Start Erasing mmc hwpart[%u]...\n", dev_desc->hwpart);
|
|
+
|
|
+ blks = fb_mmc_blk_write(dev_desc, 0, dev_desc->lba, NULL);
|
|
+
|
|
+ if (blks != dev_desc->lba) {
|
|
+ pr_err("Failed to erase mmc hwpart[%u]\n", dev_desc->hwpart);
|
|
+ return 1;
|
|
+ }
|
|
+
|
|
+ printf("........ erased %lu bytes from mmc hwpart[%u]\n",
|
|
+ dev_desc->lba * dev_desc->blksz, dev_desc->hwpart);
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+#endif
|
|
+
|
|
+#ifdef CONFIG_FASTBOOT_MMC_BOOT_SUPPORT
|
|
+static void fb_mmc_boot_ops(struct blk_desc *dev_desc, void *buffer,
|
|
+ int hwpart, u32 buff_sz, char *response)
|
|
+{
|
|
+ lbaint_t blkcnt;
|
|
+ lbaint_t blks;
|
|
+ unsigned long blksz;
|
|
+
|
|
+ // To operate on EMMC_BOOT1/2 (mmc0boot0/1) we first change the hwpart
|
|
+ if (blk_dselect_hwpart(dev_desc, hwpart)) {
|
|
+ pr_err("Failed to select hwpart\n");
|
|
+ fastboot_fail("Failed to select hwpart", response);
|
|
+ return;
|
|
+ }
|
|
+
|
|
+ if (buffer) { /* flash */
|
|
+
|
|
+ /* determine number of blocks to write */
|
|
+ blksz = dev_desc->blksz;
|
|
+ blkcnt = ((buff_sz + (blksz - 1)) & ~(blksz - 1));
|
|
+ blkcnt = lldiv(blkcnt, blksz);
|
|
+
|
|
+ if (blkcnt > dev_desc->lba) {
|
|
+ pr_err("Image size too large\n");
|
|
+ fastboot_fail("Image size too large", response);
|
|
+ return;
|
|
+ }
|
|
+
|
|
+ debug("Start Flashing Image to EMMC_BOOT%d...\n", hwpart);
|
|
+
|
|
+ blks = fb_mmc_blk_write(dev_desc, 0, blkcnt, buffer);
|
|
+
|
|
+ if (blks != blkcnt) {
|
|
+ pr_err("Failed to write EMMC_BOOT%d\n", hwpart);
|
|
+ fastboot_fail("Failed to write EMMC_BOOT part",
|
|
+ response);
|
|
+ return;
|
|
+ }
|
|
+
|
|
+ printf("........ wrote %lu bytes to EMMC_BOOT%d\n",
|
|
+ blkcnt * blksz, hwpart);
|
|
+ } else { /* erase */
|
|
+ if (fb_mmc_erase_mmc_hwpart(dev_desc)) {
|
|
+ pr_err("Failed to erase EMMC_BOOT%d\n", hwpart);
|
|
+ fastboot_fail("Failed to erase EMMC_BOOT part",
|
|
+ response);
|
|
+ return;
|
|
+ }
|
|
+ }
|
|
+
|
|
+ fastboot_okay(NULL, response);
|
|
+}
|
|
+#endif
|
|
+
|
|
#ifdef CONFIG_ANDROID_BOOT_IMAGE
|
|
/**
|
|
* Read Android boot image header from boot partition.
|
|
@@ -345,8 +421,26 @@ void fastboot_mmc_flash_write(const char *cmd, void *download_buffer,
|
|
return;
|
|
}
|
|
|
|
+#ifdef CONFIG_FASTBOOT_MMC_BOOT_SUPPORT
|
|
+ if (strcmp(cmd, CONFIG_FASTBOOT_MMC_BOOT1_NAME) == 0) {
|
|
+ fb_mmc_boot_ops(dev_desc, download_buffer, 1,
|
|
+ download_bytes, response);
|
|
+ return;
|
|
+ }
|
|
+ if (strcmp(cmd, CONFIG_FASTBOOT_MMC_BOOT2_NAME) == 0) {
|
|
+ fb_mmc_boot_ops(dev_desc, download_buffer, 2,
|
|
+ download_bytes, response);
|
|
+ return;
|
|
+ }
|
|
+#endif
|
|
+
|
|
#if CONFIG_IS_ENABLED(EFI_PARTITION)
|
|
+#ifndef CONFIG_FASTBOOT_MMC_USER_SUPPORT
|
|
if (strcmp(cmd, CONFIG_FASTBOOT_GPT_NAME) == 0) {
|
|
+#else
|
|
+ if (strcmp(cmd, CONFIG_FASTBOOT_GPT_NAME) == 0 ||
|
|
+ strcmp(cmd, CONFIG_FASTBOOT_MMC_USER_NAME) == 0) {
|
|
+#endif
|
|
printf("%s: updating MBR, Primary and Backup GPT(s)\n",
|
|
__func__);
|
|
if (is_valid_gpt_buf(dev_desc, download_buffer)) {
|
|
@@ -457,6 +551,30 @@ void fastboot_mmc_erase(const char *cmd, char *response)
|
|
return;
|
|
}
|
|
|
|
+#ifdef CONFIG_FASTBOOT_MMC_BOOT_SUPPORT
|
|
+ if (strcmp(cmd, CONFIG_FASTBOOT_MMC_BOOT1_NAME) == 0) {
|
|
+ /* erase EMMC boot1 */
|
|
+ fb_mmc_boot_ops(dev_desc, NULL, 1, 0, response);
|
|
+ return;
|
|
+ }
|
|
+ if (strcmp(cmd, CONFIG_FASTBOOT_MMC_BOOT2_NAME) == 0) {
|
|
+ /* erase EMMC boot2 */
|
|
+ fb_mmc_boot_ops(dev_desc, NULL, 2, 0, response);
|
|
+ return;
|
|
+ }
|
|
+#endif
|
|
+
|
|
+#ifdef CONFIG_FASTBOOT_MMC_USER_SUPPORT
|
|
+ if (strcmp(cmd, CONFIG_FASTBOOT_MMC_USER_NAME) == 0) {
|
|
+ /* erase EMMC userdata */
|
|
+ if (fb_mmc_erase_mmc_hwpart(dev_desc))
|
|
+ fastboot_fail("Failed to erase EMMC_USER", response);
|
|
+ else
|
|
+ fastboot_okay(NULL, response);
|
|
+ return;
|
|
+ }
|
|
+#endif
|
|
+
|
|
ret = part_get_info_by_name_or_alias(dev_desc, cmd, &info);
|
|
if (ret < 0) {
|
|
pr_err("cannot find partition: '%s'\n", cmd);
|
|
diff --git a/drivers/gpio/gpio-uclass.c b/drivers/gpio/gpio-uclass.c
|
|
index 90fbed4..5da28e6 100644
|
|
--- a/drivers/gpio/gpio-uclass.c
|
|
+++ b/drivers/gpio/gpio-uclass.c
|
|
@@ -19,6 +19,22 @@
|
|
DECLARE_GLOBAL_DATA_PTR;
|
|
|
|
/**
|
|
+ * gpio_desc_init() - Initialize the GPIO descriptor
|
|
+ *
|
|
+ * @desc: GPIO descriptor to initialize
|
|
+ * @dev: GPIO device
|
|
+ * @offset: Offset of device GPIO
|
|
+ */
|
|
+static void gpio_desc_init(struct gpio_desc *desc,
|
|
+ struct udevice *dev,
|
|
+ uint offset)
|
|
+{
|
|
+ desc->dev = dev;
|
|
+ desc->offset = offset;
|
|
+ desc->flags = 0;
|
|
+}
|
|
+
|
|
+/**
|
|
* gpio_to_device() - Convert global GPIO number to device, number
|
|
*
|
|
* Convert the GPIO number to an entry in the list of GPIOs
|
|
@@ -41,9 +57,7 @@ static int gpio_to_device(unsigned int gpio, struct gpio_desc *desc)
|
|
uc_priv = dev_get_uclass_priv(dev);
|
|
if (gpio >= uc_priv->gpio_base &&
|
|
gpio < uc_priv->gpio_base + uc_priv->gpio_count) {
|
|
- desc->dev = dev;
|
|
- desc->offset = gpio - uc_priv->gpio_base;
|
|
- desc->flags = 0;
|
|
+ gpio_desc_init(desc, dev, gpio - uc_priv->gpio_base);
|
|
return 0;
|
|
}
|
|
}
|
|
@@ -85,8 +99,7 @@ int dm_gpio_lookup_name(const char *name, struct gpio_desc *desc)
|
|
if (!dev)
|
|
return ret ? ret : -EINVAL;
|
|
|
|
- desc->dev = dev;
|
|
- desc->offset = offset;
|
|
+ gpio_desc_init(desc, dev, offset);
|
|
|
|
return 0;
|
|
}
|
|
@@ -127,8 +140,27 @@ int gpio_xlate_offs_flags(struct udevice *dev, struct gpio_desc *desc,
|
|
if (args->args_count < 2)
|
|
return 0;
|
|
|
|
+ desc->flags = 0;
|
|
if (args->args[1] & GPIO_ACTIVE_LOW)
|
|
- desc->flags = GPIOD_ACTIVE_LOW;
|
|
+ desc->flags |= GPIOD_ACTIVE_LOW;
|
|
+
|
|
+ /*
|
|
+ * need to test 2 bits for gpio output binding:
|
|
+ * OPEN_DRAIN (0x6) = SINGLE_ENDED (0x2) | LINE_OPEN_DRAIN (0x4)
|
|
+ * OPEN_SOURCE (0x2) = SINGLE_ENDED (0x2) | LINE_OPEN_SOURCE (0x0)
|
|
+ */
|
|
+ if (args->args[1] & GPIO_SINGLE_ENDED) {
|
|
+ if (args->args[1] & GPIO_LINE_OPEN_DRAIN)
|
|
+ desc->flags |= GPIOD_OPEN_DRAIN;
|
|
+ else
|
|
+ desc->flags |= GPIOD_OPEN_SOURCE;
|
|
+ }
|
|
+
|
|
+ if (args->args[1] & GPIO_PULL_UP)
|
|
+ desc->flags |= GPIOD_PULL_UP;
|
|
+
|
|
+ if (args->args[1] & GPIO_PULL_DOWN)
|
|
+ desc->flags |= GPIOD_PULL_DOWN;
|
|
|
|
return 0;
|
|
}
|
|
@@ -463,18 +495,24 @@ int gpio_direction_output(unsigned gpio, int value)
|
|
desc.offset, value);
|
|
}
|
|
|
|
-int dm_gpio_get_value(const struct gpio_desc *desc)
|
|
+static int _gpio_get_value(const struct gpio_desc *desc)
|
|
{
|
|
int value;
|
|
+
|
|
+ value = gpio_get_ops(desc->dev)->get_value(desc->dev, desc->offset);
|
|
+
|
|
+ return desc->flags & GPIOD_ACTIVE_LOW ? !value : value;
|
|
+}
|
|
+
|
|
+int dm_gpio_get_value(const struct gpio_desc *desc)
|
|
+{
|
|
int ret;
|
|
|
|
ret = check_reserved(desc, "get_value");
|
|
if (ret)
|
|
return ret;
|
|
|
|
- value = gpio_get_ops(desc->dev)->get_value(desc->dev, desc->offset);
|
|
-
|
|
- return desc->flags & GPIOD_ACTIVE_LOW ? !value : value;
|
|
+ return _gpio_get_value(desc);
|
|
}
|
|
|
|
int dm_gpio_set_value(const struct gpio_desc *desc, int value)
|
|
@@ -491,71 +529,128 @@ int dm_gpio_set_value(const struct gpio_desc *desc, int value)
|
|
return 0;
|
|
}
|
|
|
|
-int dm_gpio_get_open_drain(struct gpio_desc *desc)
|
|
+/* check dir flags invalid configuration */
|
|
+static int check_dir_flags(ulong flags)
|
|
{
|
|
- struct dm_gpio_ops *ops = gpio_get_ops(desc->dev);
|
|
- int ret;
|
|
+ if ((flags & GPIOD_IS_OUT) && (flags & GPIOD_IS_IN)) {
|
|
+ log_debug("%s: flags 0x%lx has GPIOD_IS_OUT and GPIOD_IS_IN\n",
|
|
+ __func__, flags);
|
|
+ return -EINVAL;
|
|
+ }
|
|
+
|
|
+ if ((flags & GPIOD_PULL_UP) && (flags & GPIOD_PULL_DOWN)) {
|
|
+ log_debug("%s: flags 0x%lx has GPIOD_PULL_UP and GPIOD_PULL_DOWN\n",
|
|
+ __func__, flags);
|
|
+ return -EINVAL;
|
|
+ }
|
|
+
|
|
+ if ((flags & GPIOD_OPEN_DRAIN) && (flags & GPIOD_OPEN_SOURCE)) {
|
|
+ log_debug("%s: flags 0x%lx has GPIOD_OPEN_DRAIN and GPIOD_OPEN_SOURCE\n",
|
|
+ __func__, flags);
|
|
+ return -EINVAL;
|
|
+ }
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+static int _dm_gpio_set_dir_flags(struct gpio_desc *desc, ulong flags)
|
|
+{
|
|
+ struct udevice *dev = desc->dev;
|
|
+ struct dm_gpio_ops *ops = gpio_get_ops(dev);
|
|
+ struct gpio_dev_priv *uc_priv = dev_get_uclass_priv(dev);
|
|
+ int ret = 0;
|
|
+
|
|
+ ret = check_dir_flags(flags);
|
|
+ if (ret) {
|
|
+ dev_dbg(dev,
|
|
+ "%s error: set_dir_flags for gpio %s%d has invalid dir flags 0x%lx\n",
|
|
+ desc->dev->name,
|
|
+ uc_priv->bank_name ? uc_priv->bank_name : "",
|
|
+ desc->offset, flags);
|
|
|
|
- ret = check_reserved(desc, "get_open_drain");
|
|
- if (ret)
|
|
return ret;
|
|
+ }
|
|
|
|
- if (ops->set_open_drain)
|
|
- return ops->get_open_drain(desc->dev, desc->offset);
|
|
- else
|
|
- return -ENOSYS;
|
|
+ /* GPIOD_ are directly managed by driver in set_dir_flags*/
|
|
+ if (ops->set_dir_flags) {
|
|
+ ret = ops->set_dir_flags(dev, desc->offset, flags);
|
|
+ } else {
|
|
+ if (flags & GPIOD_IS_OUT) {
|
|
+ ret = ops->direction_output(dev, desc->offset,
|
|
+ GPIOD_FLAGS_OUTPUT(flags));
|
|
+ } else if (flags & GPIOD_IS_IN) {
|
|
+ ret = ops->direction_input(dev, desc->offset);
|
|
+ }
|
|
+ }
|
|
+
|
|
+ return ret;
|
|
}
|
|
|
|
-int dm_gpio_set_open_drain(struct gpio_desc *desc, int value)
|
|
+int dm_gpio_set_dir_flags(struct gpio_desc *desc, ulong flags)
|
|
{
|
|
- struct dm_gpio_ops *ops = gpio_get_ops(desc->dev);
|
|
int ret;
|
|
|
|
- ret = check_reserved(desc, "set_open_drain");
|
|
+ ret = check_reserved(desc, "set_dir_flags");
|
|
if (ret)
|
|
return ret;
|
|
|
|
- if (ops->set_open_drain)
|
|
- ret = ops->set_open_drain(desc->dev, desc->offset, value);
|
|
- else
|
|
- return 0; /* feature not supported -> ignore setting */
|
|
+ /* combine the requested flags (for IN/OUT) and the descriptor flags */
|
|
+ flags |= desc->flags;
|
|
+ ret = _dm_gpio_set_dir_flags(desc, flags);
|
|
+
|
|
+ /* update the descriptor flags */
|
|
+ if (ret)
|
|
+ desc->flags = flags;
|
|
|
|
return ret;
|
|
}
|
|
|
|
-int dm_gpio_set_dir_flags(struct gpio_desc *desc, ulong flags)
|
|
+int dm_gpio_set_dir(struct gpio_desc *desc)
|
|
{
|
|
- struct udevice *dev = desc->dev;
|
|
- struct dm_gpio_ops *ops = gpio_get_ops(dev);
|
|
int ret;
|
|
|
|
ret = check_reserved(desc, "set_dir");
|
|
if (ret)
|
|
return ret;
|
|
|
|
- if (flags & GPIOD_IS_OUT) {
|
|
- int value = flags & GPIOD_IS_OUT_ACTIVE ? 1 : 0;
|
|
+ return _dm_gpio_set_dir_flags(desc, desc->flags);
|
|
+}
|
|
|
|
- if (flags & GPIOD_ACTIVE_LOW)
|
|
- value = !value;
|
|
- ret = ops->direction_output(dev, desc->offset, value);
|
|
- } else if (flags & GPIOD_IS_IN) {
|
|
- ret = ops->direction_input(dev, desc->offset);
|
|
- }
|
|
+int dm_gpio_get_dir_flags(struct gpio_desc *desc, ulong *flags)
|
|
+{
|
|
+ struct udevice *dev = desc->dev;
|
|
+ int ret, value;
|
|
+ struct dm_gpio_ops *ops = gpio_get_ops(dev);
|
|
+ ulong dir_flags;
|
|
+
|
|
+ ret = check_reserved(desc, "get_dir_flags");
|
|
if (ret)
|
|
return ret;
|
|
- /*
|
|
- * Update desc->flags here, so that GPIO_ACTIVE_LOW is honoured in
|
|
- * futures
|
|
- */
|
|
- desc->flags = flags;
|
|
|
|
- return 0;
|
|
-}
|
|
+ /* GPIOD_ are directly provided by driver except GPIOD_ACTIVE_LOW */
|
|
+ if (ops->get_dir_flags) {
|
|
+ ret = ops->get_dir_flags(dev, desc->offset, &dir_flags);
|
|
+ if (ret)
|
|
+ return ret;
|
|
|
|
-int dm_gpio_set_dir(struct gpio_desc *desc)
|
|
-{
|
|
- return dm_gpio_set_dir_flags(desc, desc->flags);
|
|
+ /* GPIOD_ACTIVE_LOW is saved in desc->flags */
|
|
+ value = dir_flags & GPIOD_IS_OUT_ACTIVE ? 1 : 0;
|
|
+ if (desc->flags & GPIOD_ACTIVE_LOW)
|
|
+ value = !value;
|
|
+ dir_flags &= ~(GPIOD_ACTIVE_LOW | GPIOD_IS_OUT_ACTIVE);
|
|
+ dir_flags |= (desc->flags & GPIOD_ACTIVE_LOW);
|
|
+ if (value)
|
|
+ dir_flags |= GPIOD_IS_OUT_ACTIVE;
|
|
+ } else {
|
|
+ dir_flags = desc->flags;
|
|
+ /* only GPIOD_IS_OUT_ACTIVE is provided by uclass */
|
|
+ dir_flags &= ~GPIOD_IS_OUT_ACTIVE;
|
|
+ if ((desc->flags & GPIOD_IS_OUT) && _gpio_get_value(desc))
|
|
+ dir_flags |= GPIOD_IS_OUT_ACTIVE;
|
|
+ }
|
|
+ *flags = dir_flags;
|
|
+
|
|
+ return 0;
|
|
}
|
|
|
|
/**
|
|
@@ -804,9 +899,7 @@ static int gpio_request_tail(int ret, const char *nodename,
|
|
struct gpio_desc *desc, int flags,
|
|
bool add_index, struct udevice *gpio_dev)
|
|
{
|
|
- desc->dev = gpio_dev;
|
|
- desc->offset = 0;
|
|
- desc->flags = 0;
|
|
+ gpio_desc_init(desc, gpio_dev, 0);
|
|
if (ret)
|
|
goto err;
|
|
|
|
@@ -830,7 +923,7 @@ static int gpio_request_tail(int ret, const char *nodename,
|
|
debug("%s: dm_gpio_requestf failed\n", __func__);
|
|
goto err;
|
|
}
|
|
- ret = dm_gpio_set_dir_flags(desc, flags | desc->flags);
|
|
+ ret = dm_gpio_set_dir_flags(desc, flags);
|
|
if (ret) {
|
|
debug("%s: dm_gpio_set_dir failed\n", __func__);
|
|
goto err;
|
|
@@ -1053,14 +1146,14 @@ static int gpio_post_bind(struct udevice *dev)
|
|
ops->get_value += gd->reloc_off;
|
|
if (ops->set_value)
|
|
ops->set_value += gd->reloc_off;
|
|
- if (ops->get_open_drain)
|
|
- ops->get_open_drain += gd->reloc_off;
|
|
- if (ops->set_open_drain)
|
|
- ops->set_open_drain += gd->reloc_off;
|
|
if (ops->get_function)
|
|
ops->get_function += gd->reloc_off;
|
|
if (ops->xlate)
|
|
ops->xlate += gd->reloc_off;
|
|
+ if (ops->set_dir_flags)
|
|
+ ops->set_dir_flags += gd->reloc_off;
|
|
+ if (ops->get_dir_flags)
|
|
+ ops->get_dir_flags += gd->reloc_off;
|
|
|
|
reloc_done++;
|
|
}
|
|
diff --git a/drivers/gpio/mpc8xxx_gpio.c b/drivers/gpio/mpc8xxx_gpio.c
|
|
index c273c2c..c23f5b5 100644
|
|
--- a/drivers/gpio/mpc8xxx_gpio.c
|
|
+++ b/drivers/gpio/mpc8xxx_gpio.c
|
|
@@ -144,26 +144,6 @@ static int mpc8xxx_gpio_get_value(struct udevice *dev, uint gpio)
|
|
return !!mpc8xxx_gpio_get_val(data->base, gpio_mask(gpio));
|
|
}
|
|
|
|
-static int mpc8xxx_gpio_get_open_drain(struct udevice *dev, uint gpio)
|
|
-{
|
|
- struct mpc8xxx_gpio_data *data = dev_get_priv(dev);
|
|
-
|
|
- return !!mpc8xxx_gpio_open_drain_val(data->base, gpio_mask(gpio));
|
|
-}
|
|
-
|
|
-static int mpc8xxx_gpio_set_open_drain(struct udevice *dev, uint gpio,
|
|
- int value)
|
|
-{
|
|
- struct mpc8xxx_gpio_data *data = dev_get_priv(dev);
|
|
-
|
|
- if (value)
|
|
- mpc8xxx_gpio_open_drain_on(data->base, gpio_mask(gpio));
|
|
- else
|
|
- mpc8xxx_gpio_open_drain_off(data->base, gpio_mask(gpio));
|
|
-
|
|
- return 0;
|
|
-}
|
|
-
|
|
static int mpc8xxx_gpio_get_function(struct udevice *dev, uint gpio)
|
|
{
|
|
struct mpc8xxx_gpio_data *data = dev_get_priv(dev);
|
|
@@ -240,8 +220,6 @@ static const struct dm_gpio_ops gpio_mpc8xxx_ops = {
|
|
.direction_output = mpc8xxx_gpio_direction_output,
|
|
.get_value = mpc8xxx_gpio_get_value,
|
|
.set_value = mpc8xxx_gpio_set_value,
|
|
- .get_open_drain = mpc8xxx_gpio_get_open_drain,
|
|
- .set_open_drain = mpc8xxx_gpio_set_open_drain,
|
|
.get_function = mpc8xxx_gpio_get_function,
|
|
};
|
|
|
|
diff --git a/drivers/gpio/sandbox.c b/drivers/gpio/sandbox.c
|
|
index 2ef5c67..bf6287f 100644
|
|
--- a/drivers/gpio/sandbox.c
|
|
+++ b/drivers/gpio/sandbox.c
|
|
@@ -8,43 +8,43 @@
|
|
#include <fdtdec.h>
|
|
#include <malloc.h>
|
|
#include <asm/gpio.h>
|
|
+#include <dm/lists.h>
|
|
#include <dm/of.h>
|
|
+#include <dm/pinctrl.h>
|
|
#include <dt-bindings/gpio/gpio.h>
|
|
+#include <dt-bindings/gpio/sandbox-gpio.h>
|
|
|
|
-/* Flags for each GPIO */
|
|
-#define GPIOF_OUTPUT (1 << 0) /* Currently set as an output */
|
|
-#define GPIOF_HIGH (1 << 1) /* Currently set high */
|
|
-#define GPIOF_ODR (1 << 2) /* Currently set to open drain mode */
|
|
|
|
struct gpio_state {
|
|
const char *label; /* label given by requester */
|
|
- u8 flags; /* flags (GPIOF_...) */
|
|
+ ulong dir_flags; /* dir_flags (GPIOD_...) */
|
|
};
|
|
|
|
-/* Access routines for GPIO state */
|
|
-static u8 *get_gpio_flags(struct udevice *dev, unsigned offset)
|
|
+/* Access routines for GPIO dir flags */
|
|
+static ulong *get_gpio_dir_flags(struct udevice *dev, unsigned int offset)
|
|
{
|
|
struct gpio_dev_priv *uc_priv = dev_get_uclass_priv(dev);
|
|
struct gpio_state *state = dev_get_priv(dev);
|
|
|
|
if (offset >= uc_priv->gpio_count) {
|
|
- static u8 invalid_flags;
|
|
+ static ulong invalid_dir_flags;
|
|
printf("sandbox_gpio: error: invalid gpio %u\n", offset);
|
|
- return &invalid_flags;
|
|
+ return &invalid_dir_flags;
|
|
}
|
|
|
|
- return &state[offset].flags;
|
|
+ return &state[offset].dir_flags;
|
|
+
|
|
}
|
|
|
|
-static int get_gpio_flag(struct udevice *dev, unsigned offset, int flag)
|
|
+static int get_gpio_flag(struct udevice *dev, unsigned int offset, ulong flag)
|
|
{
|
|
- return (*get_gpio_flags(dev, offset) & flag) != 0;
|
|
+ return (*get_gpio_dir_flags(dev, offset) & flag) != 0;
|
|
}
|
|
|
|
-static int set_gpio_flag(struct udevice *dev, unsigned offset, int flag,
|
|
+static int set_gpio_flag(struct udevice *dev, unsigned int offset, ulong flag,
|
|
int value)
|
|
{
|
|
- u8 *gpio = get_gpio_flags(dev, offset);
|
|
+ ulong *gpio = get_gpio_dir_flags(dev, offset);
|
|
|
|
if (value)
|
|
*gpio |= flag;
|
|
@@ -60,34 +60,40 @@ static int set_gpio_flag(struct udevice *dev, unsigned offset, int flag,
|
|
|
|
int sandbox_gpio_get_value(struct udevice *dev, unsigned offset)
|
|
{
|
|
- if (get_gpio_flag(dev, offset, GPIOF_OUTPUT))
|
|
+ if (get_gpio_flag(dev, offset, GPIOD_IS_OUT))
|
|
debug("sandbox_gpio: get_value on output gpio %u\n", offset);
|
|
- return get_gpio_flag(dev, offset, GPIOF_HIGH);
|
|
+ return get_gpio_flag(dev, offset, GPIOD_IS_OUT_ACTIVE);
|
|
}
|
|
|
|
int sandbox_gpio_set_value(struct udevice *dev, unsigned offset, int value)
|
|
{
|
|
- return set_gpio_flag(dev, offset, GPIOF_HIGH, value);
|
|
+ return set_gpio_flag(dev, offset, GPIOD_IS_OUT_ACTIVE, value);
|
|
}
|
|
|
|
-int sandbox_gpio_get_open_drain(struct udevice *dev, unsigned offset)
|
|
+int sandbox_gpio_get_direction(struct udevice *dev, unsigned offset)
|
|
{
|
|
- return get_gpio_flag(dev, offset, GPIOF_ODR);
|
|
+ return get_gpio_flag(dev, offset, GPIOD_IS_OUT);
|
|
}
|
|
|
|
-int sandbox_gpio_set_open_drain(struct udevice *dev, unsigned offset, int value)
|
|
+int sandbox_gpio_set_direction(struct udevice *dev, unsigned offset, int output)
|
|
{
|
|
- return set_gpio_flag(dev, offset, GPIOF_ODR, value);
|
|
+ set_gpio_flag(dev, offset, GPIOD_IS_OUT, output);
|
|
+ set_gpio_flag(dev, offset, GPIOD_IS_IN, !(output));
|
|
+
|
|
+ return 0;
|
|
}
|
|
|
|
-int sandbox_gpio_get_direction(struct udevice *dev, unsigned offset)
|
|
+ulong sandbox_gpio_get_dir_flags(struct udevice *dev, unsigned int offset)
|
|
{
|
|
- return get_gpio_flag(dev, offset, GPIOF_OUTPUT);
|
|
+ return *get_gpio_dir_flags(dev, offset);
|
|
}
|
|
|
|
-int sandbox_gpio_set_direction(struct udevice *dev, unsigned offset, int output)
|
|
+int sandbox_gpio_set_dir_flags(struct udevice *dev, unsigned int offset,
|
|
+ ulong flags)
|
|
{
|
|
- return set_gpio_flag(dev, offset, GPIOF_OUTPUT, output);
|
|
+ *get_gpio_dir_flags(dev, offset) = flags;
|
|
+
|
|
+ return 0;
|
|
}
|
|
|
|
/*
|
|
@@ -134,33 +140,14 @@ static int sb_gpio_set_value(struct udevice *dev, unsigned offset, int value)
|
|
return sandbox_gpio_set_value(dev, offset, value);
|
|
}
|
|
|
|
-/* read GPIO ODR value of port 'offset' */
|
|
-static int sb_gpio_get_open_drain(struct udevice *dev, unsigned offset)
|
|
-{
|
|
- debug("%s: offset:%u\n", __func__, offset);
|
|
-
|
|
- return sandbox_gpio_get_open_drain(dev, offset);
|
|
-}
|
|
-
|
|
-/* write GPIO ODR value to port 'offset' */
|
|
-static int sb_gpio_set_open_drain(struct udevice *dev, unsigned offset, int value)
|
|
-{
|
|
- debug("%s: offset:%u, value = %d\n", __func__, offset, value);
|
|
-
|
|
- if (!sandbox_gpio_get_direction(dev, offset)) {
|
|
- printf("sandbox_gpio: error: set_open_drain on input gpio %u\n",
|
|
- offset);
|
|
- return -1;
|
|
- }
|
|
-
|
|
- return sandbox_gpio_set_open_drain(dev, offset, value);
|
|
-}
|
|
-
|
|
static int sb_gpio_get_function(struct udevice *dev, unsigned offset)
|
|
{
|
|
- if (get_gpio_flag(dev, offset, GPIOF_OUTPUT))
|
|
+ if (get_gpio_flag(dev, offset, GPIOD_IS_OUT))
|
|
return GPIOF_OUTPUT;
|
|
- return GPIOF_INPUT;
|
|
+ if (get_gpio_flag(dev, offset, GPIOD_IS_IN))
|
|
+ return GPIOF_INPUT;
|
|
+
|
|
+ return GPIOF_INPUT; /*GPIO is not configurated */
|
|
}
|
|
|
|
static int sb_gpio_xlate(struct udevice *dev, struct gpio_desc *desc,
|
|
@@ -169,27 +156,54 @@ static int sb_gpio_xlate(struct udevice *dev, struct gpio_desc *desc,
|
|
desc->offset = args->args[0];
|
|
if (args->args_count < 2)
|
|
return 0;
|
|
- if (args->args[1] & GPIO_ACTIVE_LOW)
|
|
- desc->flags |= GPIOD_ACTIVE_LOW;
|
|
- if (args->args[1] & 2)
|
|
+ /* treat generic binding with gpio uclass */
|
|
+ gpio_xlate_offs_flags(dev, desc, args);
|
|
+
|
|
+ /* sandbox test specific, not defined in gpio.h */
|
|
+ if (args->args[1] & GPIO_IN)
|
|
desc->flags |= GPIOD_IS_IN;
|
|
- if (args->args[1] & 4)
|
|
+
|
|
+ if (args->args[1] & GPIO_OUT)
|
|
desc->flags |= GPIOD_IS_OUT;
|
|
- if (args->args[1] & 8)
|
|
+
|
|
+ if (args->args[1] & GPIO_OUT_ACTIVE)
|
|
desc->flags |= GPIOD_IS_OUT_ACTIVE;
|
|
|
|
return 0;
|
|
}
|
|
|
|
+static int sb_gpio_set_dir_flags(struct udevice *dev, unsigned int offset,
|
|
+ ulong flags)
|
|
+{
|
|
+ ulong *dir_flags;
|
|
+
|
|
+ debug("%s: offset:%u, dir_flags = %lx\n", __func__, offset, flags);
|
|
+
|
|
+ dir_flags = get_gpio_dir_flags(dev, offset);
|
|
+
|
|
+ *dir_flags = flags;
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+static int sb_gpio_get_dir_flags(struct udevice *dev, unsigned int offset,
|
|
+ ulong *flags)
|
|
+{
|
|
+ debug("%s: offset:%u\n", __func__, offset);
|
|
+ *flags = *get_gpio_dir_flags(dev, offset);
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+
|
|
static const struct dm_gpio_ops gpio_sandbox_ops = {
|
|
.direction_input = sb_gpio_direction_input,
|
|
.direction_output = sb_gpio_direction_output,
|
|
.get_value = sb_gpio_get_value,
|
|
.set_value = sb_gpio_set_value,
|
|
- .get_open_drain = sb_gpio_get_open_drain,
|
|
- .set_open_drain = sb_gpio_set_open_drain,
|
|
.get_function = sb_gpio_get_function,
|
|
.xlate = sb_gpio_xlate,
|
|
+ .set_dir_flags = sb_gpio_set_dir_flags,
|
|
+ .get_dir_flags = sb_gpio_get_dir_flags,
|
|
};
|
|
|
|
static int sandbox_gpio_ofdata_to_platdata(struct udevice *dev)
|
|
@@ -237,3 +251,198 @@ U_BOOT_DRIVER(gpio_sandbox) = {
|
|
.remove = gpio_sandbox_remove,
|
|
.ops = &gpio_sandbox_ops,
|
|
};
|
|
+
|
|
+/* pincontrol: used only to check GPIO pin configuration (pinmux command) */
|
|
+
|
|
+struct sb_pinctrl_priv {
|
|
+ int pinctrl_ngpios;
|
|
+ struct list_head gpio_dev;
|
|
+};
|
|
+
|
|
+struct sb_gpio_bank {
|
|
+ struct udevice *gpio_dev;
|
|
+ struct list_head list;
|
|
+};
|
|
+
|
|
+static int sb_populate_gpio_dev_list(struct udevice *dev)
|
|
+{
|
|
+ struct sb_pinctrl_priv *priv = dev_get_priv(dev);
|
|
+ struct udevice *gpio_dev;
|
|
+ struct udevice *child;
|
|
+ struct sb_gpio_bank *gpio_bank;
|
|
+ int ret;
|
|
+
|
|
+ /*
|
|
+ * parse pin-controller sub-nodes (ie gpio bank nodes) and fill
|
|
+ * a list with all gpio device reference which belongs to the
|
|
+ * current pin-controller. This list is used to find pin_name and
|
|
+ * pin muxing
|
|
+ */
|
|
+ list_for_each_entry(child, &dev->child_head, sibling_node) {
|
|
+ ret = uclass_get_device_by_name(UCLASS_GPIO, child->name,
|
|
+ &gpio_dev);
|
|
+ if (ret < 0)
|
|
+ continue;
|
|
+
|
|
+ gpio_bank = malloc(sizeof(*gpio_bank));
|
|
+ if (!gpio_bank) {
|
|
+ dev_err(dev, "Not enough memory\n");
|
|
+ return -ENOMEM;
|
|
+ }
|
|
+
|
|
+ gpio_bank->gpio_dev = gpio_dev;
|
|
+ list_add_tail(&gpio_bank->list, &priv->gpio_dev);
|
|
+ }
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+static int sb_pinctrl_get_pins_count(struct udevice *dev)
|
|
+{
|
|
+ struct sb_pinctrl_priv *priv = dev_get_priv(dev);
|
|
+ struct gpio_dev_priv *uc_priv;
|
|
+ struct sb_gpio_bank *gpio_bank;
|
|
+
|
|
+ /*
|
|
+ * if get_pins_count has already been executed once on this
|
|
+ * pin-controller, no need to run it again
|
|
+ */
|
|
+ if (priv->pinctrl_ngpios)
|
|
+ return priv->pinctrl_ngpios;
|
|
+
|
|
+ if (list_empty(&priv->gpio_dev))
|
|
+ sb_populate_gpio_dev_list(dev);
|
|
+ /*
|
|
+ * walk through all banks to retrieve the pin-controller
|
|
+ * pins number
|
|
+ */
|
|
+ list_for_each_entry(gpio_bank, &priv->gpio_dev, list) {
|
|
+ uc_priv = dev_get_uclass_priv(gpio_bank->gpio_dev);
|
|
+
|
|
+ priv->pinctrl_ngpios += uc_priv->gpio_count;
|
|
+ }
|
|
+
|
|
+ return priv->pinctrl_ngpios;
|
|
+}
|
|
+
|
|
+static struct udevice *sb_pinctrl_get_gpio_dev(struct udevice *dev,
|
|
+ unsigned int selector,
|
|
+ unsigned int *idx)
|
|
+{
|
|
+ struct sb_pinctrl_priv *priv = dev_get_priv(dev);
|
|
+ struct sb_gpio_bank *gpio_bank;
|
|
+ struct gpio_dev_priv *uc_priv;
|
|
+ int pin_count = 0;
|
|
+
|
|
+ if (list_empty(&priv->gpio_dev))
|
|
+ sb_populate_gpio_dev_list(dev);
|
|
+
|
|
+ /* look up for the bank which owns the requested pin */
|
|
+ list_for_each_entry(gpio_bank, &priv->gpio_dev, list) {
|
|
+ uc_priv = dev_get_uclass_priv(gpio_bank->gpio_dev);
|
|
+
|
|
+ if (selector < (pin_count + uc_priv->gpio_count)) {
|
|
+ /*
|
|
+ * we found the bank, convert pin selector to
|
|
+ * gpio bank index
|
|
+ */
|
|
+ *idx = selector - pin_count;
|
|
+
|
|
+ return gpio_bank->gpio_dev;
|
|
+ }
|
|
+ pin_count += uc_priv->gpio_count;
|
|
+ }
|
|
+
|
|
+ return NULL;
|
|
+}
|
|
+
|
|
+static const char *sb_pinctrl_get_pin_name(struct udevice *dev,
|
|
+ unsigned int selector)
|
|
+{
|
|
+ struct gpio_dev_priv *uc_priv;
|
|
+ struct udevice *gpio_dev;
|
|
+ unsigned int gpio_idx;
|
|
+ static char pin_name[PINNAME_SIZE];
|
|
+
|
|
+ /* look up for the bank which owns the requested pin */
|
|
+ gpio_dev = sb_pinctrl_get_gpio_dev(dev, selector, &gpio_idx);
|
|
+ if (!gpio_dev) {
|
|
+ snprintf(pin_name, PINNAME_SIZE, "Error");
|
|
+ } else {
|
|
+ uc_priv = dev_get_uclass_priv(gpio_dev);
|
|
+
|
|
+ snprintf(pin_name, PINNAME_SIZE, "%s%d",
|
|
+ uc_priv->bank_name,
|
|
+ gpio_idx);
|
|
+ }
|
|
+
|
|
+ return pin_name;
|
|
+}
|
|
+
|
|
+static char *get_dir_flags_string(ulong flags)
|
|
+{
|
|
+ if (flags & GPIOD_OPEN_DRAIN)
|
|
+ return "drive-open-drain";
|
|
+ if (flags & GPIOD_OPEN_SOURCE)
|
|
+ return "drive-open-source";
|
|
+ if (flags & GPIOD_PULL_UP)
|
|
+ return "bias-pull-up";
|
|
+ if (flags & GPIOD_PULL_DOWN)
|
|
+ return "bias-pull-down";
|
|
+ return ".";
|
|
+}
|
|
+
|
|
+static int sb_pinctrl_get_pin_muxing(struct udevice *dev,
|
|
+ unsigned int selector,
|
|
+ char *buf, int size)
|
|
+{
|
|
+ struct udevice *gpio_dev;
|
|
+ unsigned int gpio_idx;
|
|
+ ulong dir_flags;
|
|
+ int function;
|
|
+
|
|
+ /* look up for the bank which owns the requested pin */
|
|
+ gpio_dev = sb_pinctrl_get_gpio_dev(dev, selector, &gpio_idx);
|
|
+ if (!gpio_dev) {
|
|
+ snprintf(buf, size, "Error");
|
|
+ } else {
|
|
+ function = sb_gpio_get_function(gpio_dev, gpio_idx);
|
|
+ dir_flags = *get_gpio_dir_flags(gpio_dev, gpio_idx);
|
|
+
|
|
+ snprintf(buf, size, "gpio %s %s",
|
|
+ function == GPIOF_OUTPUT ? "output" : "input",
|
|
+ get_dir_flags_string(dir_flags));
|
|
+ }
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+static int sandbox_pinctrl_probe(struct udevice *dev)
|
|
+{
|
|
+ struct sb_pinctrl_priv *priv = dev_get_priv(dev);
|
|
+
|
|
+ INIT_LIST_HEAD(&priv->gpio_dev);
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+static struct pinctrl_ops sandbox_pinctrl_gpio_ops = {
|
|
+ .get_pin_name = sb_pinctrl_get_pin_name,
|
|
+ .get_pins_count = sb_pinctrl_get_pins_count,
|
|
+ .get_pin_muxing = sb_pinctrl_get_pin_muxing,
|
|
+};
|
|
+
|
|
+static const struct udevice_id sandbox_pinctrl_gpio_match[] = {
|
|
+ { .compatible = "sandbox,pinctrl-gpio" },
|
|
+ { /* sentinel */ }
|
|
+};
|
|
+
|
|
+U_BOOT_DRIVER(sandbox_pinctrl_gpio) = {
|
|
+ .name = "sandbox_pinctrl_gpio",
|
|
+ .id = UCLASS_PINCTRL,
|
|
+ .of_match = sandbox_pinctrl_gpio_match,
|
|
+ .ops = &sandbox_pinctrl_gpio_ops,
|
|
+ .bind = dm_scan_fdt_dev,
|
|
+ .probe = sandbox_pinctrl_probe,
|
|
+ .priv_auto_alloc_size = sizeof(struct sb_pinctrl_priv),
|
|
+};
|
|
diff --git a/drivers/gpio/stm32_gpio.c b/drivers/gpio/stm32_gpio.c
|
|
index 302a434..a7c89a4 100644
|
|
--- a/drivers/gpio/stm32_gpio.c
|
|
+++ b/drivers/gpio/stm32_gpio.c
|
|
@@ -19,7 +19,62 @@
|
|
#define MODE_BITS_MASK 3
|
|
#define BSRR_BIT(gpio_pin, value) BIT(gpio_pin + (value ? 0 : 16))
|
|
|
|
-#ifndef CONFIG_SPL_BUILD
|
|
+#define PUPD_BITS(gpio_pin) (gpio_pin * 2)
|
|
+#define PUPD_MASK 3
|
|
+
|
|
+#define OTYPE_BITS(gpio_pin) (gpio_pin)
|
|
+#define OTYPE_MSK 1
|
|
+
|
|
+static void stm32_gpio_set_moder(struct stm32_gpio_regs *regs,
|
|
+ int idx,
|
|
+ int mode)
|
|
+{
|
|
+ int bits_index;
|
|
+ int mask;
|
|
+
|
|
+ bits_index = MODE_BITS(idx);
|
|
+ mask = MODE_BITS_MASK << bits_index;
|
|
+
|
|
+ clrsetbits_le32(®s->moder, mask, mode << bits_index);
|
|
+}
|
|
+
|
|
+static int stm32_gpio_get_moder(struct stm32_gpio_regs *regs, int idx)
|
|
+{
|
|
+ return (readl(®s->moder) >> MODE_BITS(idx)) & MODE_BITS_MASK;
|
|
+}
|
|
+
|
|
+static void stm32_gpio_set_otype(struct stm32_gpio_regs *regs,
|
|
+ int idx,
|
|
+ enum stm32_gpio_otype otype)
|
|
+{
|
|
+ int bits;
|
|
+
|
|
+ bits = OTYPE_BITS(idx);
|
|
+ clrsetbits_le32(®s->otyper, OTYPE_MSK << bits, otype << bits);
|
|
+}
|
|
+
|
|
+static enum stm32_gpio_otype stm32_gpio_get_otype(struct stm32_gpio_regs *regs,
|
|
+ int idx)
|
|
+{
|
|
+ return (readl(®s->otyper) >> OTYPE_BITS(idx)) & OTYPE_MSK;
|
|
+}
|
|
+
|
|
+static void stm32_gpio_set_pupd(struct stm32_gpio_regs *regs,
|
|
+ int idx,
|
|
+ enum stm32_gpio_pupd pupd)
|
|
+{
|
|
+ int bits;
|
|
+
|
|
+ bits = PUPD_BITS(idx);
|
|
+ clrsetbits_le32(®s->pupdr, PUPD_MASK << bits, pupd << bits);
|
|
+}
|
|
+
|
|
+static enum stm32_gpio_pupd stm32_gpio_get_pupd(struct stm32_gpio_regs *regs,
|
|
+ int idx)
|
|
+{
|
|
+ return (readl(®s->pupdr) >> PUPD_BITS(idx)) & PUPD_MASK;
|
|
+}
|
|
+
|
|
/*
|
|
* convert gpio offset to gpio index taking into account gpio holes
|
|
* into gpio bank
|
|
@@ -45,18 +100,13 @@ static int stm32_gpio_direction_input(struct udevice *dev, unsigned offset)
|
|
{
|
|
struct stm32_gpio_priv *priv = dev_get_priv(dev);
|
|
struct stm32_gpio_regs *regs = priv->regs;
|
|
- int bits_index;
|
|
- int mask;
|
|
int idx;
|
|
|
|
idx = stm32_offset_to_index(dev, offset);
|
|
if (idx < 0)
|
|
return idx;
|
|
|
|
- bits_index = MODE_BITS(idx);
|
|
- mask = MODE_BITS_MASK << bits_index;
|
|
-
|
|
- clrsetbits_le32(®s->moder, mask, STM32_GPIO_MODE_IN << bits_index);
|
|
+ stm32_gpio_set_moder(regs, idx, STM32_GPIO_MODE_IN);
|
|
|
|
return 0;
|
|
}
|
|
@@ -66,18 +116,13 @@ static int stm32_gpio_direction_output(struct udevice *dev, unsigned offset,
|
|
{
|
|
struct stm32_gpio_priv *priv = dev_get_priv(dev);
|
|
struct stm32_gpio_regs *regs = priv->regs;
|
|
- int bits_index;
|
|
- int mask;
|
|
int idx;
|
|
|
|
idx = stm32_offset_to_index(dev, offset);
|
|
if (idx < 0)
|
|
return idx;
|
|
|
|
- bits_index = MODE_BITS(idx);
|
|
- mask = MODE_BITS_MASK << bits_index;
|
|
-
|
|
- clrsetbits_le32(®s->moder, mask, STM32_GPIO_MODE_OUT << bits_index);
|
|
+ stm32_gpio_set_moder(regs, idx, STM32_GPIO_MODE_OUT);
|
|
|
|
writel(BSRR_BIT(idx, value), ®s->bsrr);
|
|
|
|
@@ -139,14 +184,88 @@ static int stm32_gpio_get_function(struct udevice *dev, unsigned int offset)
|
|
return GPIOF_FUNC;
|
|
}
|
|
|
|
+static int stm32_gpio_set_dir_flags(struct udevice *dev, unsigned int offset,
|
|
+ ulong flags)
|
|
+{
|
|
+ struct stm32_gpio_priv *priv = dev_get_priv(dev);
|
|
+ struct stm32_gpio_regs *regs = priv->regs;
|
|
+ int idx;
|
|
+
|
|
+ idx = stm32_offset_to_index(dev, offset);
|
|
+ if (idx < 0)
|
|
+ return idx;
|
|
+
|
|
+ if (flags & GPIOD_IS_OUT) {
|
|
+ int value = GPIOD_FLAGS_OUTPUT(flags);
|
|
+
|
|
+ if (flags & GPIOD_OPEN_DRAIN)
|
|
+ stm32_gpio_set_otype(regs, idx, STM32_GPIO_OTYPE_OD);
|
|
+ else
|
|
+ stm32_gpio_set_otype(regs, idx, STM32_GPIO_OTYPE_PP);
|
|
+ stm32_gpio_set_moder(regs, idx, STM32_GPIO_MODE_OUT);
|
|
+ writel(BSRR_BIT(idx, value), ®s->bsrr);
|
|
+
|
|
+ } else if (flags & GPIOD_IS_IN) {
|
|
+ stm32_gpio_set_moder(regs, idx, STM32_GPIO_MODE_IN);
|
|
+ if (flags & GPIOD_PULL_UP)
|
|
+ stm32_gpio_set_pupd(regs, idx, STM32_GPIO_PUPD_UP);
|
|
+ else if (flags & GPIOD_PULL_DOWN)
|
|
+ stm32_gpio_set_pupd(regs, idx, STM32_GPIO_PUPD_DOWN);
|
|
+ }
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+static int stm32_gpio_get_dir_flags(struct udevice *dev, unsigned int offset,
|
|
+ ulong *flags)
|
|
+{
|
|
+ struct stm32_gpio_priv *priv = dev_get_priv(dev);
|
|
+ struct stm32_gpio_regs *regs = priv->regs;
|
|
+ int idx;
|
|
+ ulong dir_flags = 0;
|
|
+
|
|
+ idx = stm32_offset_to_index(dev, offset);
|
|
+ if (idx < 0)
|
|
+ return idx;
|
|
+
|
|
+ switch (stm32_gpio_get_moder(regs, idx)) {
|
|
+ case STM32_GPIO_MODE_OUT:
|
|
+ dir_flags |= GPIOD_IS_OUT;
|
|
+ if (stm32_gpio_get_otype(regs, idx) == STM32_GPIO_OTYPE_OD)
|
|
+ dir_flags |= GPIOD_OPEN_DRAIN;
|
|
+ if (readl(®s->idr) & BIT(idx))
|
|
+ dir_flags |= GPIOD_IS_OUT_ACTIVE;
|
|
+ break;
|
|
+ case STM32_GPIO_MODE_IN:
|
|
+ dir_flags |= GPIOD_IS_IN;
|
|
+ switch (stm32_gpio_get_pupd(regs, idx)) {
|
|
+ case STM32_GPIO_PUPD_UP:
|
|
+ dir_flags |= GPIOD_PULL_UP;
|
|
+ break;
|
|
+ case STM32_GPIO_PUPD_DOWN:
|
|
+ dir_flags |= GPIOD_PULL_DOWN;
|
|
+ break;
|
|
+ default:
|
|
+ break;
|
|
+ }
|
|
+ break;
|
|
+ default:
|
|
+ break;
|
|
+ }
|
|
+ *flags = dir_flags;
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+
|
|
static const struct dm_gpio_ops gpio_stm32_ops = {
|
|
.direction_input = stm32_gpio_direction_input,
|
|
.direction_output = stm32_gpio_direction_output,
|
|
.get_value = stm32_gpio_get_value,
|
|
.set_value = stm32_gpio_set_value,
|
|
.get_function = stm32_gpio_get_function,
|
|
+ .set_dir_flags = stm32_gpio_set_dir_flags,
|
|
+ .get_dir_flags = stm32_gpio_get_dir_flags,
|
|
};
|
|
-#endif
|
|
|
|
static int gpio_stm32_probe(struct udevice *dev)
|
|
{
|
|
@@ -161,7 +280,6 @@ static int gpio_stm32_probe(struct udevice *dev)
|
|
|
|
priv->regs = (struct stm32_gpio_regs *)addr;
|
|
|
|
-#ifndef CONFIG_SPL_BUILD
|
|
struct gpio_dev_priv *uc_priv = dev_get_uclass_priv(dev);
|
|
struct ofnode_phandle_args args;
|
|
const char *name;
|
|
@@ -194,7 +312,7 @@ static int gpio_stm32_probe(struct udevice *dev)
|
|
dev_dbg(dev, "addr = 0x%p bank_name = %s gpio_count = %d gpio_range = 0x%x\n",
|
|
(u32 *)priv->regs, uc_priv->bank_name, uc_priv->gpio_count,
|
|
priv->gpio_range);
|
|
-#endif
|
|
+
|
|
ret = clk_get_by_index(dev, 0, &clk);
|
|
if (ret < 0)
|
|
return ret;
|
|
@@ -214,9 +332,7 @@ U_BOOT_DRIVER(gpio_stm32) = {
|
|
.name = "gpio_stm32",
|
|
.id = UCLASS_GPIO,
|
|
.probe = gpio_stm32_probe,
|
|
-#ifndef CONFIG_SPL_BUILD
|
|
.ops = &gpio_stm32_ops,
|
|
-#endif
|
|
.flags = DM_UC_FLAG_SEQ_ALIAS,
|
|
.priv_auto_alloc_size = sizeof(struct stm32_gpio_priv),
|
|
};
|
|
diff --git a/drivers/i2c/stm32f7_i2c.c b/drivers/i2c/stm32f7_i2c.c
|
|
index 2b18735..7321f80 100644
|
|
--- a/drivers/i2c/stm32f7_i2c.c
|
|
+++ b/drivers/i2c/stm32f7_i2c.c
|
|
@@ -10,6 +10,7 @@
|
|
#include <reset.h>
|
|
|
|
#include <dm/device.h>
|
|
+#include <linux/err.h>
|
|
#include <linux/io.h>
|
|
|
|
/* STM32 I2C registers */
|
|
@@ -115,17 +116,6 @@ struct stm32_i2c_regs {
|
|
|
|
#define STM32_NSEC_PER_SEC 1000000000L
|
|
|
|
-#define STANDARD_RATE 100000
|
|
-#define FAST_RATE 400000
|
|
-#define FAST_PLUS_RATE 1000000
|
|
-
|
|
-enum stm32_i2c_speed {
|
|
- STM32_I2C_SPEED_STANDARD, /* 100 kHz */
|
|
- STM32_I2C_SPEED_FAST, /* 400 kHz */
|
|
- STM32_I2C_SPEED_FAST_PLUS, /* 1 MHz */
|
|
- STM32_I2C_SPEED_END,
|
|
-};
|
|
-
|
|
/**
|
|
* struct stm32_i2c_spec - private i2c specification timing
|
|
* @rate: I2C bus speed (Hz)
|
|
@@ -155,7 +145,6 @@ struct stm32_i2c_spec {
|
|
|
|
/**
|
|
* struct stm32_i2c_setup - private I2C timing setup parameters
|
|
- * @speed: I2C speed mode (standard, Fast Plus)
|
|
* @speed_freq: I2C speed frequency (Hz)
|
|
* @clock_src: I2C clock source frequency (Hz)
|
|
* @rise_time: Rise time (ns)
|
|
@@ -164,7 +153,6 @@ struct stm32_i2c_spec {
|
|
* @analog_filter: Analog filter delay (On/Off)
|
|
*/
|
|
struct stm32_i2c_setup {
|
|
- enum stm32_i2c_speed speed;
|
|
u32 speed_freq;
|
|
u32 clock_src;
|
|
u32 rise_time;
|
|
@@ -194,12 +182,13 @@ struct stm32_i2c_priv {
|
|
struct stm32_i2c_regs *regs;
|
|
struct clk clk;
|
|
struct stm32_i2c_setup *setup;
|
|
- int speed;
|
|
+ u32 speed;
|
|
};
|
|
|
|
static const struct stm32_i2c_spec i2c_specs[] = {
|
|
- [STM32_I2C_SPEED_STANDARD] = {
|
|
- .rate = STANDARD_RATE,
|
|
+ /* Standard speed - 100 KHz */
|
|
+ [IC_SPEED_MODE_STANDARD] = {
|
|
+ .rate = I2C_SPEED_STANDARD_RATE,
|
|
.rate_min = 8000,
|
|
.rate_max = 120000,
|
|
.fall_max = 300,
|
|
@@ -210,8 +199,9 @@ static const struct stm32_i2c_spec i2c_specs[] = {
|
|
.l_min = 4700,
|
|
.h_min = 4000,
|
|
},
|
|
- [STM32_I2C_SPEED_FAST] = {
|
|
- .rate = FAST_RATE,
|
|
+ /* Fast speed - 400 KHz */
|
|
+ [IC_SPEED_MODE_FAST] = {
|
|
+ .rate = I2C_SPEED_FAST_RATE,
|
|
.rate_min = 320000,
|
|
.rate_max = 480000,
|
|
.fall_max = 300,
|
|
@@ -222,8 +212,9 @@ static const struct stm32_i2c_spec i2c_specs[] = {
|
|
.l_min = 1300,
|
|
.h_min = 600,
|
|
},
|
|
- [STM32_I2C_SPEED_FAST_PLUS] = {
|
|
- .rate = FAST_PLUS_RATE,
|
|
+ /* Fast Plus Speed - 1 MHz */
|
|
+ [IC_SPEED_MODE_FAST_PLUS] = {
|
|
+ .rate = I2C_SPEED_FAST_PLUS_RATE,
|
|
.rate_min = 800000,
|
|
.rate_max = 1200000,
|
|
.fall_max = 100,
|
|
@@ -484,6 +475,7 @@ static int stm32_i2c_xfer(struct udevice *bus, struct i2c_msg *msg,
|
|
}
|
|
|
|
static int stm32_i2c_compute_solutions(struct stm32_i2c_setup *setup,
|
|
+ const struct stm32_i2c_spec *specs,
|
|
struct list_head *solutions)
|
|
{
|
|
struct stm32_i2c_timings *v;
|
|
@@ -500,13 +492,13 @@ static int stm32_i2c_compute_solutions(struct stm32_i2c_setup *setup,
|
|
af_delay_max = setup->analog_filter ?
|
|
STM32_I2C_ANALOG_FILTER_DELAY_MAX : 0;
|
|
|
|
- sdadel_min = i2c_specs[setup->speed].hddat_min + setup->fall_time -
|
|
+ sdadel_min = specs->hddat_min + setup->fall_time -
|
|
af_delay_min - (setup->dnf + 3) * i2cclk;
|
|
|
|
- sdadel_max = i2c_specs[setup->speed].vddat_max - setup->rise_time -
|
|
+ sdadel_max = specs->vddat_max - setup->rise_time -
|
|
af_delay_max - (setup->dnf + 4) * i2cclk;
|
|
|
|
- scldel_min = setup->rise_time + i2c_specs[setup->speed].sudat_min;
|
|
+ scldel_min = setup->rise_time + specs->sudat_min;
|
|
|
|
if (sdadel_min < 0)
|
|
sdadel_min = 0;
|
|
@@ -558,6 +550,7 @@ static int stm32_i2c_compute_solutions(struct stm32_i2c_setup *setup,
|
|
}
|
|
|
|
static int stm32_i2c_choose_solution(struct stm32_i2c_setup *setup,
|
|
+ const struct stm32_i2c_spec *specs,
|
|
struct list_head *solutions,
|
|
struct stm32_i2c_timings *s)
|
|
{
|
|
@@ -580,8 +573,8 @@ static int stm32_i2c_choose_solution(struct stm32_i2c_setup *setup,
|
|
dnf_delay = setup->dnf * i2cclk;
|
|
|
|
tsync = af_delay_min + dnf_delay + (2 * i2cclk);
|
|
- clk_max = STM32_NSEC_PER_SEC / i2c_specs[setup->speed].rate_min;
|
|
- clk_min = STM32_NSEC_PER_SEC / i2c_specs[setup->speed].rate_max;
|
|
+ clk_max = STM32_NSEC_PER_SEC / specs->rate_min;
|
|
+ clk_min = STM32_NSEC_PER_SEC / specs->rate_max;
|
|
|
|
/*
|
|
* Among Prescaler possibilities discovered above figures out SCL Low
|
|
@@ -599,7 +592,7 @@ static int stm32_i2c_choose_solution(struct stm32_i2c_setup *setup,
|
|
for (l = 0; l < STM32_SCLL_MAX; l++) {
|
|
u32 tscl_l = (l + 1) * prescaler + tsync;
|
|
|
|
- if ((tscl_l < i2c_specs[setup->speed].l_min) ||
|
|
+ if (tscl_l < specs->l_min ||
|
|
(i2cclk >=
|
|
((tscl_l - af_delay_min - dnf_delay) / 4))) {
|
|
continue;
|
|
@@ -611,7 +604,7 @@ static int stm32_i2c_choose_solution(struct stm32_i2c_setup *setup,
|
|
setup->rise_time + setup->fall_time;
|
|
|
|
if ((tscl >= clk_min) && (tscl <= clk_max) &&
|
|
- (tscl_h >= i2c_specs[setup->speed].h_min) &&
|
|
+ (tscl_h >= specs->h_min) &&
|
|
(i2cclk < tscl_h)) {
|
|
u32 clk_error;
|
|
|
|
@@ -640,26 +633,40 @@ static int stm32_i2c_choose_solution(struct stm32_i2c_setup *setup,
|
|
return ret;
|
|
}
|
|
|
|
+static const struct stm32_i2c_spec *get_specs(u32 rate)
|
|
+{
|
|
+ unsigned int i;
|
|
+
|
|
+ for (i = 0; i < ARRAY_SIZE(i2c_specs); i++)
|
|
+ if (rate <= i2c_specs[i].rate)
|
|
+ return &i2c_specs[i];
|
|
+
|
|
+ /* NOT REACHED */
|
|
+ return ERR_PTR(-EINVAL);
|
|
+}
|
|
+
|
|
static int stm32_i2c_compute_timing(struct stm32_i2c_priv *i2c_priv,
|
|
struct stm32_i2c_setup *setup,
|
|
struct stm32_i2c_timings *output)
|
|
{
|
|
+ const struct stm32_i2c_spec *specs;
|
|
struct stm32_i2c_timings *v, *_v;
|
|
struct list_head solutions;
|
|
int ret;
|
|
|
|
- if (setup->speed >= STM32_I2C_SPEED_END) {
|
|
- pr_err("%s: speed out of bound {%d/%d}\n", __func__,
|
|
- setup->speed, STM32_I2C_SPEED_END - 1);
|
|
+ specs = get_specs(setup->speed_freq);
|
|
+ if (specs == ERR_PTR(-EINVAL)) {
|
|
+ pr_err("%s: speed out of bound {%d}\n", __func__,
|
|
+ setup->speed_freq);
|
|
return -EINVAL;
|
|
}
|
|
|
|
- if ((setup->rise_time > i2c_specs[setup->speed].rise_max) ||
|
|
- (setup->fall_time > i2c_specs[setup->speed].fall_max)) {
|
|
+ if (setup->rise_time > specs->rise_max ||
|
|
+ setup->fall_time > specs->fall_max) {
|
|
pr_err("%s :timings out of bound Rise{%d>%d}/Fall{%d>%d}\n",
|
|
__func__,
|
|
- setup->rise_time, i2c_specs[setup->speed].rise_max,
|
|
- setup->fall_time, i2c_specs[setup->speed].fall_max);
|
|
+ setup->rise_time, specs->rise_max,
|
|
+ setup->fall_time, specs->fall_max);
|
|
return -EINVAL;
|
|
}
|
|
|
|
@@ -669,18 +676,12 @@ static int stm32_i2c_compute_timing(struct stm32_i2c_priv *i2c_priv,
|
|
return -EINVAL;
|
|
}
|
|
|
|
- if (setup->speed_freq > i2c_specs[setup->speed].rate) {
|
|
- pr_err("%s: Freq {%d/%d}\n", __func__,
|
|
- setup->speed_freq, i2c_specs[setup->speed].rate);
|
|
- return -EINVAL;
|
|
- }
|
|
-
|
|
INIT_LIST_HEAD(&solutions);
|
|
- ret = stm32_i2c_compute_solutions(setup, &solutions);
|
|
+ ret = stm32_i2c_compute_solutions(setup, specs, &solutions);
|
|
if (ret)
|
|
goto exit;
|
|
|
|
- ret = stm32_i2c_choose_solution(setup, &solutions, output);
|
|
+ ret = stm32_i2c_choose_solution(setup, specs, &solutions, output);
|
|
if (ret)
|
|
goto exit;
|
|
|
|
@@ -699,14 +700,24 @@ exit:
|
|
return ret;
|
|
}
|
|
|
|
+static u32 get_lower_rate(u32 rate)
|
|
+{
|
|
+ int i;
|
|
+
|
|
+ for (i = ARRAY_SIZE(i2c_specs) - 1; i >= 0; i--)
|
|
+ if (rate > i2c_specs[i].rate)
|
|
+ return i2c_specs[i].rate;
|
|
+
|
|
+ return i2c_specs[0].rate;
|
|
+}
|
|
+
|
|
static int stm32_i2c_setup_timing(struct stm32_i2c_priv *i2c_priv,
|
|
struct stm32_i2c_timings *timing)
|
|
{
|
|
struct stm32_i2c_setup *setup = i2c_priv->setup;
|
|
int ret = 0;
|
|
|
|
- setup->speed = i2c_priv->speed;
|
|
- setup->speed_freq = i2c_specs[setup->speed].rate;
|
|
+ setup->speed_freq = i2c_priv->speed;
|
|
setup->clock_src = clk_get_rate(&i2c_priv->clk);
|
|
|
|
if (!setup->clock_src) {
|
|
@@ -719,13 +730,11 @@ static int stm32_i2c_setup_timing(struct stm32_i2c_priv *i2c_priv,
|
|
if (ret) {
|
|
debug("%s: failed to compute I2C timings.\n",
|
|
__func__);
|
|
- if (i2c_priv->speed > STM32_I2C_SPEED_STANDARD) {
|
|
- i2c_priv->speed--;
|
|
- setup->speed = i2c_priv->speed;
|
|
+ if (setup->speed_freq > I2C_SPEED_STANDARD_RATE) {
|
|
setup->speed_freq =
|
|
- i2c_specs[setup->speed].rate;
|
|
+ get_lower_rate(setup->speed_freq);
|
|
debug("%s: downgrade I2C Speed Freq to (%i)\n",
|
|
- __func__, i2c_specs[setup->speed].rate);
|
|
+ __func__, setup->speed_freq);
|
|
} else {
|
|
break;
|
|
}
|
|
@@ -737,13 +746,15 @@ static int stm32_i2c_setup_timing(struct stm32_i2c_priv *i2c_priv,
|
|
return ret;
|
|
}
|
|
|
|
- debug("%s: I2C Speed(%i), Freq(%i), Clk Source(%i)\n", __func__,
|
|
- setup->speed, setup->speed_freq, setup->clock_src);
|
|
+ debug("%s: I2C Freq(%i), Clk Source(%i)\n", __func__,
|
|
+ setup->speed_freq, setup->clock_src);
|
|
debug("%s: I2C Rise(%i) and Fall(%i) Time\n", __func__,
|
|
setup->rise_time, setup->fall_time);
|
|
debug("%s: I2C Analog Filter(%s), DNF(%i)\n", __func__,
|
|
setup->analog_filter ? "On" : "Off", setup->dnf);
|
|
|
|
+ i2c_priv->speed = setup->speed_freq;
|
|
+
|
|
return 0;
|
|
}
|
|
|
|
@@ -783,21 +794,13 @@ static int stm32_i2c_set_bus_speed(struct udevice *bus, unsigned int speed)
|
|
{
|
|
struct stm32_i2c_priv *i2c_priv = dev_get_priv(bus);
|
|
|
|
- switch (speed) {
|
|
- case STANDARD_RATE:
|
|
- i2c_priv->speed = STM32_I2C_SPEED_STANDARD;
|
|
- break;
|
|
- case FAST_RATE:
|
|
- i2c_priv->speed = STM32_I2C_SPEED_FAST;
|
|
- break;
|
|
- case FAST_PLUS_RATE:
|
|
- i2c_priv->speed = STM32_I2C_SPEED_FAST_PLUS;
|
|
- break;
|
|
- default:
|
|
+ if (speed > I2C_SPEED_FAST_PLUS_RATE) {
|
|
debug("%s: Speed %d not supported\n", __func__, speed);
|
|
return -EINVAL;
|
|
}
|
|
|
|
+ i2c_priv->speed = speed;
|
|
+
|
|
return stm32_i2c_hw_config(i2c_priv);
|
|
}
|
|
|
|
@@ -867,6 +870,7 @@ static const struct dm_i2c_ops stm32_i2c_ops = {
|
|
|
|
static const struct udevice_id stm32_i2c_of_match[] = {
|
|
{ .compatible = "st,stm32f7-i2c", .data = (ulong)&stm32f7_setup },
|
|
+ { .compatible = "st,stm32mp15-i2c", .data = (ulong)&stm32f7_setup },
|
|
{}
|
|
};
|
|
|
|
diff --git a/drivers/mailbox/Kconfig b/drivers/mailbox/Kconfig
|
|
index 85c2a82..dbb3d81 100644
|
|
--- a/drivers/mailbox/Kconfig
|
|
+++ b/drivers/mailbox/Kconfig
|
|
@@ -47,4 +47,11 @@ config ZYNQMP_IPI
|
|
help
|
|
This enables support for the Xilinx ZynqMP Inter Processor Interrupt
|
|
communication controller.
|
|
+
|
|
+config ARM_SMC_MAILBOX
|
|
+ bool "Enable Arm SMC mailbox support"
|
|
+ depends on DM_MAILBOX && ARM_SMCCC
|
|
+ help
|
|
+ Mailbox notification through an Arm SMC or HVC calls.
|
|
+
|
|
endmenu
|
|
diff --git a/drivers/mailbox/Makefile b/drivers/mailbox/Makefile
|
|
index d2ace8c..7a56a45 100644
|
|
--- a/drivers/mailbox/Makefile
|
|
+++ b/drivers/mailbox/Makefile
|
|
@@ -3,6 +3,7 @@
|
|
# Copyright (c) 2016, NVIDIA CORPORATION.
|
|
#
|
|
|
|
+obj-$(CONFIG_ARM_SMC_MAILBOX) += arm-smc-mbox.o
|
|
obj-$(CONFIG_$(SPL_)DM_MAILBOX) += mailbox-uclass.o
|
|
obj-$(CONFIG_SANDBOX_MBOX) += sandbox-mbox.o
|
|
obj-$(CONFIG_SANDBOX_MBOX) += sandbox-mbox-test.o
|
|
diff --git a/drivers/mailbox/arm-smc-mbox.c b/drivers/mailbox/arm-smc-mbox.c
|
|
new file mode 100644
|
|
index 0000000..37f595a
|
|
--- /dev/null
|
|
+++ b/drivers/mailbox/arm-smc-mbox.c
|
|
@@ -0,0 +1,118 @@
|
|
+// SPDX-License-Identifier: GPL-2.0+
|
|
+/*
|
|
+ * Copyright (C) 2019, Linaro Limited
|
|
+ */
|
|
+
|
|
+#include <common.h>
|
|
+#include <dm.h>
|
|
+#include <mailbox-uclass.h>
|
|
+#include <linux/arm-smccc.h>
|
|
+
|
|
+#define ARM_SMC_METHOD 0
|
|
+#define ARM_HVC_METHOD 1
|
|
+
|
|
+typedef void (invoke_fn_t)(unsigned long);
|
|
+
|
|
+struct smc_pdata {
|
|
+ unsigned long func_id;
|
|
+ invoke_fn_t *invoke_fn;
|
|
+};
|
|
+
|
|
+/* Simple wrapper functions to be able to use a function pointer */
|
|
+static void smccc_smc(unsigned long a0)
|
|
+{
|
|
+ struct arm_smccc_res res;
|
|
+
|
|
+ arm_smccc_smc(a0, 0, 0, 0, 0, 0, 0, 0, &res);
|
|
+}
|
|
+
|
|
+static void smccc_hvc(unsigned long a0)
|
|
+{
|
|
+ struct arm_smccc_res res;
|
|
+
|
|
+ arm_smccc_hvc(a0, 0, 0, 0, 0, 0, 0, 0, &res);
|
|
+}
|
|
+
|
|
+static int smc_mbox_send(struct mbox_chan *chan, const void *data)
|
|
+{
|
|
+ struct smc_pdata *pdata = dev_get_platdata(chan->dev);
|
|
+
|
|
+ /*
|
|
+ * This mailbox invokes secure world for a channel event.
|
|
+ * Message is already in the channel's shared memory.
|
|
+ */
|
|
+ pdata->invoke_fn(pdata->func_id);
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+static int smc_mbox_recv(struct mbox_chan *chan, void *data)
|
|
+{
|
|
+ /* Mbox owner already got the return message from shared memory */
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+static int smc_mbox_request(struct mbox_chan *chan)
|
|
+{
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+static int smc_mbox_free(struct mbox_chan *chan)
|
|
+{
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+static int smc_mbox_of_xlate(struct mbox_chan *chan,
|
|
+ struct ofnode_phandle_args *args)
|
|
+{
|
|
+ if (args->args_count)
|
|
+ dev_warn(chan->dev, "Expect no argument to smc-mbox cells\n");
|
|
+
|
|
+ chan->id = 0;
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+static int smc_mbox_ofdata_to_platdata(struct udevice *dev)
|
|
+{
|
|
+ ulong compat_data = dev_get_driver_data(dev);
|
|
+ struct smc_pdata *pdata = dev_get_platdata(dev);
|
|
+ u32 func_id;
|
|
+
|
|
+ if (dev_read_u32(dev, "arm,func-id", &func_id)) {
|
|
+ dev_err(dev, "Missing property arm,func-id\n");
|
|
+ return -EINVAL;
|
|
+ }
|
|
+
|
|
+ pdata->func_id = func_id;
|
|
+
|
|
+ if (compat_data == ARM_SMC_METHOD)
|
|
+ pdata->invoke_fn = smccc_smc;
|
|
+ else
|
|
+ pdata->invoke_fn = smccc_hvc;
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+static const struct udevice_id smc_mbox_ids[] = {
|
|
+ { .compatible = "arm,smc-mbox", .data = ARM_SMC_METHOD, },
|
|
+ { .compatible = "arm,hvc-mbox", .data = ARM_HVC_METHOD, },
|
|
+ { }
|
|
+};
|
|
+
|
|
+struct mbox_ops smc_mbox_ops = {
|
|
+ .of_xlate = smc_mbox_of_xlate,
|
|
+ .request = smc_mbox_request,
|
|
+ .free = smc_mbox_free,
|
|
+ .send = smc_mbox_send,
|
|
+ .recv = smc_mbox_recv,
|
|
+};
|
|
+
|
|
+U_BOOT_DRIVER(smc_mbox) = {
|
|
+ .name = "arm_smc_mbox",
|
|
+ .id = UCLASS_MAILBOX,
|
|
+ .of_match = smc_mbox_ids,
|
|
+ .ofdata_to_platdata = smc_mbox_ofdata_to_platdata,
|
|
+ .platdata_auto_alloc_size = sizeof(struct smc_pdata),
|
|
+ .ops = &smc_mbox_ops,
|
|
+};
|
|
diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig
|
|
index 82bb093..547e144 100644
|
|
--- a/drivers/misc/Kconfig
|
|
+++ b/drivers/misc/Kconfig
|
|
@@ -439,4 +439,16 @@ config K3_AVS0
|
|
optimized voltage from the efuse, so that it can be programmed
|
|
to the PMIC on board.
|
|
|
|
+config SCMI_AGENT
|
|
+ bool "Enable SCMI support"
|
|
+ select OF_TRANSLATE
|
|
+ help
|
|
+ An SCMI agent communicates with a related SCMI server located
|
|
+ in another sub-system, as a companion micro controller or a
|
|
+ companion host in the CPU system.
|
|
+
|
|
+ Communications between agent (client) and the SCMI server are
|
|
+ based on message exchange, for example through a mailbox device
|
|
+ and some piece of identified shared memory.
|
|
+
|
|
endmenu
|
|
diff --git a/drivers/misc/Makefile b/drivers/misc/Makefile
|
|
index 55976d6..df7b3ed 100644
|
|
--- a/drivers/misc/Makefile
|
|
+++ b/drivers/misc/Makefile
|
|
@@ -68,3 +68,4 @@ obj-$(CONFIG_WINBOND_W83627) += winbond_w83627.o
|
|
obj-$(CONFIG_JZ4780_EFUSE) += jz4780_efuse.o
|
|
obj-$(CONFIG_MICROCHIP_FLEXCOM) += microchip_flexcom.o
|
|
obj-$(CONFIG_K3_AVS0) += k3_avs.o
|
|
+obj-$(CONFIG_SCMI_AGENT) += scmi_agent.o
|
|
diff --git a/drivers/misc/scmi_agent.c b/drivers/misc/scmi_agent.c
|
|
new file mode 100644
|
|
index 0000000..d36e460
|
|
--- /dev/null
|
|
+++ b/drivers/misc/scmi_agent.c
|
|
@@ -0,0 +1,337 @@
|
|
+// SPDX-License-Identifier: GPL-2.0+
|
|
+/*
|
|
+ * Copyright (c) 2015-2019, Arm Limited and Contributors. All rights reserved.
|
|
+ * Copyright (C) 2019 Linaro Limited.
|
|
+ */
|
|
+
|
|
+#include <common.h>
|
|
+#include <cpu_func.h>
|
|
+#include <asm/system.h>
|
|
+#include <asm/types.h>
|
|
+#include <dm.h>
|
|
+#include <dm/device-internal.h>
|
|
+#include <dm/lists.h>
|
|
+#include <dm/ofnode.h>
|
|
+#include <errno.h>
|
|
+#include <linux/errno.h>
|
|
+#include <linux/io.h>
|
|
+#include <linux/ioport.h>
|
|
+#include <mailbox.h>
|
|
+#include <memalign.h>
|
|
+#include <scmi_agent.h>
|
|
+#include <tee.h>
|
|
+
|
|
+struct error_code {
|
|
+ int scmi;
|
|
+ int errno;
|
|
+};
|
|
+
|
|
+static const struct error_code scmi_linux_errmap[] = {
|
|
+ { .scmi = SCMI_NOT_SUPPORTED, .errno = -EOPNOTSUPP, },
|
|
+ { .scmi = SCMI_INVALID_PARAMETERS, .errno = -EINVAL, },
|
|
+ { .scmi = SCMI_DENIED, .errno = -EACCES, },
|
|
+ { .scmi = SCMI_NOT_FOUND, .errno = -ENOENT, },
|
|
+ { .scmi = SCMI_OUT_OF_RANGE, .errno = -ERANGE, },
|
|
+ { .scmi = SCMI_BUSY, .errno = -EBUSY, },
|
|
+ { .scmi = SCMI_COMMS_ERROR, .errno = -ECOMM, },
|
|
+ { .scmi = SCMI_GENERIC_ERROR, .errno = -EIO, },
|
|
+ { .scmi = SCMI_HARDWARE_ERROR, .errno = -EREMOTEIO, },
|
|
+ { .scmi = SCMI_PROTOCOL_ERROR, .errno = -EPROTO, },
|
|
+};
|
|
+
|
|
+int scmi_to_linux_errno(int32_t scmi_code)
|
|
+{
|
|
+ int n;
|
|
+
|
|
+ if (scmi_code == 0)
|
|
+ return 0;
|
|
+
|
|
+ for (n = 0; n < ARRAY_SIZE(scmi_linux_errmap); n++)
|
|
+ if (scmi_code == scmi_linux_errmap[n].scmi)
|
|
+ return scmi_linux_errmap[1].errno;
|
|
+
|
|
+ return -EPROTO;
|
|
+}
|
|
+
|
|
+struct method_ops {
|
|
+ int (*process_msg)(struct udevice *dev, struct scmi_msg *msg);
|
|
+ int (*remove_agent)(struct udevice *dev);
|
|
+};
|
|
+
|
|
+struct scmi_agent {
|
|
+ struct method_ops *method_ops;
|
|
+ void *method_priv;
|
|
+};
|
|
+
|
|
+/*
|
|
+ * Shared Memory based Transport (SMT) message buffer management
|
|
+ *
|
|
+ * SMT uses 28 byte header prior message payload to handle the state of
|
|
+ * the communication channel realized by the shared memory area and
|
|
+ * to define SCMI protocol information the payload relates to.
|
|
+ */
|
|
+struct scmi_smt_header {
|
|
+ __le32 reserved;
|
|
+ __le32 channel_status;
|
|
+#define SCMI_SHMEM_CHAN_STAT_CHANNEL_ERROR BIT(1)
|
|
+#define SCMI_SHMEM_CHAN_STAT_CHANNEL_FREE BIT(0)
|
|
+ __le32 reserved1[2];
|
|
+ __le32 flags;
|
|
+#define SCMI_SHMEM_FLAG_INTR_ENABLED BIT(0)
|
|
+ __le32 length;
|
|
+ __le32 msg_header;
|
|
+ u8 msg_payload[0];
|
|
+};
|
|
+
|
|
+#define SMT_HEADER_TOKEN(token) (((token) << 18) & GENMASK(31, 18))
|
|
+#define SMT_HEADER_PROTOCOL_ID(proto) (((proto) << 10) & GENMASK(17, 10))
|
|
+#define SMT_HEADER_MESSAGE_TYPE(type) (((type) << 18) & GENMASK(9, 8))
|
|
+#define SMT_HEADER_MESSAGE_ID(id) ((id) & GENMASK(7, 0))
|
|
+
|
|
+struct scmi_shm_buf {
|
|
+ u8 *buf;
|
|
+ size_t size;
|
|
+};
|
|
+
|
|
+static int get_shm_buffer(struct udevice *dev, struct scmi_shm_buf *shm)
|
|
+{
|
|
+ int rc;
|
|
+ struct ofnode_phandle_args args;
|
|
+ struct resource resource;
|
|
+ fdt32_t faddr;
|
|
+ phys_addr_t paddr;
|
|
+
|
|
+ rc = dev_read_phandle_with_args(dev, "shmem", NULL, 0, 0, &args);
|
|
+ if (rc)
|
|
+ return rc;
|
|
+
|
|
+ rc = ofnode_read_resource(args.node, 0, &resource);
|
|
+ if (rc)
|
|
+ return rc;
|
|
+
|
|
+ faddr = cpu_to_fdt32(resource.start);
|
|
+ paddr = ofnode_translate_address(args.node, &faddr);
|
|
+
|
|
+ shm->size = resource_size(&resource);
|
|
+ if (shm->size < sizeof(struct scmi_smt_header)) {
|
|
+ dev_err(dev, "Shared memory buffer too small\n");
|
|
+ return -EINVAL;
|
|
+ }
|
|
+
|
|
+ shm->buf = devm_ioremap(dev, paddr, shm->size);
|
|
+ if (!shm->buf)
|
|
+ return -ENOMEM;
|
|
+
|
|
+ if (dcache_status())
|
|
+ mmu_set_region_dcache_behaviour((uintptr_t)shm->buf,
|
|
+ shm->size, DCACHE_OFF);
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+/*
|
|
+ * Mailbox support
|
|
+ */
|
|
+struct scmi_mbox_channel {
|
|
+ struct scmi_shm_buf shm_buf;
|
|
+ struct mbox_chan mbox;
|
|
+ ulong timeout_us;
|
|
+};
|
|
+
|
|
+static int mbox_process_msg(struct udevice *dev, struct scmi_msg *msg)
|
|
+{
|
|
+ struct scmi_agent *agent = dev_get_priv(dev);
|
|
+ struct scmi_mbox_channel *chan = agent->method_priv;
|
|
+ struct scmi_smt_header *hdr = (void *)chan->shm_buf.buf;
|
|
+ int rc;
|
|
+
|
|
+ /* Basic check-up */
|
|
+ if (!(hdr->channel_status & SCMI_SHMEM_CHAN_STAT_CHANNEL_FREE)) {
|
|
+ dev_dbg(dev, "Channel busy\n");
|
|
+ return -EBUSY;
|
|
+ }
|
|
+
|
|
+ if ((!msg->in_msg && msg->in_msg_sz) ||
|
|
+ (!msg->out_msg && msg->out_msg_sz))
|
|
+ return -EINVAL;
|
|
+
|
|
+ if (chan->shm_buf.size < (sizeof(*hdr) + msg->in_msg_sz) ||
|
|
+ chan->shm_buf.size < (sizeof(*hdr) + msg->out_msg_sz)) {
|
|
+ dev_dbg(dev, "Buffer too small\n");
|
|
+ return -ETOOSMALL;
|
|
+ }
|
|
+
|
|
+ /* Load message in shared memory */
|
|
+ hdr->channel_status &= ~SCMI_SHMEM_CHAN_STAT_CHANNEL_FREE;
|
|
+ hdr->length = msg->in_msg_sz + sizeof(hdr->msg_header);
|
|
+ hdr->msg_header = SMT_HEADER_TOKEN(0) |
|
|
+ SMT_HEADER_MESSAGE_TYPE(0) |
|
|
+ SMT_HEADER_PROTOCOL_ID(msg->protocol_id) |
|
|
+ SMT_HEADER_MESSAGE_ID(msg->message_id);
|
|
+
|
|
+ memcpy(hdr->msg_payload, msg->in_msg, msg->in_msg_sz);
|
|
+
|
|
+ /* Give shm addr to mbox in case it is meaningful */
|
|
+ rc = mbox_send(&chan->mbox, hdr);
|
|
+ if (rc) {
|
|
+ dev_err(dev, "Message send failed: %d\n", rc);
|
|
+ goto out;
|
|
+ }
|
|
+
|
|
+ /* Receive the response */
|
|
+ rc = mbox_recv(&chan->mbox, hdr, chan->timeout_us);
|
|
+ if (rc) {
|
|
+ dev_err(dev, "Response failed: %d, abort\n", rc);
|
|
+ goto out;
|
|
+ }
|
|
+
|
|
+ /* Check the statuses */
|
|
+ if (!(hdr->channel_status & SCMI_SHMEM_CHAN_STAT_CHANNEL_FREE)) {
|
|
+ dev_err(dev, "Channel unexpectedly busy, reset channel\n");
|
|
+ rc = -ECOMM;
|
|
+ goto out;
|
|
+ }
|
|
+
|
|
+ if (hdr->channel_status & SCMI_SHMEM_CHAN_STAT_CHANNEL_ERROR) {
|
|
+ dev_err(dev, "Channel error reported, reset channel\n");
|
|
+ rc = -ECOMM;
|
|
+ goto out;
|
|
+ }
|
|
+
|
|
+ if (hdr->length > msg->out_msg_sz + sizeof(hdr->msg_header)) {
|
|
+ dev_err(dev, "Buffer to small\n");
|
|
+ rc = -ETOOSMALL;
|
|
+ goto out;
|
|
+ }
|
|
+
|
|
+ /* Get the data */
|
|
+ msg->out_msg_sz = hdr->length - sizeof(hdr->msg_header);
|
|
+ memcpy(msg->out_msg, hdr->msg_payload, msg->out_msg_sz);
|
|
+
|
|
+out:
|
|
+ /* Free channel for further communication */
|
|
+ hdr->channel_status |= SCMI_SHMEM_CHAN_STAT_CHANNEL_FREE;
|
|
+ hdr->channel_status &= ~SCMI_SHMEM_CHAN_STAT_CHANNEL_ERROR;
|
|
+
|
|
+ return rc;
|
|
+}
|
|
+
|
|
+struct method_ops mbox_channel_ops = {
|
|
+ .process_msg = mbox_process_msg,
|
|
+};
|
|
+
|
|
+static int probe_smc_mailbox_channel(struct udevice *dev)
|
|
+{
|
|
+ struct scmi_agent *agent = dev_get_priv(dev);
|
|
+ struct scmi_mbox_channel *chan;
|
|
+ int rc;
|
|
+
|
|
+ chan = devm_kzalloc(dev, sizeof(*chan), GFP_KERNEL);
|
|
+ if (!chan)
|
|
+ return -ENOMEM;
|
|
+
|
|
+ chan->timeout_us = 10000;
|
|
+
|
|
+ rc = mbox_get_by_index(dev, 0, &chan->mbox);
|
|
+ if (rc) {
|
|
+ dev_err(dev, "Failed to find mailbox: %d\n", rc);
|
|
+ goto out;
|
|
+ }
|
|
+
|
|
+ rc = get_shm_buffer(dev, &chan->shm_buf);
|
|
+ if (rc)
|
|
+ dev_err(dev, "Failed to get shm resources: %d\n", rc);
|
|
+
|
|
+out:
|
|
+ if (rc) {
|
|
+ devm_kfree(dev, chan);
|
|
+ } else {
|
|
+ agent->method_ops = &mbox_channel_ops;
|
|
+ agent->method_priv = (void *)chan;
|
|
+ }
|
|
+
|
|
+ return rc;
|
|
+}
|
|
+
|
|
+/*
|
|
+ * Exported functions by the SCMI agent
|
|
+ */
|
|
+
|
|
+int scmi_agent_process_msg(struct udevice *dev, struct scmi_msg *msg)
|
|
+{
|
|
+ struct scmi_agent *agent = dev_get_priv(dev);
|
|
+
|
|
+ return agent->method_ops->process_msg(dev, msg);
|
|
+}
|
|
+
|
|
+static int scmi_agent_remove(struct udevice *dev)
|
|
+{
|
|
+ struct scmi_agent *agent = dev_get_priv(dev);
|
|
+
|
|
+ if (agent->method_ops->remove_agent)
|
|
+ return agent->method_ops->remove_agent(dev);
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+static int scmi_agent_probe(struct udevice *dev)
|
|
+{
|
|
+ /* Only mailbox method supported for now */
|
|
+ return probe_smc_mailbox_channel(dev);
|
|
+}
|
|
+
|
|
+static int scmi_agent_bind(struct udevice *dev)
|
|
+{
|
|
+ int rc = 0;
|
|
+ ofnode node;
|
|
+ struct driver *drv;
|
|
+
|
|
+ dev_for_each_subnode(node, dev) {
|
|
+ u32 protocol_id;
|
|
+
|
|
+ if (!ofnode_is_available(node))
|
|
+ continue;
|
|
+
|
|
+ if (ofnode_read_u32(node, "reg", &protocol_id))
|
|
+ continue;
|
|
+
|
|
+ switch (protocol_id) {
|
|
+ case SCMI_PROTOCOL_ID_CLOCK:
|
|
+ drv = DM_GET_DRIVER(scmi_clock);
|
|
+ break;
|
|
+ case SCMI_PROTOCOL_ID_RESET_DOMAIN:
|
|
+ drv = DM_GET_DRIVER(scmi_reset_domain);
|
|
+ break;
|
|
+ default:
|
|
+ dev_info(dev, "Ignore unsupported SCMI protocol %u\n",
|
|
+ protocol_id);
|
|
+ continue;
|
|
+ }
|
|
+
|
|
+ rc = device_bind_ofnode(dev, drv, ofnode_get_name(node),
|
|
+ NULL, node, NULL);
|
|
+ if (rc)
|
|
+ break;
|
|
+ }
|
|
+
|
|
+ if (rc)
|
|
+ device_unbind(dev);
|
|
+
|
|
+ return rc;
|
|
+}
|
|
+
|
|
+static const struct udevice_id scmi_agent_ids[] = {
|
|
+ { .compatible = "arm,scmi", },
|
|
+ { }
|
|
+};
|
|
+
|
|
+U_BOOT_DRIVER(scmi_agent) = {
|
|
+ .name = "scmi-agent",
|
|
+ .id = UCLASS_NOP,
|
|
+ .of_match = scmi_agent_ids,
|
|
+ .priv_auto_alloc_size = sizeof(struct scmi_agent),
|
|
+ .bind = scmi_agent_bind,
|
|
+ .probe = scmi_agent_probe,
|
|
+ .remove = scmi_agent_remove,
|
|
+ .flags = DM_FLAG_OS_PREPARE,
|
|
+};
|
|
diff --git a/drivers/mmc/stm32_sdmmc2.c b/drivers/mmc/stm32_sdmmc2.c
|
|
index 0a7a2fe..9ad0504 100644
|
|
--- a/drivers/mmc/stm32_sdmmc2.c
|
|
+++ b/drivers/mmc/stm32_sdmmc2.c
|
|
@@ -673,7 +673,7 @@ static int stm32_sdmmc2_probe(struct udevice *dev)
|
|
cfg->f_max = dev_read_u32_default(dev, "max-frequency", 52000000);
|
|
cfg->voltages = MMC_VDD_32_33 | MMC_VDD_33_34 | MMC_VDD_165_195;
|
|
cfg->b_max = CONFIG_SYS_MMC_MAX_BLK_COUNT;
|
|
- cfg->name = "STM32 SDMMC2";
|
|
+ cfg->name = "STM32 SD/MMC";
|
|
|
|
cfg->host_caps = 0;
|
|
if (cfg->f_max > 25000000)
|
|
diff --git a/drivers/mtd/Kconfig b/drivers/mtd/Kconfig
|
|
index 5e7571c..348b43e 100644
|
|
--- a/drivers/mtd/Kconfig
|
|
+++ b/drivers/mtd/Kconfig
|
|
@@ -22,6 +22,13 @@ config MTD_NOR_FLASH
|
|
help
|
|
Enable support for parallel NOR flash.
|
|
|
|
+config SYS_MTDPARTS_RUNTIME
|
|
+ bool "Allow MTDPARTS to be configured at runtime"
|
|
+ depends on MTD
|
|
+ help
|
|
+ This option allows to call the function board_mtdparts_default to
|
|
+ dynamically build the variables mtdids and mtdparts at runtime.
|
|
+
|
|
config FLASH_CFI_DRIVER
|
|
bool "Enable CFI Flash driver"
|
|
help
|
|
diff --git a/drivers/net/dwc_eth_qos.c b/drivers/net/dwc_eth_qos.c
|
|
index 4632111..fad7810 100644
|
|
--- a/drivers/net/dwc_eth_qos.c
|
|
+++ b/drivers/net/dwc_eth_qos.c
|
|
@@ -305,6 +305,8 @@ struct eqos_priv {
|
|
struct clk clk_slave_bus;
|
|
struct mii_dev *mii;
|
|
struct phy_device *phy;
|
|
+ int phyaddr;
|
|
+ u32 max_speed;
|
|
void *descs;
|
|
struct eqos_desc *tx_descs;
|
|
struct eqos_desc *rx_descs;
|
|
@@ -693,6 +695,29 @@ static int eqos_start_resets_tegra186(struct udevice *dev)
|
|
|
|
static int eqos_start_resets_stm32(struct udevice *dev)
|
|
{
|
|
+ struct eqos_priv *eqos = dev_get_priv(dev);
|
|
+ int ret;
|
|
+
|
|
+ debug("%s(dev=%p):\n", __func__, dev);
|
|
+ if (dm_gpio_is_valid(&eqos->phy_reset_gpio)) {
|
|
+ ret = dm_gpio_set_value(&eqos->phy_reset_gpio, 1);
|
|
+ if (ret < 0) {
|
|
+ pr_err("dm_gpio_set_value(phy_reset, assert) failed: %d",
|
|
+ ret);
|
|
+ return ret;
|
|
+ }
|
|
+
|
|
+ udelay(2);
|
|
+
|
|
+ ret = dm_gpio_set_value(&eqos->phy_reset_gpio, 0);
|
|
+ if (ret < 0) {
|
|
+ pr_err("dm_gpio_set_value(phy_reset, deassert) failed: %d",
|
|
+ ret);
|
|
+ return ret;
|
|
+ }
|
|
+ }
|
|
+ debug("%s: OK\n", __func__);
|
|
+
|
|
return 0;
|
|
}
|
|
|
|
@@ -708,6 +733,18 @@ static int eqos_stop_resets_tegra186(struct udevice *dev)
|
|
|
|
static int eqos_stop_resets_stm32(struct udevice *dev)
|
|
{
|
|
+ struct eqos_priv *eqos = dev_get_priv(dev);
|
|
+ int ret;
|
|
+
|
|
+ if (dm_gpio_is_valid(&eqos->phy_reset_gpio)) {
|
|
+ ret = dm_gpio_set_value(&eqos->phy_reset_gpio, 1);
|
|
+ if (ret < 0) {
|
|
+ pr_err("dm_gpio_set_value(phy_reset, assert) failed: %d",
|
|
+ ret);
|
|
+ return ret;
|
|
+ }
|
|
+ }
|
|
+
|
|
return 0;
|
|
}
|
|
|
|
@@ -1045,12 +1082,21 @@ static int eqos_start(struct udevice *dev)
|
|
* don't need to reconnect/reconfigure again
|
|
*/
|
|
if (!eqos->phy) {
|
|
- eqos->phy = phy_connect(eqos->mii, -1, dev,
|
|
+ eqos->phy = phy_connect(eqos->mii, eqos->phyaddr, dev,
|
|
eqos->config->interface(dev));
|
|
if (!eqos->phy) {
|
|
pr_err("phy_connect() failed");
|
|
goto err_stop_resets;
|
|
}
|
|
+
|
|
+ if (eqos->max_speed) {
|
|
+ ret = phy_set_supported(eqos->phy, eqos->max_speed);
|
|
+ if (ret) {
|
|
+ pr_err("phy_set_supported() failed: %d", ret);
|
|
+ goto err_shutdown_phy;
|
|
+ }
|
|
+ }
|
|
+
|
|
ret = phy_config(eqos->phy);
|
|
if (ret < 0) {
|
|
pr_err("phy_config() failed: %d", ret);
|
|
@@ -1603,6 +1649,9 @@ static int eqos_probe_resources_stm32(struct udevice *dev)
|
|
struct eqos_priv *eqos = dev_get_priv(dev);
|
|
int ret;
|
|
phy_interface_t interface;
|
|
+ struct ofnode_phandle_args phandle_args;
|
|
+ /* Hardcode for now */
|
|
+ eqos->phyaddr = -1;
|
|
|
|
debug("%s(dev=%p):\n", __func__, dev);
|
|
|
|
@@ -1617,6 +1666,8 @@ static int eqos_probe_resources_stm32(struct udevice *dev)
|
|
if (ret)
|
|
return -EINVAL;
|
|
|
|
+ eqos->max_speed = dev_read_u32_default(dev, "max-speed", 0);
|
|
+
|
|
ret = clk_get_by_name(dev, "stmmaceth", &eqos->clk_master_bus);
|
|
if (ret) {
|
|
pr_err("clk_get_by_name(master_bus) failed: %d", ret);
|
|
@@ -1640,6 +1691,23 @@ static int eqos_probe_resources_stm32(struct udevice *dev)
|
|
if (ret)
|
|
pr_warn("No phy clock provided %d", ret);
|
|
|
|
+ ret = dev_read_phandle_with_args(dev, "phy-handle", NULL, 0, 0,
|
|
+ &phandle_args);
|
|
+ if (!ret) {
|
|
+ /* search "reset-gpios" in phy node */
|
|
+ ret = gpio_request_by_name_nodev(phandle_args.node,
|
|
+ "reset-gpios", 0,
|
|
+ &eqos->phy_reset_gpio,
|
|
+ GPIOD_IS_OUT |
|
|
+ GPIOD_IS_OUT_ACTIVE);
|
|
+ if (ret)
|
|
+ pr_warn("gpio_request_by_name(phy reset) not provided %d",
|
|
+ ret);
|
|
+
|
|
+ eqos->phyaddr = ofnode_read_u32_default(phandle_args.node,
|
|
+ "reg", -1);
|
|
+ }
|
|
+
|
|
debug("%s: OK\n", __func__);
|
|
return 0;
|
|
|
|
@@ -1703,6 +1771,9 @@ static int eqos_remove_resources_stm32(struct udevice *dev)
|
|
if (clk_valid(&eqos->clk_ck))
|
|
clk_free(&eqos->clk_ck);
|
|
|
|
+ if (dm_gpio_is_valid(&eqos->phy_reset_gpio))
|
|
+ dm_gpio_free(dev, &eqos->phy_reset_gpio);
|
|
+
|
|
debug("%s: OK\n", __func__);
|
|
return 0;
|
|
}
|
|
diff --git a/drivers/phy/phy-stm32-usbphyc.c b/drivers/phy/phy-stm32-usbphyc.c
|
|
index 6f11190..c122608 100644
|
|
--- a/drivers/phy/phy-stm32-usbphyc.c
|
|
+++ b/drivers/phy/phy-stm32-usbphyc.c
|
|
@@ -260,7 +260,7 @@ static int stm32_usbphyc_phy_power_off(struct phy *phy)
|
|
return 0;
|
|
|
|
if (usbphyc_phy->vdd) {
|
|
- ret = regulator_set_enable(usbphyc_phy->vdd, false);
|
|
+ ret = regulator_set_enable_if_allowed(usbphyc_phy->vdd, false);
|
|
if (ret)
|
|
return ret;
|
|
}
|
|
diff --git a/drivers/phy/phy-uclass.c b/drivers/phy/phy-uclass.c
|
|
index e201a90..363985b 100644
|
|
--- a/drivers/phy/phy-uclass.c
|
|
+++ b/drivers/phy/phy-uclass.c
|
|
@@ -109,56 +109,86 @@ int generic_phy_get_by_name(struct udevice *dev, const char *phy_name,
|
|
int generic_phy_init(struct phy *phy)
|
|
{
|
|
struct phy_ops const *ops;
|
|
+ int ret;
|
|
|
|
if (!phy)
|
|
return 0;
|
|
ops = phy_dev_ops(phy->dev);
|
|
|
|
- return ops->init ? ops->init(phy) : 0;
|
|
+ ret = ops->init ? ops->init(phy) : 0;
|
|
+ if (ret)
|
|
+ dev_err(phy->dev, "PHY: Failed to init %s: %d.\n",
|
|
+ phy->dev->name, ret);
|
|
+
|
|
+ return ret;
|
|
}
|
|
|
|
int generic_phy_reset(struct phy *phy)
|
|
{
|
|
struct phy_ops const *ops;
|
|
+ int ret;
|
|
|
|
if (!phy)
|
|
return 0;
|
|
ops = phy_dev_ops(phy->dev);
|
|
|
|
- return ops->reset ? ops->reset(phy) : 0;
|
|
+ ret = ops->reset ? ops->reset(phy) : 0;
|
|
+ if (ret)
|
|
+ dev_err(phy->dev, "PHY: Failed to reset %s: %d.\n",
|
|
+ phy->dev->name, ret);
|
|
+
|
|
+ return ret;
|
|
}
|
|
|
|
int generic_phy_exit(struct phy *phy)
|
|
{
|
|
struct phy_ops const *ops;
|
|
+ int ret;
|
|
|
|
if (!phy)
|
|
return 0;
|
|
ops = phy_dev_ops(phy->dev);
|
|
|
|
- return ops->exit ? ops->exit(phy) : 0;
|
|
+ ret = ops->exit ? ops->exit(phy) : 0;
|
|
+ if (ret)
|
|
+ dev_err(phy->dev, "PHY: Failed to exit %s: %d.\n",
|
|
+ phy->dev->name, ret);
|
|
+
|
|
+ return ret;
|
|
}
|
|
|
|
int generic_phy_power_on(struct phy *phy)
|
|
{
|
|
struct phy_ops const *ops;
|
|
+ int ret;
|
|
|
|
if (!phy)
|
|
return 0;
|
|
ops = phy_dev_ops(phy->dev);
|
|
|
|
- return ops->power_on ? ops->power_on(phy) : 0;
|
|
+ ret = ops->power_on ? ops->power_on(phy) : 0;
|
|
+ if (ret)
|
|
+ dev_err(phy->dev, "PHY: Failed to power on %s: %d.\n",
|
|
+ phy->dev->name, ret);
|
|
+
|
|
+ return ret;
|
|
}
|
|
|
|
int generic_phy_power_off(struct phy *phy)
|
|
{
|
|
struct phy_ops const *ops;
|
|
+ int ret;
|
|
|
|
if (!phy)
|
|
return 0;
|
|
ops = phy_dev_ops(phy->dev);
|
|
|
|
- return ops->power_off ? ops->power_off(phy) : 0;
|
|
+ ret = ops->power_off ? ops->power_off(phy) : 0;
|
|
+ if (ret)
|
|
+ dev_err(phy->dev, "PHY: Failed to power off %s: %d.\n",
|
|
+ phy->dev->name, ret);
|
|
+
|
|
+ return ret;
|
|
}
|
|
|
|
UCLASS_DRIVER(phy) = {
|
|
diff --git a/drivers/pinctrl/pinctrl-generic.c b/drivers/pinctrl/pinctrl-generic.c
|
|
index eecf0f5..9c4f73b 100644
|
|
--- a/drivers/pinctrl/pinctrl-generic.c
|
|
+++ b/drivers/pinctrl/pinctrl-generic.c
|
|
@@ -8,8 +8,6 @@
|
|
#include <linux/compat.h>
|
|
#include <dm/pinctrl.h>
|
|
|
|
-DECLARE_GLOBAL_DATA_PTR;
|
|
-
|
|
/**
|
|
* pinctrl_pin_name_to_selector() - return the pin selector for a pin
|
|
*
|
|
@@ -243,18 +241,14 @@ static int pinctrl_generic_set_state_one(struct udevice *dev,
|
|
struct udevice *config,
|
|
bool is_group, unsigned selector)
|
|
{
|
|
- const void *fdt = gd->fdt_blob;
|
|
- int node_offset = dev_of_offset(config);
|
|
const char *propname;
|
|
const void *value;
|
|
- int prop_offset, len, func_selector, param, ret;
|
|
+ struct ofprop property;
|
|
+ int len, func_selector, param, ret;
|
|
u32 arg, default_val;
|
|
|
|
- for (prop_offset = fdt_first_property_offset(fdt, node_offset);
|
|
- prop_offset > 0;
|
|
- prop_offset = fdt_next_property_offset(fdt, prop_offset)) {
|
|
- value = fdt_getprop_by_offset(fdt, prop_offset,
|
|
- &propname, &len);
|
|
+ dev_for_each_property(property, config) {
|
|
+ value = dev_read_prop_by_prop(&property, &propname, &len);
|
|
if (!value)
|
|
return -EINVAL;
|
|
|
|
@@ -298,19 +292,17 @@ static int pinctrl_generic_set_state_one(struct udevice *dev,
|
|
static int pinctrl_generic_set_state_subnode(struct udevice *dev,
|
|
struct udevice *config)
|
|
{
|
|
- const void *fdt = gd->fdt_blob;
|
|
- int node = dev_of_offset(config);
|
|
const char *subnode_target_type = "pins";
|
|
bool is_group = false;
|
|
const char *name;
|
|
int strings_count, selector, i, ret;
|
|
|
|
- strings_count = fdt_stringlist_count(fdt, node, subnode_target_type);
|
|
+ strings_count = dev_read_string_count(config, subnode_target_type);
|
|
if (strings_count < 0) {
|
|
subnode_target_type = "groups";
|
|
is_group = true;
|
|
- strings_count = fdt_stringlist_count(fdt, node,
|
|
- subnode_target_type);
|
|
+ strings_count = dev_read_string_count(config,
|
|
+ subnode_target_type);
|
|
if (strings_count < 0) {
|
|
/* skip this node; may contain config child nodes */
|
|
return 0;
|
|
@@ -318,10 +310,10 @@ static int pinctrl_generic_set_state_subnode(struct udevice *dev,
|
|
}
|
|
|
|
for (i = 0; i < strings_count; i++) {
|
|
- name = fdt_stringlist_get(fdt, node, subnode_target_type, i,
|
|
- NULL);
|
|
- if (!name)
|
|
- return -EINVAL;
|
|
+ ret = dev_read_string_index(config, subnode_target_type, i,
|
|
+ &name);
|
|
+ if (ret)
|
|
+ return ret;
|
|
|
|
if (is_group)
|
|
selector = pinctrl_group_name_to_selector(dev, name);
|
|
diff --git a/drivers/pinctrl/pinctrl-sandbox.c b/drivers/pinctrl/pinctrl-sandbox.c
|
|
index 0786afe..3ee75fb 100644
|
|
--- a/drivers/pinctrl/pinctrl-sandbox.c
|
|
+++ b/drivers/pinctrl/pinctrl-sandbox.c
|
|
@@ -14,7 +14,11 @@ static const char * const sandbox_pins[] = {
|
|
"SDA",
|
|
"TX",
|
|
"RX",
|
|
- "W1"
|
|
+ "W1",
|
|
+ "GPIO0",
|
|
+ "GPIO1",
|
|
+ "GPIO2",
|
|
+ "GPIO3",
|
|
};
|
|
|
|
static const char * const sandbox_pins_muxing[] = {
|
|
@@ -23,6 +27,10 @@ static const char * const sandbox_pins_muxing[] = {
|
|
"Uart TX",
|
|
"Uart RX",
|
|
"1-wire gpio",
|
|
+ "gpio",
|
|
+ "gpio",
|
|
+ "gpio",
|
|
+ "gpio",
|
|
};
|
|
|
|
static const char * const sandbox_groups[] = {
|
|
@@ -38,6 +46,10 @@ static const char * const sandbox_functions[] = {
|
|
"serial",
|
|
"spi",
|
|
"w1",
|
|
+ "gpio",
|
|
+ "gpio",
|
|
+ "gpio",
|
|
+ "gpio",
|
|
};
|
|
|
|
static const struct pinconf_param sandbox_conf_params[] = {
|
|
@@ -54,6 +66,10 @@ static const struct pinconf_param sandbox_conf_params[] = {
|
|
{ "input-disable", PIN_CONFIG_INPUT_ENABLE, 0 },
|
|
};
|
|
|
|
+/* bitfield used to save param and value of each pin/selector */
|
|
+static unsigned int sandbox_pins_param[ARRAY_SIZE(sandbox_pins)];
|
|
+static unsigned int sandbox_pins_value[ARRAY_SIZE(sandbox_pins)];
|
|
+
|
|
static int sandbox_get_pins_count(struct udevice *dev)
|
|
{
|
|
return ARRAY_SIZE(sandbox_pins);
|
|
@@ -68,8 +84,25 @@ static int sandbox_get_pin_muxing(struct udevice *dev,
|
|
unsigned int selector,
|
|
char *buf, int size)
|
|
{
|
|
+ const struct pinconf_param *p;
|
|
+ int i;
|
|
+
|
|
snprintf(buf, size, "%s", sandbox_pins_muxing[selector]);
|
|
|
|
+ if (sandbox_pins_param[selector]) {
|
|
+ for (i = 0, p = sandbox_conf_params;
|
|
+ i < ARRAY_SIZE(sandbox_conf_params);
|
|
+ i++, p++) {
|
|
+ if ((sandbox_pins_param[selector] & BIT(p->param)) &&
|
|
+ (!!(sandbox_pins_value[selector] & BIT(p->param)) ==
|
|
+ p->default_value)) {
|
|
+ strncat(buf, " ", size);
|
|
+ strncat(buf, p->property, size);
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+ strncat(buf, ".", size);
|
|
+
|
|
return 0;
|
|
}
|
|
|
|
@@ -102,6 +135,9 @@ static int sandbox_pinmux_set(struct udevice *dev, unsigned pin_selector,
|
|
pin_selector, sandbox_get_pin_name(dev, pin_selector),
|
|
func_selector, sandbox_get_function_name(dev, func_selector));
|
|
|
|
+ sandbox_pins_param[pin_selector] = 0;
|
|
+ sandbox_pins_value[pin_selector] = 0;
|
|
+
|
|
return 0;
|
|
}
|
|
|
|
@@ -123,6 +159,12 @@ static int sandbox_pinconf_set(struct udevice *dev, unsigned pin_selector,
|
|
pin_selector, sandbox_get_pin_name(dev, pin_selector),
|
|
param, argument);
|
|
|
|
+ sandbox_pins_param[pin_selector] |= BIT(param);
|
|
+ if (argument)
|
|
+ sandbox_pins_value[pin_selector] |= BIT(param);
|
|
+ else
|
|
+ sandbox_pins_value[pin_selector] &= ~BIT(param);
|
|
+
|
|
return 0;
|
|
}
|
|
|
|
diff --git a/drivers/pinctrl/pinctrl-single.c b/drivers/pinctrl/pinctrl-single.c
|
|
index 1dfc97d..6d8f989 100644
|
|
--- a/drivers/pinctrl/pinctrl-single.c
|
|
+++ b/drivers/pinctrl/pinctrl-single.c
|
|
@@ -9,8 +9,6 @@
|
|
#include <linux/libfdt.h>
|
|
#include <asm/io.h>
|
|
|
|
-DECLARE_GLOBAL_DATA_PTR;
|
|
-
|
|
struct single_pdata {
|
|
fdt_addr_t base; /* first configuration register */
|
|
int offset; /* index of last configuration register */
|
|
@@ -117,13 +115,11 @@ static int single_configure_bits(struct udevice *dev,
|
|
static int single_set_state(struct udevice *dev,
|
|
struct udevice *config)
|
|
{
|
|
- const void *fdt = gd->fdt_blob;
|
|
const struct single_fdt_pin_cfg *prop;
|
|
const struct single_fdt_bits_cfg *prop_bits;
|
|
int len;
|
|
|
|
- prop = fdt_getprop(fdt, dev_of_offset(config), "pinctrl-single,pins",
|
|
- &len);
|
|
+ prop = dev_read_prop(dev, "pinctrl-single,pins", &len);
|
|
|
|
if (prop) {
|
|
dev_dbg(dev, "configuring pins for %s\n", config->name);
|
|
@@ -136,9 +132,7 @@ static int single_set_state(struct udevice *dev,
|
|
}
|
|
|
|
/* pinctrl-single,pins not found so check for pinctrl-single,bits */
|
|
- prop_bits = fdt_getprop(fdt, dev_of_offset(config),
|
|
- "pinctrl-single,bits",
|
|
- &len);
|
|
+ prop_bits = dev_read_prop(dev, "pinctrl-single,bits", &len);
|
|
if (prop_bits) {
|
|
dev_dbg(dev, "configuring pins for %s\n", config->name);
|
|
if (len % sizeof(struct single_fdt_bits_cfg)) {
|
|
@@ -160,27 +154,24 @@ static int single_ofdata_to_platdata(struct udevice *dev)
|
|
int res;
|
|
struct single_pdata *pdata = dev->platdata;
|
|
|
|
- pdata->width = fdtdec_get_int(gd->fdt_blob, dev_of_offset(dev),
|
|
- "pinctrl-single,register-width", 0);
|
|
+ pdata->width =
|
|
+ dev_read_u32_default(dev, "pinctrl-single,register-width", 0);
|
|
|
|
- res = fdtdec_get_int_array(gd->fdt_blob, dev_of_offset(dev),
|
|
- "reg", of_reg, 2);
|
|
+ res = dev_read_u32_array(dev, "reg", of_reg, 2);
|
|
if (res)
|
|
return res;
|
|
pdata->offset = of_reg[1] - pdata->width / 8;
|
|
|
|
- addr = devfdt_get_addr(dev);
|
|
+ addr = dev_read_addr(dev);
|
|
if (addr == FDT_ADDR_T_NONE) {
|
|
dev_dbg(dev, "no valid base register address\n");
|
|
return -EINVAL;
|
|
}
|
|
pdata->base = addr;
|
|
|
|
- pdata->mask = fdtdec_get_int(gd->fdt_blob, dev_of_offset(dev),
|
|
- "pinctrl-single,function-mask",
|
|
- 0xffffffff);
|
|
- pdata->bits_per_mux = fdtdec_get_bool(gd->fdt_blob, dev_of_offset(dev),
|
|
- "pinctrl-single,bit-per-mux");
|
|
+ pdata->mask = dev_read_u32_default(dev, "pinctrl-single,function-mask",
|
|
+ 0xffffffff);
|
|
+ pdata->bits_per_mux = dev_read_bool(dev, "pinctrl-single,bit-per-mux");
|
|
|
|
return 0;
|
|
}
|
|
diff --git a/drivers/pinctrl/pinctrl-stmfx.c b/drivers/pinctrl/pinctrl-stmfx.c
|
|
index 0b5a043..b7987d5 100644
|
|
--- a/drivers/pinctrl/pinctrl-stmfx.c
|
|
+++ b/drivers/pinctrl/pinctrl-stmfx.c
|
|
@@ -71,17 +71,61 @@ static int stmfx_write(struct udevice *dev, uint offset, unsigned int val)
|
|
return dm_i2c_reg_write(dev_get_parent(dev), offset, val);
|
|
}
|
|
|
|
-static int stmfx_gpio_get(struct udevice *dev, unsigned int offset)
|
|
+static int stmfx_read_reg(struct udevice *dev, u8 reg_base, uint offset)
|
|
{
|
|
- u32 reg = STMFX_REG_GPIO_STATE + get_reg(offset);
|
|
+ u8 reg = reg_base + get_reg(offset);
|
|
u32 mask = get_mask(offset);
|
|
int ret;
|
|
|
|
ret = stmfx_read(dev, reg);
|
|
+ if (ret < 0)
|
|
+ return ret;
|
|
|
|
return ret < 0 ? ret : !!(ret & mask);
|
|
}
|
|
|
|
+static int stmfx_write_reg(struct udevice *dev, u8 reg_base, uint offset,
|
|
+ uint val)
|
|
+{
|
|
+ u8 reg = reg_base + get_reg(offset);
|
|
+ u32 mask = get_mask(offset);
|
|
+ int ret;
|
|
+
|
|
+ ret = stmfx_read(dev, reg);
|
|
+ if (ret < 0)
|
|
+ return ret;
|
|
+ ret = (ret & ~mask) | (val ? mask : 0);
|
|
+
|
|
+ return stmfx_write(dev, reg, ret);
|
|
+}
|
|
+
|
|
+static int stmfx_conf_set_pupd(struct udevice *dev,
|
|
+ unsigned int offset, uint pupd)
|
|
+{
|
|
+ return stmfx_write_reg(dev, STMFX_REG_GPIO_PUPD, offset, pupd);
|
|
+}
|
|
+
|
|
+static int stmfx_conf_get_pupd(struct udevice *dev, unsigned int offset)
|
|
+{
|
|
+ return stmfx_read_reg(dev, STMFX_REG_GPIO_PUPD, offset);
|
|
+}
|
|
+
|
|
+static int stmfx_conf_set_type(struct udevice *dev,
|
|
+ unsigned int offset, uint type)
|
|
+{
|
|
+ return stmfx_write_reg(dev, STMFX_REG_GPIO_TYPE, offset, type);
|
|
+}
|
|
+
|
|
+static int stmfx_conf_get_type(struct udevice *dev, unsigned int offset)
|
|
+{
|
|
+ return stmfx_read_reg(dev, STMFX_REG_GPIO_TYPE, offset);
|
|
+}
|
|
+
|
|
+static int stmfx_gpio_get(struct udevice *dev, unsigned int offset)
|
|
+{
|
|
+ return stmfx_read_reg(dev, STMFX_REG_GPIO_STATE, offset);
|
|
+}
|
|
+
|
|
static int stmfx_gpio_set(struct udevice *dev, unsigned int offset, int value)
|
|
{
|
|
u32 reg = value ? STMFX_REG_GPO_SET : STMFX_REG_GPO_CLR;
|
|
@@ -92,50 +136,103 @@ static int stmfx_gpio_set(struct udevice *dev, unsigned int offset, int value)
|
|
|
|
static int stmfx_gpio_get_function(struct udevice *dev, unsigned int offset)
|
|
{
|
|
- u32 reg = STMFX_REG_GPIO_DIR + get_reg(offset);
|
|
- u32 mask = get_mask(offset);
|
|
- int ret;
|
|
-
|
|
- ret = stmfx_read(dev, reg);
|
|
+ int ret = stmfx_read_reg(dev, STMFX_REG_GPIO_DIR, offset);
|
|
|
|
if (ret < 0)
|
|
return ret;
|
|
/* On stmfx, gpio pins direction is (0)input, (1)output. */
|
|
|
|
- return ret & mask ? GPIOF_OUTPUT : GPIOF_INPUT;
|
|
+ return ret ? GPIOF_OUTPUT : GPIOF_INPUT;
|
|
}
|
|
|
|
static int stmfx_gpio_direction_input(struct udevice *dev, unsigned int offset)
|
|
{
|
|
- u32 reg = STMFX_REG_GPIO_DIR + get_reg(offset);
|
|
- u32 mask = get_mask(offset);
|
|
- int ret;
|
|
+ return stmfx_write_reg(dev, STMFX_REG_GPIO_DIR, offset, 0);
|
|
+}
|
|
|
|
- ret = stmfx_read(dev, reg);
|
|
+static int stmfx_gpio_direction_output(struct udevice *dev,
|
|
+ unsigned int offset, int value)
|
|
+{
|
|
+ int ret = stmfx_gpio_set(dev, offset, value);
|
|
if (ret < 0)
|
|
return ret;
|
|
|
|
- ret &= ~mask;
|
|
+ return stmfx_write_reg(dev, STMFX_REG_GPIO_DIR, offset, 1);
|
|
+}
|
|
|
|
- return stmfx_write(dev, reg, ret & ~mask);
|
|
+static int stmfx_gpio_set_dir_flags(struct udevice *dev, unsigned int offset,
|
|
+ ulong flags)
|
|
+{
|
|
+ int ret = -ENOTSUPP;
|
|
+
|
|
+ if (flags & GPIOD_IS_OUT) {
|
|
+ if (flags & GPIOD_OPEN_SOURCE)
|
|
+ return -ENOTSUPP;
|
|
+ if (flags & GPIOD_OPEN_DRAIN)
|
|
+ ret = stmfx_conf_set_type(dev, offset, 0);
|
|
+ else /* PUSH-PULL */
|
|
+ ret = stmfx_conf_set_type(dev, offset, 1);
|
|
+ if (ret)
|
|
+ return ret;
|
|
+ ret = stmfx_gpio_direction_output(dev, offset,
|
|
+ GPIOD_FLAGS_OUTPUT(flags));
|
|
+ } else if (flags & GPIOD_IS_IN) {
|
|
+ ret = stmfx_gpio_direction_input(dev, offset);
|
|
+ if (ret)
|
|
+ return ret;
|
|
+ if (flags & GPIOD_PULL_UP) {
|
|
+ ret = stmfx_conf_set_type(dev, offset, 1);
|
|
+ if (ret)
|
|
+ return ret;
|
|
+ ret = stmfx_conf_set_pupd(dev, offset, 1);
|
|
+ } else if (flags & GPIOD_PULL_DOWN) {
|
|
+ ret = stmfx_conf_set_type(dev, offset, 1);
|
|
+ if (ret)
|
|
+ return ret;
|
|
+ ret = stmfx_conf_set_pupd(dev, offset, 0);
|
|
+ }
|
|
+ }
|
|
+
|
|
+ return ret;
|
|
}
|
|
|
|
-static int stmfx_gpio_direction_output(struct udevice *dev,
|
|
- unsigned int offset, int value)
|
|
+static int stmfx_gpio_get_dir_flags(struct udevice *dev, unsigned int offset,
|
|
+ ulong *flags)
|
|
{
|
|
- u32 reg = STMFX_REG_GPIO_DIR + get_reg(offset);
|
|
- u32 mask = get_mask(offset);
|
|
+ ulong dir_flags = 0;
|
|
int ret;
|
|
|
|
- ret = stmfx_gpio_set(dev, offset, value);
|
|
- if (ret < 0)
|
|
- return ret;
|
|
-
|
|
- ret = stmfx_read(dev, reg);
|
|
- if (ret < 0)
|
|
- return ret;
|
|
+ if (stmfx_gpio_get_function(dev, offset) == GPIOF_OUTPUT) {
|
|
+ dir_flags |= GPIOD_IS_OUT;
|
|
+ ret = stmfx_conf_get_type(dev, offset);
|
|
+ if (ret < 0)
|
|
+ return ret;
|
|
+ if (ret == 0)
|
|
+ dir_flags |= GPIOD_OPEN_DRAIN;
|
|
+ /* 1 = push-pull (default), open source not supported */
|
|
+ ret = stmfx_gpio_get(dev, offset);
|
|
+ if (ret < 0)
|
|
+ return ret;
|
|
+ if (ret)
|
|
+ dir_flags |= GPIOD_IS_OUT_ACTIVE;
|
|
+ } else {
|
|
+ dir_flags |= GPIOD_IS_IN;
|
|
+ ret = stmfx_conf_get_type(dev, offset);
|
|
+ if (ret < 0)
|
|
+ return ret;
|
|
+ if (ret == 1) {
|
|
+ ret = stmfx_conf_get_pupd(dev, offset);
|
|
+ if (ret < 0)
|
|
+ return ret;
|
|
+ if (ret == 1)
|
|
+ dir_flags |= GPIOD_PULL_UP;
|
|
+ else
|
|
+ dir_flags |= GPIOD_PULL_DOWN;
|
|
+ }
|
|
+ }
|
|
+ *flags = dir_flags;
|
|
|
|
- return stmfx_write(dev, reg, ret | mask);
|
|
+ return 0;
|
|
}
|
|
|
|
static int stmfx_gpio_probe(struct udevice *dev)
|
|
@@ -166,6 +263,8 @@ static const struct dm_gpio_ops stmfx_gpio_ops = {
|
|
.get_function = stmfx_gpio_get_function,
|
|
.direction_input = stmfx_gpio_direction_input,
|
|
.direction_output = stmfx_gpio_direction_output,
|
|
+ .set_dir_flags = stmfx_gpio_set_dir_flags,
|
|
+ .get_dir_flags = stmfx_gpio_get_dir_flags,
|
|
};
|
|
|
|
U_BOOT_DRIVER(stmfx_gpio) = {
|
|
@@ -187,36 +286,6 @@ static const struct pinconf_param stmfx_pinctrl_conf_params[] = {
|
|
{ "output-low", PIN_CONFIG_OUTPUT, 0 },
|
|
};
|
|
|
|
-static int stmfx_pinctrl_set_pupd(struct udevice *dev,
|
|
- unsigned int pin, u32 pupd)
|
|
-{
|
|
- u8 reg = STMFX_REG_GPIO_PUPD + get_reg(pin);
|
|
- u32 mask = get_mask(pin);
|
|
- int ret;
|
|
-
|
|
- ret = stmfx_read(dev, reg);
|
|
- if (ret < 0)
|
|
- return ret;
|
|
- ret = (ret & ~mask) | (pupd ? mask : 0);
|
|
-
|
|
- return stmfx_write(dev, reg, ret);
|
|
-}
|
|
-
|
|
-static int stmfx_pinctrl_set_type(struct udevice *dev,
|
|
- unsigned int pin, u32 type)
|
|
-{
|
|
- u8 reg = STMFX_REG_GPIO_TYPE + get_reg(pin);
|
|
- u32 mask = get_mask(pin);
|
|
- int ret;
|
|
-
|
|
- ret = stmfx_read(dev, reg);
|
|
- if (ret < 0)
|
|
- return ret;
|
|
- ret = (ret & ~mask) | (type ? mask : 0);
|
|
-
|
|
- return stmfx_write(dev, reg, ret);
|
|
-}
|
|
-
|
|
static int stmfx_pinctrl_conf_set(struct udevice *dev, unsigned int pin,
|
|
unsigned int param, unsigned int arg)
|
|
{
|
|
@@ -232,22 +301,22 @@ static int stmfx_pinctrl_conf_set(struct udevice *dev, unsigned int pin,
|
|
case PIN_CONFIG_BIAS_PULL_PIN_DEFAULT:
|
|
case PIN_CONFIG_BIAS_DISABLE:
|
|
case PIN_CONFIG_DRIVE_PUSH_PULL:
|
|
- ret = stmfx_pinctrl_set_type(dev, pin, 0);
|
|
+ ret = stmfx_conf_set_type(dev, pin, 0);
|
|
break;
|
|
case PIN_CONFIG_BIAS_PULL_DOWN:
|
|
- ret = stmfx_pinctrl_set_type(dev, pin, 1);
|
|
+ ret = stmfx_conf_set_type(dev, pin, 1);
|
|
if (ret)
|
|
return ret;
|
|
- ret = stmfx_pinctrl_set_pupd(dev, pin, 0);
|
|
+ ret = stmfx_conf_set_pupd(dev, pin, 0);
|
|
break;
|
|
case PIN_CONFIG_BIAS_PULL_UP:
|
|
- ret = stmfx_pinctrl_set_type(dev, pin, 1);
|
|
+ ret = stmfx_conf_set_type(dev, pin, 1);
|
|
if (ret)
|
|
return ret;
|
|
- ret = stmfx_pinctrl_set_pupd(dev, pin, 1);
|
|
+ ret = stmfx_conf_set_pupd(dev, pin, 1);
|
|
break;
|
|
case PIN_CONFIG_DRIVE_OPEN_DRAIN:
|
|
- ret = stmfx_pinctrl_set_type(dev, pin, 1);
|
|
+ ret = stmfx_conf_set_type(dev, pin, 1);
|
|
break;
|
|
case PIN_CONFIG_OUTPUT:
|
|
ret = stmfx_gpio_direction_output(plat->gpio, pin, arg);
|
|
@@ -286,6 +355,34 @@ static const char *stmfx_pinctrl_get_pin_name(struct udevice *dev,
|
|
return pin_name;
|
|
}
|
|
|
|
+static const char *stmfx_pinctrl_get_pin_conf(struct udevice *dev,
|
|
+ unsigned int pin, int func)
|
|
+{
|
|
+ int pupd, type;
|
|
+
|
|
+ type = stmfx_conf_get_type(dev, pin);
|
|
+ if (type < 0)
|
|
+ return "";
|
|
+
|
|
+ if (func == GPIOF_OUTPUT) {
|
|
+ if (type)
|
|
+ return "drive-open-drain";
|
|
+ else
|
|
+ return ""; /* default: push-pull*/
|
|
+ }
|
|
+ if (!type)
|
|
+ return ""; /* default: bias-disable*/
|
|
+
|
|
+ pupd = stmfx_conf_get_pupd(dev, pin);
|
|
+ if (pupd < 0)
|
|
+ return "";
|
|
+
|
|
+ if (pupd)
|
|
+ return "bias-pull-up";
|
|
+ else
|
|
+ return "bias-pull-down";
|
|
+}
|
|
+
|
|
static int stmfx_pinctrl_get_pin_muxing(struct udevice *dev,
|
|
unsigned int selector,
|
|
char *buf, int size)
|
|
@@ -297,7 +394,9 @@ static int stmfx_pinctrl_get_pin_muxing(struct udevice *dev,
|
|
if (func < 0)
|
|
return func;
|
|
|
|
- snprintf(buf, size, "%s", func == GPIOF_INPUT ? "input" : "output");
|
|
+ snprintf(buf, size, "%s ", func == GPIOF_INPUT ? "input" : "output");
|
|
+
|
|
+ strncat(buf, stmfx_pinctrl_get_pin_conf(dev, selector, func), size);
|
|
|
|
return 0;
|
|
}
|
|
@@ -351,11 +450,12 @@ static int stmfx_chip_init(struct udevice *dev)
|
|
int ret;
|
|
struct dm_i2c_chip *chip = dev_get_parent_platdata(dev);
|
|
|
|
- id = dm_i2c_reg_read(dev, STMFX_REG_CHIP_ID);
|
|
- if (id < 0) {
|
|
- dev_err(dev, "error reading chip id: %d\n", id);
|
|
+ ret = dm_i2c_reg_read(dev, STMFX_REG_CHIP_ID);
|
|
+ if (ret < 0) {
|
|
+ dev_err(dev, "error reading chip id: %d\n", ret);
|
|
return ret;
|
|
}
|
|
+ id = (u8)ret;
|
|
/*
|
|
* Check that ID is the complement of the I2C address:
|
|
* STMFX I2C address follows the 7-bit format (MSB), that's why
|
|
diff --git a/drivers/pinctrl/pinctrl_stm32.c b/drivers/pinctrl/pinctrl_stm32.c
|
|
index 3a235ae..4511cd7 100644
|
|
--- a/drivers/pinctrl/pinctrl_stm32.c
|
|
+++ b/drivers/pinctrl/pinctrl_stm32.c
|
|
@@ -39,6 +39,17 @@ static const char * const pinmux_mode[PINMUX_MODE_COUNT] = {
|
|
"alt function",
|
|
};
|
|
|
|
+static const char * const pinmux_output[] = {
|
|
+ [STM32_GPIO_PUPD_NO] = "bias-disable",
|
|
+ [STM32_GPIO_PUPD_UP] = "bias-pull-up",
|
|
+ [STM32_GPIO_PUPD_DOWN] = "bias-pull-down",
|
|
+};
|
|
+
|
|
+static const char * const pinmux_input[] = {
|
|
+ [STM32_GPIO_OTYPE_PP] = "drive-push-pull",
|
|
+ [STM32_GPIO_OTYPE_OD] = "drive-open-drain",
|
|
+};
|
|
+
|
|
static int stm32_pinctrl_get_af(struct udevice *dev, unsigned int offset)
|
|
{
|
|
struct stm32_gpio_priv *priv = dev_get_priv(dev);
|
|
@@ -176,10 +187,12 @@ static int stm32_pinctrl_get_pin_muxing(struct udevice *dev,
|
|
int size)
|
|
{
|
|
struct udevice *gpio_dev;
|
|
+ struct stm32_gpio_priv *priv;
|
|
const char *label;
|
|
int mode;
|
|
int af_num;
|
|
unsigned int gpio_idx;
|
|
+ u32 pupd, otype;
|
|
|
|
/* look up for the bank which owns the requested pin */
|
|
gpio_dev = stm32_pinctrl_get_gpio_dev(dev, selector, &gpio_idx);
|
|
@@ -188,9 +201,9 @@ static int stm32_pinctrl_get_pin_muxing(struct udevice *dev,
|
|
return -ENODEV;
|
|
|
|
mode = gpio_get_raw_function(gpio_dev, gpio_idx, &label);
|
|
-
|
|
dev_dbg(dev, "selector = %d gpio_idx = %d mode = %d\n",
|
|
selector, gpio_idx, mode);
|
|
+ priv = dev_get_priv(gpio_dev);
|
|
|
|
|
|
switch (mode) {
|
|
@@ -205,9 +218,17 @@ static int stm32_pinctrl_get_pin_muxing(struct udevice *dev,
|
|
snprintf(buf, size, "%s %d", pinmux_mode[mode], af_num);
|
|
break;
|
|
case GPIOF_OUTPUT:
|
|
+ pupd = (readl(&priv->regs->pupdr) >> (gpio_idx * 2)) &
|
|
+ PUPD_MASK;
|
|
+ snprintf(buf, size, "%s %s %s",
|
|
+ pinmux_mode[mode], pinmux_output[pupd],
|
|
+ label ? label : "");
|
|
+ break;
|
|
case GPIOF_INPUT:
|
|
- snprintf(buf, size, "%s %s",
|
|
- pinmux_mode[mode], label ? label : "");
|
|
+ otype = (readl(&priv->regs->otyper) >> gpio_idx) & OTYPE_MSK;
|
|
+ snprintf(buf, size, "%s %s %s",
|
|
+ pinmux_mode[mode], pinmux_input[otype],
|
|
+ label ? label : "");
|
|
break;
|
|
}
|
|
|
|
diff --git a/drivers/power/regulator/stm32-vrefbuf.c b/drivers/power/regulator/stm32-vrefbuf.c
|
|
index 645528e..c8ff6a1 100644
|
|
--- a/drivers/power/regulator/stm32-vrefbuf.c
|
|
+++ b/drivers/power/regulator/stm32-vrefbuf.c
|
|
@@ -41,8 +41,20 @@ static int stm32_vrefbuf_set_enable(struct udevice *dev, bool enable)
|
|
u32 val;
|
|
int ret;
|
|
|
|
- clrsetbits_le32(priv->base + STM32_VREFBUF_CSR, STM32_HIZ | STM32_ENVR,
|
|
- enable ? STM32_ENVR : STM32_HIZ);
|
|
+ if (enable && !(readl(priv->base + STM32_VREFBUF_CSR) & STM32_ENVR)) {
|
|
+ /*
|
|
+ * There maybe an overshoot:
|
|
+ * - when disabling, then re-enabling vrefbuf too quickly
|
|
+ * - or upon platform reset as external capacitor maybe slow
|
|
+ * discharging (VREFBUF is HiZ at reset by default).
|
|
+ * So force active discharge (HiZ=0) for 1ms before enabling.
|
|
+ */
|
|
+ clrbits_le32(priv->base + STM32_VREFBUF_CSR, STM32_HIZ);
|
|
+ udelay(1000);
|
|
+ }
|
|
+
|
|
+ clrsetbits_le32(priv->base + STM32_VREFBUF_CSR, STM32_ENVR,
|
|
+ enable ? STM32_ENVR : 0);
|
|
if (!enable)
|
|
return 0;
|
|
|
|
diff --git a/drivers/ram/stm32mp1/stm32mp1_ddr.c b/drivers/ram/stm32mp1/stm32mp1_ddr.c
|
|
index d765a46..11b14ae 100644
|
|
--- a/drivers/ram/stm32mp1/stm32mp1_ddr.c
|
|
+++ b/drivers/ram/stm32mp1/stm32mp1_ddr.c
|
|
@@ -639,7 +639,8 @@ void stm32mp1_refresh_disable(struct stm32mp1_ddrctl *ctl)
|
|
start_sw_done(ctl);
|
|
/* quasi-dynamic register update*/
|
|
setbits_le32(&ctl->rfshctl3, DDRCTRL_RFSHCTL3_DIS_AUTO_REFRESH);
|
|
- clrbits_le32(&ctl->pwrctl, DDRCTRL_PWRCTL_POWERDOWN_EN);
|
|
+ clrbits_le32(&ctl->pwrctl, DDRCTRL_PWRCTL_POWERDOWN_EN |
|
|
+ DDRCTRL_PWRCTL_SELFREF_EN);
|
|
clrbits_le32(&ctl->dfimisc, DDRCTRL_DFIMISC_DFI_INIT_COMPLETE_EN);
|
|
wait_sw_done_ack(ctl);
|
|
}
|
|
@@ -652,6 +653,8 @@ void stm32mp1_refresh_restore(struct stm32mp1_ddrctl *ctl,
|
|
clrbits_le32(&ctl->rfshctl3, DDRCTRL_RFSHCTL3_DIS_AUTO_REFRESH);
|
|
if (pwrctl & DDRCTRL_PWRCTL_POWERDOWN_EN)
|
|
setbits_le32(&ctl->pwrctl, DDRCTRL_PWRCTL_POWERDOWN_EN);
|
|
+ if ((pwrctl & DDRCTRL_PWRCTL_SELFREF_EN))
|
|
+ setbits_le32(&ctl->pwrctl, DDRCTRL_PWRCTL_SELFREF_EN);
|
|
setbits_le32(&ctl->dfimisc, DDRCTRL_DFIMISC_DFI_INIT_COMPLETE_EN);
|
|
wait_sw_done_ack(ctl);
|
|
}
|
|
@@ -668,14 +671,34 @@ void stm32mp1_ddr_init(struct ddr_info *priv,
|
|
{
|
|
u32 pir;
|
|
int ret = -EINVAL;
|
|
+ char bus_width;
|
|
+
|
|
+ switch (config->c_reg.mstr & DDRCTRL_MSTR_DATA_BUS_WIDTH_MASK) {
|
|
+ case DDRCTRL_MSTR_DATA_BUS_WIDTH_QUARTER:
|
|
+ bus_width = 8;
|
|
+ break;
|
|
+ case DDRCTRL_MSTR_DATA_BUS_WIDTH_HALF:
|
|
+ bus_width = 16;
|
|
+ break;
|
|
+ default:
|
|
+ bus_width = 32;
|
|
+ break;
|
|
+ }
|
|
+
|
|
|
|
if (config->c_reg.mstr & DDRCTRL_MSTR_DDR3)
|
|
ret = board_ddr_power_init(STM32MP_DDR3);
|
|
- else if (config->c_reg.mstr & DDRCTRL_MSTR_LPDDR2)
|
|
- ret = board_ddr_power_init(STM32MP_LPDDR2);
|
|
- else if (config->c_reg.mstr & DDRCTRL_MSTR_LPDDR3)
|
|
- ret = board_ddr_power_init(STM32MP_LPDDR3);
|
|
-
|
|
+ else if (config->c_reg.mstr & DDRCTRL_MSTR_LPDDR2) {
|
|
+ if (bus_width == 32)
|
|
+ ret = board_ddr_power_init(STM32MP_LPDDR2_32);
|
|
+ else
|
|
+ ret = board_ddr_power_init(STM32MP_LPDDR2_16);
|
|
+ } else if (config->c_reg.mstr & DDRCTRL_MSTR_LPDDR3) {
|
|
+ if (bus_width == 32)
|
|
+ ret = board_ddr_power_init(STM32MP_LPDDR3_32);
|
|
+ else
|
|
+ ret = board_ddr_power_init(STM32MP_LPDDR3_16);
|
|
+ }
|
|
if (ret)
|
|
panic("ddr power init failed\n");
|
|
|
|
@@ -746,7 +769,8 @@ start:
|
|
*/
|
|
set_reg(priv, REGPHY_REG, &config->p_reg);
|
|
set_reg(priv, REGPHY_TIMING, &config->p_timing);
|
|
- set_reg(priv, REGPHY_CAL, &config->p_cal);
|
|
+ if (config->p_cal_present)
|
|
+ set_reg(priv, REGPHY_CAL, &config->p_cal);
|
|
|
|
if (INTERACTIVE(STEP_PHY_INIT))
|
|
goto start;
|
|
@@ -781,13 +805,16 @@ start:
|
|
|
|
wait_operating_mode(priv, DDRCTRL_STAT_OPERATING_MODE_NORMAL);
|
|
|
|
- debug("DDR DQS training : ");
|
|
+ if (config->p_cal_present) {
|
|
+ debug("DDR DQS training skipped.\n");
|
|
+ } else {
|
|
+ debug("DDR DQS training : ");
|
|
/* 8. Disable Auto refresh and power down by setting
|
|
* - RFSHCTL3.dis_au_refresh = 1
|
|
* - PWRCTL.powerdown_en = 0
|
|
* - DFIMISC.dfiinit_complete_en = 0
|
|
*/
|
|
- stm32mp1_refresh_disable(priv->ctl);
|
|
+ stm32mp1_refresh_disable(priv->ctl);
|
|
|
|
/* 9. Program PUBL PGCR to enable refresh during training and rank to train
|
|
* not done => keep the programed value in PGCR
|
|
@@ -795,14 +822,15 @@ start:
|
|
|
|
/* 10. configure PUBL PIR register to specify which training step to run */
|
|
/* warning : RVTRN is not supported by this PUBL */
|
|
- stm32mp1_ddrphy_init(priv->phy, DDRPHYC_PIR_QSTRN);
|
|
+ stm32mp1_ddrphy_init(priv->phy, DDRPHYC_PIR_QSTRN);
|
|
|
|
/* 11. monitor PUB PGSR.IDONE to poll cpmpletion of training sequence */
|
|
- ddrphy_idone_wait(priv->phy);
|
|
+ ddrphy_idone_wait(priv->phy);
|
|
|
|
/* 12. set back registers in step 8 to the orginal values if desidered */
|
|
- stm32mp1_refresh_restore(priv->ctl, config->c_reg.rfshctl3,
|
|
- config->c_reg.pwrctl);
|
|
+ stm32mp1_refresh_restore(priv->ctl, config->c_reg.rfshctl3,
|
|
+ config->c_reg.pwrctl);
|
|
+ } /* if (config->p_cal_present) */
|
|
|
|
/* enable uMCTL2 AXI port 0 and 1 */
|
|
setbits_le32(&priv->ctl->pctrl_0, DDRCTRL_PCTRL_N_PORT_EN);
|
|
diff --git a/drivers/ram/stm32mp1/stm32mp1_ddr.h b/drivers/ram/stm32mp1/stm32mp1_ddr.h
|
|
index 52b748f..4998f04 100644
|
|
--- a/drivers/ram/stm32mp1/stm32mp1_ddr.h
|
|
+++ b/drivers/ram/stm32mp1/stm32mp1_ddr.h
|
|
@@ -170,6 +170,7 @@ struct stm32mp1_ddr_config {
|
|
struct stm32mp1_ddrphy_reg p_reg;
|
|
struct stm32mp1_ddrphy_timing p_timing;
|
|
struct stm32mp1_ddrphy_cal p_cal;
|
|
+ bool p_cal_present;
|
|
};
|
|
|
|
int stm32mp1_ddr_clk_enable(struct ddr_info *priv, u32 mem_speed);
|
|
diff --git a/drivers/ram/stm32mp1/stm32mp1_ddr_regs.h b/drivers/ram/stm32mp1/stm32mp1_ddr_regs.h
|
|
index 9d33186..afd93c5 100644
|
|
--- a/drivers/ram/stm32mp1/stm32mp1_ddr_regs.h
|
|
+++ b/drivers/ram/stm32mp1/stm32mp1_ddr_regs.h
|
|
@@ -260,6 +260,7 @@ struct stm32mp1_ddrphy {
|
|
|
|
#define DDRCTRL_MRSTAT_MR_WR_BUSY BIT(0)
|
|
|
|
+#define DDRCTRL_PWRCTL_SELFREF_EN BIT(0)
|
|
#define DDRCTRL_PWRCTL_POWERDOWN_EN BIT(1)
|
|
#define DDRCTRL_PWRCTL_SELFREF_SW BIT(5)
|
|
|
|
diff --git a/drivers/ram/stm32mp1/stm32mp1_interactive.c b/drivers/ram/stm32mp1/stm32mp1_interactive.c
|
|
index cc9b2e7..805c9dd 100644
|
|
--- a/drivers/ram/stm32mp1/stm32mp1_interactive.c
|
|
+++ b/drivers/ram/stm32mp1/stm32mp1_interactive.c
|
|
@@ -106,7 +106,7 @@ static void stm32mp1_do_usage(void)
|
|
"help displays help\n"
|
|
"info displays DDR information\n"
|
|
"info <param> <val> changes DDR information\n"
|
|
- " with <param> = step, name, size or speed\n"
|
|
+ " with <param> = step, name, size, speed or cal\n"
|
|
"freq displays the DDR PHY frequency in kHz\n"
|
|
"freq <freq> changes the DDR PHY frequency\n"
|
|
"param [type|reg] prints input parameters\n"
|
|
@@ -160,6 +160,7 @@ static void stm32mp1_do_info(struct ddr_info *priv,
|
|
printf("name = %s\n", config->info.name);
|
|
printf("size = 0x%x\n", config->info.size);
|
|
printf("speed = %d kHz\n", config->info.speed);
|
|
+ printf("cal = %d\n", config->p_cal_present);
|
|
return;
|
|
}
|
|
|
|
@@ -208,6 +209,16 @@ static void stm32mp1_do_info(struct ddr_info *priv,
|
|
}
|
|
return;
|
|
}
|
|
+ if (!strcmp(argv[1], "cal")) {
|
|
+ if (strict_strtoul(argv[2], 10, &value) < 0 ||
|
|
+ (value != 0 && value != 1)) {
|
|
+ printf("invalid value %s\n", argv[2]);
|
|
+ } else {
|
|
+ config->p_cal_present = value;
|
|
+ printf("cal = %d\n", config->p_cal_present);
|
|
+ }
|
|
+ return;
|
|
+ }
|
|
printf("argument %s invalid\n", argv[1]);
|
|
}
|
|
|
|
@@ -367,7 +378,6 @@ bool stm32mp1_ddr_interactive(void *priv,
|
|
enum stm32mp1_ddr_interact_step step,
|
|
const struct stm32mp1_ddr_config *config)
|
|
{
|
|
- const char *prompt = "DDR>";
|
|
char buffer[CONFIG_SYS_CBSIZE];
|
|
char *argv[CONFIG_SYS_MAXARGS + 1]; /* NULL terminated */
|
|
int argc;
|
|
@@ -403,13 +413,12 @@ bool stm32mp1_ddr_interactive(void *priv,
|
|
}
|
|
|
|
printf("%d:%s\n", step, step_str[step]);
|
|
- printf("%s\n", prompt);
|
|
|
|
if (next_step > step)
|
|
return false;
|
|
|
|
while (next_step == step) {
|
|
- cli_readline_into_buffer(prompt, buffer, 0);
|
|
+ cli_readline_into_buffer("DDR>", buffer, 0);
|
|
argc = cli_simple_parse_line(buffer, argv);
|
|
if (!argc)
|
|
continue;
|
|
diff --git a/drivers/ram/stm32mp1/stm32mp1_ram.c b/drivers/ram/stm32mp1/stm32mp1_ram.c
|
|
index a362cf9..c54f314 100644
|
|
--- a/drivers/ram/stm32mp1/stm32mp1_ram.c
|
|
+++ b/drivers/ram/stm32mp1/stm32mp1_ram.c
|
|
@@ -64,18 +64,22 @@ static __maybe_unused int stm32mp1_ddr_setup(struct udevice *dev)
|
|
struct clk axidcg;
|
|
struct stm32mp1_ddr_config config;
|
|
|
|
-#define PARAM(x, y) \
|
|
- { x,\
|
|
- offsetof(struct stm32mp1_ddr_config, y),\
|
|
- sizeof(config.y) / sizeof(u32)}
|
|
+#define PARAM(x, y, z) \
|
|
+ { .name = x, \
|
|
+ .offset = offsetof(struct stm32mp1_ddr_config, y), \
|
|
+ .size = sizeof(config.y) / sizeof(u32), \
|
|
+ .present = z, \
|
|
+ }
|
|
|
|
-#define CTL_PARAM(x) PARAM("st,ctl-"#x, c_##x)
|
|
-#define PHY_PARAM(x) PARAM("st,phy-"#x, p_##x)
|
|
+#define CTL_PARAM(x) PARAM("st,ctl-"#x, c_##x, NULL)
|
|
+#define PHY_PARAM(x) PARAM("st,phy-"#x, p_##x, NULL)
|
|
+#define PHY_PARAM_OPT(x) PARAM("st,phy-"#x, p_##x, &config.p_##x##_present)
|
|
|
|
const struct {
|
|
const char *name; /* name in DT */
|
|
const u32 offset; /* offset in config struct */
|
|
const u32 size; /* size of parameters */
|
|
+ bool * const present; /* presence indication for opt */
|
|
} param[] = {
|
|
CTL_PARAM(reg),
|
|
CTL_PARAM(timing),
|
|
@@ -83,7 +87,7 @@ static __maybe_unused int stm32mp1_ddr_setup(struct udevice *dev)
|
|
CTL_PARAM(perf),
|
|
PHY_PARAM(reg),
|
|
PHY_PARAM(timing),
|
|
- PHY_PARAM(cal)
|
|
+ PHY_PARAM_OPT(cal)
|
|
};
|
|
|
|
config.info.speed = dev_read_u32_default(dev, "st,mem-speed", 0);
|
|
@@ -102,11 +106,25 @@ static __maybe_unused int stm32mp1_ddr_setup(struct udevice *dev)
|
|
param[idx].size);
|
|
debug("%s: %s[0x%x] = %d\n", __func__,
|
|
param[idx].name, param[idx].size, ret);
|
|
- if (ret) {
|
|
+ if (ret &&
|
|
+ (ret != -FDT_ERR_NOTFOUND || !param[idx].present)) {
|
|
pr_err("%s: Cannot read %s, error=%d\n",
|
|
__func__, param[idx].name, ret);
|
|
return -EINVAL;
|
|
}
|
|
+ if (param[idx].present) {
|
|
+ /* save presence of optional parameters */
|
|
+ *param[idx].present = true;
|
|
+ if (ret == -FDT_ERR_NOTFOUND) {
|
|
+ *param[idx].present = false;
|
|
+#ifdef CONFIG_STM32MP1_DDR_INTERACTIVE
|
|
+ /* reset values if used later */
|
|
+ memset((void *)((u32)&config +
|
|
+ param[idx].offset),
|
|
+ 0, param[idx].size * sizeof(u32));
|
|
+#endif
|
|
+ }
|
|
+ }
|
|
}
|
|
|
|
ret = clk_get_by_name(dev, "axidcg", &axidcg);
|
|
diff --git a/drivers/ram/stm32mp1/stm32mp1_tests.c b/drivers/ram/stm32mp1/stm32mp1_tests.c
|
|
index 581ee48..cc7b429 100644
|
|
--- a/drivers/ram/stm32mp1/stm32mp1_tests.c
|
|
+++ b/drivers/ram/stm32mp1/stm32mp1_tests.c
|
|
@@ -14,7 +14,7 @@
|
|
DECLARE_GLOBAL_DATA_PTR;
|
|
|
|
static int get_bufsize(char *string, int argc, char *argv[], int arg_nb,
|
|
- size_t *bufsize, size_t default_size)
|
|
+ size_t *bufsize, size_t default_size, size_t min_size)
|
|
{
|
|
unsigned long value;
|
|
|
|
@@ -24,8 +24,9 @@ static int get_bufsize(char *string, int argc, char *argv[], int arg_nb,
|
|
arg_nb, argv[arg_nb]);
|
|
return -1;
|
|
}
|
|
- if (value > STM32_DDR_SIZE || value == 0) {
|
|
- sprintf(string, "invalid size %s", argv[arg_nb]);
|
|
+ if (value > STM32_DDR_SIZE || value < min_size) {
|
|
+ sprintf(string, "invalid size %s (min=%d)",
|
|
+ argv[arg_nb], min_size);
|
|
return -1;
|
|
}
|
|
if (value & 0x3) {
|
|
@@ -438,7 +439,7 @@ static enum test_result test_addressbus(struct stm32mp1_ddrctl *ctl,
|
|
u32 bufsize;
|
|
u32 error;
|
|
|
|
- if (get_bufsize(string, argc, argv, 0, &bufsize, 4 * 1024))
|
|
+ if (get_bufsize(string, argc, argv, 0, &bufsize, 4 * 1024, 4))
|
|
return TEST_ERROR;
|
|
if (!is_power_of_2(bufsize)) {
|
|
sprintf(string, "size 0x%x is not a power of 2",
|
|
@@ -467,7 +468,7 @@ static enum test_result test_memdevice(struct stm32mp1_ddrctl *ctl,
|
|
size_t bufsize;
|
|
u32 error;
|
|
|
|
- if (get_bufsize(string, argc, argv, 0, &bufsize, 4 * 1024))
|
|
+ if (get_bufsize(string, argc, argv, 0, &bufsize, 4 * 1024, 4))
|
|
return TEST_ERROR;
|
|
if (get_addr(string, argc, argv, 1, &addr))
|
|
return TEST_ERROR;
|
|
@@ -509,7 +510,7 @@ static enum test_result test_sso(struct stm32mp1_ddrctl *ctl,
|
|
u32 error = 0;
|
|
u32 data;
|
|
|
|
- if (get_bufsize(string, argc, argv, 0, &bufsize, 4))
|
|
+ if (get_bufsize(string, argc, argv, 0, &bufsize, 4 * 1024, 4))
|
|
return TEST_ERROR;
|
|
if (get_addr(string, argc, argv, 1, &addr))
|
|
return TEST_ERROR;
|
|
@@ -581,7 +582,7 @@ static enum test_result test_random(struct stm32mp1_ddrctl *ctl,
|
|
u32 error = 0;
|
|
unsigned int seed;
|
|
|
|
- if (get_bufsize(string, argc, argv, 0, &bufsize, 8 * 1024))
|
|
+ if (get_bufsize(string, argc, argv, 0, &bufsize, 4 * 1024, 8))
|
|
return TEST_ERROR;
|
|
if (get_nb_loop(string, argc, argv, 1, &nb_loop, 1))
|
|
return TEST_ERROR;
|
|
@@ -741,7 +742,7 @@ static enum test_result test_noise_burst(struct stm32mp1_ddrctl *ctl,
|
|
int i;
|
|
enum test_result res = TEST_PASSED;
|
|
|
|
- if (get_bufsize(string, argc, argv, 0, &bufsize, 4 * 1024))
|
|
+ if (get_bufsize(string, argc, argv, 0, &bufsize, 4 * 1024, 128))
|
|
return TEST_ERROR;
|
|
if (get_pattern(string, argc, argv, 1, &pattern, 0xFFFFFFFF))
|
|
return TEST_ERROR;
|
|
@@ -917,7 +918,7 @@ static enum test_result test_freq_pattern(struct stm32mp1_ddrctl *ctl,
|
|
const u32 **patterns;
|
|
u32 bufsize;
|
|
|
|
- if (get_bufsize(string, argc, argv, 0, &bufsize, 4 * 1024))
|
|
+ if (get_bufsize(string, argc, argv, 0, &bufsize, 4 * 1024, 128))
|
|
return TEST_ERROR;
|
|
|
|
switch (readl(&ctl->mstr) & DDRCTRL_MSTR_DATA_BUS_WIDTH_MASK) {
|
|
@@ -1004,7 +1005,7 @@ static enum test_result test_checkboard(struct stm32mp1_ddrctl *ctl,
|
|
|
|
u32 checkboard[2] = {0x55555555, 0xAAAAAAAA};
|
|
|
|
- if (get_bufsize(string, argc, argv, 0, &bufsize, 4 * 1024))
|
|
+ if (get_bufsize(string, argc, argv, 0, &bufsize, 4 * 1024, 8))
|
|
return TEST_ERROR;
|
|
if (get_nb_loop(string, argc, argv, 1, &nb_loop, 1))
|
|
return TEST_ERROR;
|
|
@@ -1039,7 +1040,7 @@ static enum test_result test_blockseq(struct stm32mp1_ddrctl *ctl,
|
|
u32 bufsize, nb_loop, loop = 0, addr, value;
|
|
int i;
|
|
|
|
- if (get_bufsize(string, argc, argv, 0, &bufsize, 4 * 1024))
|
|
+ if (get_bufsize(string, argc, argv, 0, &bufsize, 4 * 1024, 4))
|
|
return TEST_ERROR;
|
|
if (get_nb_loop(string, argc, argv, 1, &nb_loop, 1))
|
|
return TEST_ERROR;
|
|
@@ -1073,7 +1074,7 @@ static enum test_result test_walkbit0(struct stm32mp1_ddrctl *ctl,
|
|
u32 bufsize, nb_loop, loop = 0, addr, value;
|
|
int i;
|
|
|
|
- if (get_bufsize(string, argc, argv, 0, &bufsize, 4 * 1024))
|
|
+ if (get_bufsize(string, argc, argv, 0, &bufsize, 4 * 1024, 4))
|
|
return TEST_ERROR;
|
|
if (get_nb_loop(string, argc, argv, 1, &nb_loop, 1))
|
|
return TEST_ERROR;
|
|
@@ -1111,7 +1112,7 @@ static enum test_result test_walkbit1(struct stm32mp1_ddrctl *ctl,
|
|
u32 bufsize, nb_loop, loop = 0, addr, value;
|
|
int i;
|
|
|
|
- if (get_bufsize(string, argc, argv, 0, &bufsize, 4 * 1024))
|
|
+ if (get_bufsize(string, argc, argv, 0, &bufsize, 4 * 1024, 4))
|
|
return TEST_ERROR;
|
|
if (get_nb_loop(string, argc, argv, 1, &nb_loop, 1))
|
|
return TEST_ERROR;
|
|
@@ -1153,7 +1154,7 @@ static enum test_result test_bitspread(struct stm32mp1_ddrctl *ctl,
|
|
u32 bufsize, nb_loop, loop = 0, addr, bitspread[4];
|
|
int i, j;
|
|
|
|
- if (get_bufsize(string, argc, argv, 0, &bufsize, 4 * 1024))
|
|
+ if (get_bufsize(string, argc, argv, 0, &bufsize, 4 * 1024, 32))
|
|
return TEST_ERROR;
|
|
if (get_nb_loop(string, argc, argv, 1, &nb_loop, 1))
|
|
return TEST_ERROR;
|
|
@@ -1200,7 +1201,7 @@ static enum test_result test_bitflip(struct stm32mp1_ddrctl *ctl,
|
|
|
|
u32 bitflip[4];
|
|
|
|
- if (get_bufsize(string, argc, argv, 0, &bufsize, 4 * 1024))
|
|
+ if (get_bufsize(string, argc, argv, 0, &bufsize, 4 * 1024, 32))
|
|
return TEST_ERROR;
|
|
if (get_nb_loop(string, argc, argv, 1, &nb_loop, 1))
|
|
return TEST_ERROR;
|
|
diff --git a/drivers/ram/stm32mp1/stm32mp1_tuning.c b/drivers/ram/stm32mp1/stm32mp1_tuning.c
|
|
index 4e1c1fa..3013b7b 100644
|
|
--- a/drivers/ram/stm32mp1/stm32mp1_tuning.c
|
|
+++ b/drivers/ram/stm32mp1/stm32mp1_tuning.c
|
|
@@ -8,6 +8,8 @@
|
|
#include <ram.h>
|
|
#include <reset.h>
|
|
#include <asm/io.h>
|
|
+#include <linux/bitops.h>
|
|
+#include <linux/iopoll.h>
|
|
|
|
#include "stm32mp1_ddr_regs.h"
|
|
#include "stm32mp1_ddr.h"
|
|
@@ -75,6 +77,133 @@ static u8 get_nb_bytes(struct stm32mp1_ddrctl *ctl)
|
|
return nb_bytes;
|
|
}
|
|
|
|
+static u8 get_nb_bank(struct stm32mp1_ddrctl *ctl)
|
|
+{
|
|
+ /* Count bank address bits */
|
|
+ u8 bits = 0;
|
|
+ u32 reg, val;
|
|
+
|
|
+ reg = readl(&ctl->addrmap1);
|
|
+ /* addrmap1.addrmap_bank_b1 */
|
|
+ val = (reg & GENMASK(5, 0)) >> 0;
|
|
+ if (val <= 31)
|
|
+ bits++;
|
|
+ /* addrmap1.addrmap_bank_b2 */
|
|
+ val = (reg & GENMASK(13, 8)) >> 8;
|
|
+ if (val <= 31)
|
|
+ bits++;
|
|
+ /* addrmap1.addrmap_bank_b3 */
|
|
+ val = (reg & GENMASK(21, 16)) >> 16;
|
|
+ if (val <= 31)
|
|
+ bits++;
|
|
+
|
|
+ return bits;
|
|
+}
|
|
+
|
|
+static u8 get_nb_col(struct stm32mp1_ddrctl *ctl)
|
|
+{
|
|
+ u8 bits;
|
|
+ u32 reg, val;
|
|
+
|
|
+ /* Count column address bits, start at 2 for b0 and b1 (fixed) */
|
|
+ bits = 2;
|
|
+
|
|
+ reg = readl(&ctl->addrmap2);
|
|
+ /* addrmap2.addrmap_col_b2 */
|
|
+ val = (reg & GENMASK(3, 0)) >> 0;
|
|
+ if (val <= 7)
|
|
+ bits++;
|
|
+ /* addrmap2.addrmap_col_b3 */
|
|
+ val = (reg & GENMASK(11, 8)) >> 8;
|
|
+ if (val <= 7)
|
|
+ bits++;
|
|
+ /* addrmap2.addrmap_col_b4 */
|
|
+ val = (reg & GENMASK(19, 16)) >> 16;
|
|
+ if (val <= 7)
|
|
+ bits++;
|
|
+ /* addrmap2.addrmap_col_b5 */
|
|
+ val = (reg & GENMASK(27, 24)) >> 24;
|
|
+ if (val <= 7)
|
|
+ bits++;
|
|
+
|
|
+ reg = readl(&ctl->addrmap3);
|
|
+ /* addrmap3.addrmap_col_b6 */
|
|
+ val = (reg & GENMASK(3, 0)) >> 0;
|
|
+ if (val <= 7)
|
|
+ bits++;
|
|
+ /* addrmap3.addrmap_col_b7 */
|
|
+ val = (reg & GENMASK(11, 8)) >> 8;
|
|
+ if (val <= 7)
|
|
+ bits++;
|
|
+ /* addrmap3.addrmap_col_b8 */
|
|
+ val = (reg & GENMASK(19, 16)) >> 16;
|
|
+ if (val <= 7)
|
|
+ bits++;
|
|
+ /* addrmap3.addrmap_col_b9 */
|
|
+ val = (reg & GENMASK(27, 24)) >> 24;
|
|
+ if (val <= 7)
|
|
+ bits++;
|
|
+
|
|
+ reg = readl(&ctl->addrmap4);
|
|
+ /* addrmap4.addrmap_col_b10 */
|
|
+ val = (reg & GENMASK(3, 0)) >> 0;
|
|
+ if (val <= 7)
|
|
+ bits++;
|
|
+ /* addrmap4.addrmap_col_b11 */
|
|
+ val = (reg & GENMASK(11, 8)) >> 8;
|
|
+ if (val <= 7)
|
|
+ bits++;
|
|
+
|
|
+ return bits;
|
|
+}
|
|
+
|
|
+static u8 get_nb_row(struct stm32mp1_ddrctl *ctl)
|
|
+{
|
|
+ /* Count row address bits */
|
|
+ u8 bits = 0;
|
|
+ u32 reg, val;
|
|
+
|
|
+ reg = readl(&ctl->addrmap5);
|
|
+ /* addrmap5.addrmap_row_b0 */
|
|
+ val = (reg & GENMASK(3, 0)) >> 0;
|
|
+ if (val <= 11)
|
|
+ bits++;
|
|
+ /* addrmap5.addrmap_row_b1 */
|
|
+ val = (reg & GENMASK(11, 8)) >> 8;
|
|
+ if (val <= 11)
|
|
+ bits++;
|
|
+ /* addrmap5.addrmap_row_b2_10 */
|
|
+ val = (reg & GENMASK(19, 16)) >> 16;
|
|
+ if (val <= 11)
|
|
+ bits += 9;
|
|
+ else
|
|
+ printf("warning: addrmap5.addrmap_row_b2_10 not supported\n");
|
|
+ /* addrmap5.addrmap_row_b11 */
|
|
+ val = (reg & GENMASK(27, 24)) >> 24;
|
|
+ if (val <= 11)
|
|
+ bits++;
|
|
+
|
|
+ reg = readl(&ctl->addrmap6);
|
|
+ /* addrmap6.addrmap_row_b12 */
|
|
+ val = (reg & GENMASK(3, 0)) >> 0;
|
|
+ if (val <= 7)
|
|
+ bits++;
|
|
+ /* addrmap6.addrmap_row_b13 */
|
|
+ val = (reg & GENMASK(11, 8)) >> 8;
|
|
+ if (val <= 7)
|
|
+ bits++;
|
|
+ /* addrmap6.addrmap_row_b14 */
|
|
+ val = (reg & GENMASK(19, 16)) >> 16;
|
|
+ if (val <= 7)
|
|
+ bits++;
|
|
+ /* addrmap6.addrmap_row_b15 */
|
|
+ val = (reg & GENMASK(27, 24)) >> 24;
|
|
+ if (val <= 7)
|
|
+ bits++;
|
|
+
|
|
+ return bits;
|
|
+}
|
|
+
|
|
static void itm_soft_reset(struct stm32mp1_ddrphy *phy)
|
|
{
|
|
stm32mp1_ddrphy_init(phy, DDRPHYC_PIR_ITMSRST);
|
|
@@ -169,8 +298,13 @@ static void set_r0dgps_delay(struct stm32mp1_ddrphy *phy,
|
|
}
|
|
|
|
/* Basic BIST configuration for data lane tests. */
|
|
-static void config_BIST(struct stm32mp1_ddrphy *phy)
|
|
+static void config_BIST(struct stm32mp1_ddrctl *ctl,
|
|
+ struct stm32mp1_ddrphy *phy)
|
|
{
|
|
+ u8 nb_bank = get_nb_bank(ctl);
|
|
+ u8 nb_row = get_nb_row(ctl);
|
|
+ u8 nb_col = get_nb_col(ctl);
|
|
+
|
|
/* Selects the SDRAM bank address to be used during BIST. */
|
|
u32 bbank = 0;
|
|
/* Selects the SDRAM row address to be used during BIST. */
|
|
@@ -190,18 +324,20 @@ static void config_BIST(struct stm32mp1_ddrphy *phy)
|
|
* must be 0 with single rank
|
|
*/
|
|
u32 brank = 0;
|
|
+
|
|
/* Specifies the maximum SDRAM bank address to be used during
|
|
* BIST before the address & increments to the next rank.
|
|
*/
|
|
- u32 bmbank = 1;
|
|
+ u32 bmbank = (1 << nb_bank) - 1;
|
|
/* Specifies the maximum SDRAM row address to be used during
|
|
* BIST before the address & increments to the next bank.
|
|
*/
|
|
- u32 bmrow = 0x7FFF; /* To check */
|
|
+ u32 bmrow = (1 << nb_row) - 1;
|
|
/* Specifies the maximum SDRAM column address to be used during
|
|
* BIST before the address & increments to the next row.
|
|
*/
|
|
- u32 bmcol = 0x3FF; /* To check */
|
|
+ u32 bmcol = (1 << nb_col) - 1;
|
|
+
|
|
u32 bmode_conf = 0x00000001; /* DRam mode */
|
|
u32 bdxen_conf = 0x00000001; /* BIST on Data byte */
|
|
u32 bdpat_conf = 0x00000002; /* Select LFSR pattern */
|
|
@@ -223,8 +359,6 @@ static void config_BIST(struct stm32mp1_ddrphy *phy)
|
|
|
|
writel(bcol | (brow << 12) | (bbank << 28), &phy->bistar0);
|
|
writel(brank | (bmrank << 2) | (bainc << 4), &phy->bistar1);
|
|
-
|
|
- /* To check this line : */
|
|
writel(bmcol | (bmrow << 12) | (bmbank << 28), &phy->bistar2);
|
|
}
|
|
|
|
@@ -246,6 +380,8 @@ static void BIST_test(struct stm32mp1_ddrphy *phy, u8 byte,
|
|
bool result = true; /* BIST_SUCCESS */
|
|
u32 cnt = 0;
|
|
u32 error = 0;
|
|
+ u32 val;
|
|
+ int ret;
|
|
|
|
bist->test_result = true;
|
|
|
|
@@ -266,7 +402,7 @@ run:
|
|
writel(rand(), &phy->bistlsr);
|
|
|
|
/* some delay to reset BIST */
|
|
- mdelay(1);
|
|
+ udelay(10);
|
|
|
|
/*Perform BIST Run*/
|
|
clrsetbits_le32(&phy->bistrr,
|
|
@@ -274,27 +410,29 @@ run:
|
|
0x00000001);
|
|
/* Write BISTRR.BINST = 3?b001; */
|
|
|
|
- /* Wait for a number of CTL clocks before reading BIST register*/
|
|
- /* Wait 300 ctl_clk cycles; ... IS it really needed?? */
|
|
- /* Perform BIST Instruction Stop*/
|
|
- /* Write BISTRR.BINST = 3?b010;*/
|
|
-
|
|
- /* poll on BISTGSR.BDONE. If 0, wait. ++TODO Add timeout */
|
|
- while (!(readl(&phy->bistgsr) & DDRPHYC_BISTGSR_BDDONE))
|
|
- ;
|
|
-
|
|
- /*Check if received correct number of words*/
|
|
- /* if (Read BISTWCSR.DXWCNT = Read BISTWCR.BWCNT) */
|
|
- if (((readl(&phy->bistwcsr)) >> DDRPHYC_BISTWCSR_DXWCNT_SHIFT) ==
|
|
- readl(&phy->bistwcr)) {
|
|
- /*Determine if there is a data comparison error*/
|
|
- /* if (Read BISTGSR.BDXERR = 1?b0) */
|
|
- if (readl(&phy->bistgsr) & DDRPHYC_BISTGSR_BDXERR)
|
|
- result = false; /* BIST_FAIL; */
|
|
- else
|
|
- result = true; /* BIST_SUCCESS; */
|
|
- } else {
|
|
+ /* poll on BISTGSR.BDONE and wait max 1000 us */
|
|
+ ret = readl_poll_timeout(&phy->bistgsr, val,
|
|
+ val & DDRPHYC_BISTGSR_BDDONE, 1000);
|
|
+
|
|
+ if (ret < 0) {
|
|
+ printf("warning: BIST timeout\n");
|
|
result = false; /* BIST_FAIL; */
|
|
+ /*Perform BIST Stop */
|
|
+ clrsetbits_le32(&phy->bistrr, 0x00000007, 0x00000002);
|
|
+ } else {
|
|
+ /*Check if received correct number of words*/
|
|
+ /* if (Read BISTWCSR.DXWCNT = Read BISTWCR.BWCNT) */
|
|
+ if (((readl(&phy->bistwcsr)) >> DDRPHYC_BISTWCSR_DXWCNT_SHIFT)
|
|
+ == readl(&phy->bistwcr)) {
|
|
+ /*Determine if there is a data comparison error*/
|
|
+ /* if (Read BISTGSR.BDXERR = 1?b0) */
|
|
+ if (readl(&phy->bistgsr) & DDRPHYC_BISTGSR_BDXERR)
|
|
+ result = false; /* BIST_FAIL; */
|
|
+ else
|
|
+ result = true; /* BIST_SUCCESS; */
|
|
+ } else {
|
|
+ result = false; /* BIST_FAIL; */
|
|
+ }
|
|
}
|
|
|
|
/* loop while success */
|
|
@@ -394,7 +532,7 @@ static enum test_result bit_deskew(struct stm32mp1_ddrctl *ctl,
|
|
clrbits_le32(&phy->dx3gcr, DDRPHYC_DXNGCR_DXEN);
|
|
|
|
/* Config the BIST block */
|
|
- config_BIST(phy);
|
|
+ config_BIST(ctl, phy);
|
|
pr_debug("BIST Config done.\n");
|
|
|
|
/* Train each byte */
|
|
@@ -807,7 +945,7 @@ static enum test_result eye_training(struct stm32mp1_ddrctl *ctl,
|
|
clrbits_le32(&phy->dx3gcr, DDRPHYC_DXNGCR_DXEN);
|
|
|
|
/* Config the BIST block */
|
|
- config_BIST(phy);
|
|
+ config_BIST(ctl, phy);
|
|
|
|
for (byte = 0; byte < nb_bytes; byte++) {
|
|
if (ctrlc()) {
|
|
@@ -1182,15 +1320,17 @@ static u8 set_midpoint_read_dqs_gating(struct stm32mp1_ddrphy *phy, u8 byte,
|
|
dqs_gate_values[byte][0],
|
|
dqs_gate_values[byte][1]);
|
|
pr_debug("*******the nominal values were system latency: 0 phase: 2*******\n");
|
|
- set_r0dgsl_delay(phy, byte, dqs_gate_values[byte][0]);
|
|
- set_r0dgps_delay(phy, byte, dqs_gate_values[byte][1]);
|
|
}
|
|
} else {
|
|
/* if intermitant, restore defaut values */
|
|
pr_debug("dqs gating:no regular fail/pass/fail found. defaults values restored.\n");
|
|
- set_r0dgsl_delay(phy, byte, 0);
|
|
- set_r0dgps_delay(phy, byte, 2);
|
|
+ dqs_gate_values[byte][0] = 0;
|
|
+ dqs_gate_values[byte][1] = 2;
|
|
}
|
|
+ set_r0dgsl_delay(phy, byte, dqs_gate_values[byte][0]);
|
|
+ set_r0dgps_delay(phy, byte, dqs_gate_values[byte][1]);
|
|
+ printf("Byte %d, R0DGSL = %d, R0DGPS = %d\n",
|
|
+ byte, dqs_gate_values[byte][0], dqs_gate_values[byte][1]);
|
|
|
|
/* return 0 if intermittent or if both left_bound
|
|
* and right_bound are not found
|
|
@@ -1227,7 +1367,7 @@ static enum test_result read_dqs_gating(struct stm32mp1_ddrctl *ctl,
|
|
clrbits_le32(&phy->dx3gcr, DDRPHYC_DXNGCR_DXEN);
|
|
|
|
/* config the bist block */
|
|
- config_BIST(phy);
|
|
+ config_BIST(ctl, phy);
|
|
|
|
for (byte = 0; byte < nb_bytes; byte++) {
|
|
if (ctrlc()) {
|
|
@@ -1281,11 +1421,16 @@ static enum test_result do_read_dqs_gating(struct stm32mp1_ddrctl *ctl,
|
|
{
|
|
u32 rfshctl3 = readl(&ctl->rfshctl3);
|
|
u32 pwrctl = readl(&ctl->pwrctl);
|
|
+ u32 derateen = readl(&ctl->derateen);
|
|
enum test_result res;
|
|
|
|
+ writel(0x0, &ctl->derateen);
|
|
stm32mp1_refresh_disable(ctl);
|
|
+
|
|
res = read_dqs_gating(ctl, phy, string);
|
|
+
|
|
stm32mp1_refresh_restore(ctl, rfshctl3, pwrctl);
|
|
+ writel(derateen, &ctl->derateen);
|
|
|
|
return res;
|
|
}
|
|
@@ -1296,11 +1441,16 @@ static enum test_result do_bit_deskew(struct stm32mp1_ddrctl *ctl,
|
|
{
|
|
u32 rfshctl3 = readl(&ctl->rfshctl3);
|
|
u32 pwrctl = readl(&ctl->pwrctl);
|
|
+ u32 derateen = readl(&ctl->derateen);
|
|
enum test_result res;
|
|
|
|
+ writel(0x0, &ctl->derateen);
|
|
stm32mp1_refresh_disable(ctl);
|
|
+
|
|
res = bit_deskew(ctl, phy, string);
|
|
+
|
|
stm32mp1_refresh_restore(ctl, rfshctl3, pwrctl);
|
|
+ writel(derateen, &ctl->derateen);
|
|
|
|
return res;
|
|
}
|
|
@@ -1311,11 +1461,16 @@ static enum test_result do_eye_training(struct stm32mp1_ddrctl *ctl,
|
|
{
|
|
u32 rfshctl3 = readl(&ctl->rfshctl3);
|
|
u32 pwrctl = readl(&ctl->pwrctl);
|
|
+ u32 derateen = readl(&ctl->derateen);
|
|
enum test_result res;
|
|
|
|
+ writel(0x0, &ctl->derateen);
|
|
stm32mp1_refresh_disable(ctl);
|
|
+
|
|
res = eye_training(ctl, phy, string);
|
|
+
|
|
stm32mp1_refresh_restore(ctl, rfshctl3, pwrctl);
|
|
+ writel(derateen, &ctl->derateen);
|
|
|
|
return res;
|
|
}
|
|
diff --git a/drivers/remoteproc/rproc-elf-loader.c b/drivers/remoteproc/rproc-elf-loader.c
|
|
index e8026cd..5384812 100644
|
|
--- a/drivers/remoteproc/rproc-elf-loader.c
|
|
+++ b/drivers/remoteproc/rproc-elf-loader.c
|
|
@@ -8,6 +8,39 @@
|
|
#include <elf.h>
|
|
#include <remoteproc.h>
|
|
|
|
+/**
|
|
+ * struct resource_table - firmware resource table header
|
|
+ * @ver: version number
|
|
+ * @num: number of resource entries
|
|
+ * @reserved: reserved (must be zero)
|
|
+ * @offset: array of offsets pointing at the various resource entries
|
|
+ *
|
|
+ * A resource table is essentially a list of system resources required
|
|
+ * by the remote processor. It may also include configuration entries.
|
|
+ * If needed, the remote processor firmware should contain this table
|
|
+ * as a dedicated ".resource_table" ELF section.
|
|
+ *
|
|
+ * Some resources entries are mere announcements, where the host is informed
|
|
+ * of specific remoteproc configuration. Other entries require the host to
|
|
+ * do something (e.g. allocate a system resource). Sometimes a negotiation
|
|
+ * is expected, where the firmware requests a resource, and once allocated,
|
|
+ * the host should provide back its details (e.g. address of an allocated
|
|
+ * memory region).
|
|
+ *
|
|
+ * The header of the resource table, as expressed by this structure,
|
|
+ * contains a version number (should we need to change this format in the
|
|
+ * future), the number of available resource entries, and their offsets
|
|
+ * in the table.
|
|
+ *
|
|
+ * Immediately following this header are the resource entries themselves.
|
|
+ */
|
|
+struct resource_table {
|
|
+ u32 ver;
|
|
+ u32 num;
|
|
+ u32 reserved[2];
|
|
+ u32 offset[0];
|
|
+} __packed;
|
|
+
|
|
/* Basic function to verify ELF32 image format */
|
|
int rproc_elf32_sanity_check(ulong addr, ulong size)
|
|
{
|
|
@@ -276,3 +309,239 @@ ulong rproc_elf_get_boot_addr(struct udevice *dev, ulong addr)
|
|
else
|
|
return rproc_elf32_get_boot_addr(addr);
|
|
}
|
|
+
|
|
+/*
|
|
+ * Search for the resource table in an ELF32 image.
|
|
+ * Returns the address of the resource table section if found, NULL if there is
|
|
+ * no resource table section, or error pointer.
|
|
+ */
|
|
+static Elf32_Shdr *rproc_elf32_find_rsc_table(struct udevice *dev,
|
|
+ ulong fw_addr, ulong fw_size)
|
|
+{
|
|
+ int ret;
|
|
+ unsigned int i;
|
|
+ const char *name_table;
|
|
+ struct resource_table *table;
|
|
+ const u8 *elf_data = (void *)fw_addr;
|
|
+ Elf32_Ehdr *ehdr = (Elf32_Ehdr *)fw_addr;
|
|
+ Elf32_Shdr *shdr;
|
|
+
|
|
+ ret = rproc_elf32_sanity_check(fw_addr, fw_size);
|
|
+ if (ret) {
|
|
+ pr_debug("Invalid ELF32 Image %d\n", ret);
|
|
+ return ERR_PTR(ret);
|
|
+ }
|
|
+
|
|
+ /* look for the resource table and handle it */
|
|
+ shdr = (Elf32_Shdr *)(elf_data + ehdr->e_shoff);
|
|
+ name_table = (const char *)(elf_data +
|
|
+ shdr[ehdr->e_shstrndx].sh_offset);
|
|
+
|
|
+ for (i = 0; i < ehdr->e_shnum; i++, shdr++) {
|
|
+ u32 size = shdr->sh_size;
|
|
+ u32 offset = shdr->sh_offset;
|
|
+
|
|
+ if (strcmp(name_table + shdr->sh_name, ".resource_table"))
|
|
+ continue;
|
|
+
|
|
+ table = (struct resource_table *)(elf_data + offset);
|
|
+
|
|
+ /* make sure we have the entire table */
|
|
+ if (offset + size > fw_size) {
|
|
+ pr_debug("resource table truncated\n");
|
|
+ return ERR_PTR(-ENOSPC);
|
|
+ }
|
|
+
|
|
+ /* make sure table has at least the header */
|
|
+ if (sizeof(*table) > size) {
|
|
+ pr_debug("header-less resource table\n");
|
|
+ return ERR_PTR(-ENOSPC);
|
|
+ }
|
|
+
|
|
+ /* we don't support any version beyond the first */
|
|
+ if (table->ver != 1) {
|
|
+ pr_debug("unsupported fw ver: %d\n", table->ver);
|
|
+ return ERR_PTR(-EPROTONOSUPPORT);
|
|
+ }
|
|
+
|
|
+ /* make sure reserved bytes are zeroes */
|
|
+ if (table->reserved[0] || table->reserved[1]) {
|
|
+ pr_debug("non zero reserved bytes\n");
|
|
+ return ERR_PTR(-EBADF);
|
|
+ }
|
|
+
|
|
+ /* make sure the offsets array isn't truncated */
|
|
+ if (table->num * sizeof(table->offset[0]) +
|
|
+ sizeof(*table) > size) {
|
|
+ pr_debug("resource table incomplete\n");
|
|
+ return ERR_PTR(-ENOSPC);
|
|
+ }
|
|
+
|
|
+ return shdr;
|
|
+ }
|
|
+
|
|
+ return NULL;
|
|
+}
|
|
+
|
|
+/* Load the resource table from an ELF32 image */
|
|
+int rproc_elf32_load_rsc_table(struct udevice *dev, ulong fw_addr,
|
|
+ ulong fw_size, ulong *rsc_addr, ulong *rsc_size)
|
|
+{
|
|
+ const struct dm_rproc_ops *ops;
|
|
+ Elf32_Shdr *shdr;
|
|
+ void *src, *dst;
|
|
+
|
|
+ shdr = rproc_elf32_find_rsc_table(dev, fw_addr, fw_size);
|
|
+ if (!shdr)
|
|
+ return -ENODATA;
|
|
+ if (IS_ERR(shdr))
|
|
+ return PTR_ERR(shdr);
|
|
+
|
|
+ ops = rproc_get_ops(dev);
|
|
+ *rsc_addr = (ulong)shdr->sh_addr;
|
|
+ *rsc_size = (ulong)shdr->sh_size;
|
|
+
|
|
+ src = (void *)fw_addr + shdr->sh_offset;
|
|
+ if (ops->device_to_virt)
|
|
+ dst = (void *)ops->device_to_virt(dev, *rsc_addr, *rsc_size);
|
|
+ else
|
|
+ dst = (void *)rsc_addr;
|
|
+
|
|
+ dev_dbg(dev, "Loading resource table to 0x%8lx (%ld bytes)\n",
|
|
+ (ulong)dst, *rsc_size);
|
|
+
|
|
+ memcpy(dst, src, *rsc_size);
|
|
+ flush_cache(rounddown((unsigned long)dst, ARCH_DMA_MINALIGN),
|
|
+ roundup((unsigned long)dst + *rsc_size,
|
|
+ ARCH_DMA_MINALIGN) -
|
|
+ rounddown((unsigned long)dst, ARCH_DMA_MINALIGN));
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+/*
|
|
+ * Search for the resource table in an ELF64 image.
|
|
+ * Returns the address of the resource table section if found, NULL if there is
|
|
+ * no resource table section, or error pointer.
|
|
+ */
|
|
+static Elf64_Shdr *rproc_elf64_find_rsc_table(struct udevice *dev,
|
|
+ ulong fw_addr, ulong fw_size)
|
|
+{
|
|
+ int ret;
|
|
+ unsigned int i;
|
|
+ const char *name_table;
|
|
+ struct resource_table *table;
|
|
+ const u8 *elf_data = (void *)fw_addr;
|
|
+ Elf64_Ehdr *ehdr = (Elf64_Ehdr *)fw_addr;
|
|
+ Elf64_Shdr *shdr;
|
|
+
|
|
+ ret = rproc_elf64_sanity_check(fw_addr, fw_size);
|
|
+ if (ret) {
|
|
+ pr_debug("Invalid ELF64 Image %d\n", ret);
|
|
+ return ERR_PTR(ret);
|
|
+ }
|
|
+
|
|
+ /* look for the resource table and handle it */
|
|
+ shdr = (Elf64_Shdr *)(elf_data + ehdr->e_shoff);
|
|
+ name_table = (const char *)(elf_data +
|
|
+ shdr[ehdr->e_shstrndx].sh_offset);
|
|
+
|
|
+ for (i = 0; i < ehdr->e_shnum; i++, shdr++) {
|
|
+ u64 size = shdr->sh_size;
|
|
+ u64 offset = shdr->sh_offset;
|
|
+
|
|
+ if (strcmp(name_table + shdr->sh_name, ".resource_table"))
|
|
+ continue;
|
|
+
|
|
+ table = (struct resource_table *)(elf_data + offset);
|
|
+
|
|
+ /* make sure we have the entire table */
|
|
+ if (offset + size > fw_size) {
|
|
+ pr_debug("resource table truncated\n");
|
|
+ return ERR_PTR(-ENOSPC);
|
|
+ }
|
|
+
|
|
+ /* make sure table has at least the header */
|
|
+ if (sizeof(*table) > size) {
|
|
+ pr_debug("header-less resource table\n");
|
|
+ return ERR_PTR(-ENOSPC);
|
|
+ }
|
|
+
|
|
+ /* we don't support any version beyond the first */
|
|
+ if (table->ver != 1) {
|
|
+ pr_debug("unsupported fw ver: %d\n", table->ver);
|
|
+ return ERR_PTR(-EPROTONOSUPPORT);
|
|
+ }
|
|
+
|
|
+ /* make sure reserved bytes are zeroes */
|
|
+ if (table->reserved[0] || table->reserved[1]) {
|
|
+ pr_debug("non zero reserved bytes\n");
|
|
+ return ERR_PTR(-EBADF);
|
|
+ }
|
|
+
|
|
+ /* make sure the offsets array isn't truncated */
|
|
+ if (table->num * sizeof(table->offset[0]) +
|
|
+ sizeof(*table) > size) {
|
|
+ pr_debug("resource table incomplete\n");
|
|
+ return ERR_PTR(-ENOSPC);
|
|
+ }
|
|
+
|
|
+ return shdr;
|
|
+ }
|
|
+
|
|
+ return NULL;
|
|
+}
|
|
+
|
|
+/* Load the resource table from an ELF64 image */
|
|
+int rproc_elf64_load_rsc_table(struct udevice *dev, ulong fw_addr,
|
|
+ ulong fw_size, ulong *rsc_addr, ulong *rsc_size)
|
|
+{
|
|
+ const struct dm_rproc_ops *ops;
|
|
+ Elf64_Shdr *shdr;
|
|
+ void *src, *dst;
|
|
+
|
|
+ shdr = rproc_elf64_find_rsc_table(dev, fw_addr, fw_size);
|
|
+ if (!shdr)
|
|
+ return -ENODATA;
|
|
+ if (IS_ERR(shdr))
|
|
+ return PTR_ERR(shdr);
|
|
+
|
|
+ ops = rproc_get_ops(dev);
|
|
+ *rsc_addr = (ulong)shdr->sh_addr;
|
|
+ *rsc_size = (ulong)shdr->sh_size;
|
|
+
|
|
+ src = (void *)fw_addr + shdr->sh_offset;
|
|
+ if (ops->device_to_virt)
|
|
+ dst = (void *)ops->device_to_virt(dev, *rsc_addr, *rsc_size);
|
|
+ else
|
|
+ dst = (void *)rsc_addr;
|
|
+
|
|
+ dev_dbg(dev, "Loading resource table to 0x%8lx (%ld bytes)\n",
|
|
+ (ulong)dst, *rsc_size);
|
|
+
|
|
+ memcpy(dst, src, *rsc_size);
|
|
+ flush_cache(rounddown((unsigned long)dst, ARCH_DMA_MINALIGN),
|
|
+ roundup((unsigned long)dst + *rsc_size,
|
|
+ ARCH_DMA_MINALIGN) -
|
|
+ rounddown((unsigned long)dst, ARCH_DMA_MINALIGN));
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+/* Load the resource table from an ELF32 or ELF64 image */
|
|
+int rproc_elf_load_rsc_table(struct udevice *dev, ulong fw_addr,
|
|
+ ulong fw_size, ulong *rsc_addr, ulong *rsc_size)
|
|
+
|
|
+{
|
|
+ Elf32_Ehdr *ehdr = (Elf32_Ehdr *)fw_addr;
|
|
+
|
|
+ if (!fw_addr)
|
|
+ return -EFAULT;
|
|
+
|
|
+ if (ehdr->e_ident[EI_CLASS] == ELFCLASS64)
|
|
+ return rproc_elf64_load_rsc_table(dev, fw_addr, fw_size,
|
|
+ rsc_addr, rsc_size);
|
|
+ else
|
|
+ return rproc_elf32_load_rsc_table(dev, fw_addr, fw_size,
|
|
+ rsc_addr, rsc_size);
|
|
+}
|
|
diff --git a/drivers/remoteproc/stm32_copro.c b/drivers/remoteproc/stm32_copro.c
|
|
index 40bba37..b8e62e5 100644
|
|
--- a/drivers/remoteproc/stm32_copro.c
|
|
+++ b/drivers/remoteproc/stm32_copro.c
|
|
@@ -12,6 +12,7 @@
|
|
#include <reset.h>
|
|
#include <syscon.h>
|
|
#include <asm/io.h>
|
|
+#include <asm/arch/stm32mp1_smc.h>
|
|
|
|
#define RCC_GCR_HOLD_BOOT 0
|
|
#define RCC_GCR_RELEASE_BOOT 1
|
|
@@ -22,14 +23,16 @@
|
|
* @hold_boot_regmap: regmap for remote processor reset hold boot
|
|
* @hold_boot_offset: offset of the register controlling the hold boot setting
|
|
* @hold_boot_mask: bitmask of the register for the hold boot field
|
|
- * @is_running: is the remote processor running
|
|
+ * @secured_soc: TZEN flag (register protection)
|
|
+ * @rsc_table_addr: resource table address
|
|
*/
|
|
struct stm32_copro_privdata {
|
|
struct reset_ctl reset_ctl;
|
|
struct regmap *hold_boot_regmap;
|
|
uint hold_boot_offset;
|
|
uint hold_boot_mask;
|
|
- bool is_running;
|
|
+ bool secured_soc;
|
|
+ ulong rsc_table_addr;
|
|
};
|
|
|
|
/**
|
|
@@ -42,6 +45,7 @@ static int stm32_copro_probe(struct udevice *dev)
|
|
struct stm32_copro_privdata *priv;
|
|
struct regmap *regmap;
|
|
const fdt32_t *cell;
|
|
+ uint tz_offset, tz_mask, tzen;
|
|
int len, ret;
|
|
|
|
priv = dev_get_priv(dev);
|
|
@@ -69,6 +73,31 @@ static int stm32_copro_probe(struct udevice *dev)
|
|
return ret;
|
|
}
|
|
|
|
+ regmap = syscon_regmap_lookup_by_phandle(dev, "st,syscfg-tz");
|
|
+ if (IS_ERR(regmap)) {
|
|
+ dev_dbg(dev, "unable to find tz regmap (%ld)\n",
|
|
+ PTR_ERR(regmap));
|
|
+ return -EINVAL;
|
|
+ }
|
|
+
|
|
+ cell = dev_read_prop(dev, "st,syscfg-tz", &len);
|
|
+ if (3 * sizeof(fdt32_t) - len > 0) {
|
|
+ dev_dbg(dev, "tz offset and mask not available\n");
|
|
+ return -EINVAL;
|
|
+ }
|
|
+
|
|
+ tz_offset = fdtdec_get_number(cell + 1, 1);
|
|
+
|
|
+ tz_mask = fdtdec_get_number(cell + 2, 1);
|
|
+
|
|
+ ret = regmap_read(regmap, tz_offset, &tzen);
|
|
+ if (ret) {
|
|
+ dev_dbg(dev, "failed to read soc secure state\n");
|
|
+ return ret;
|
|
+ }
|
|
+
|
|
+ priv->secured_soc = !!(tzen & tz_mask);
|
|
+
|
|
dev_dbg(dev, "probed\n");
|
|
|
|
return 0;
|
|
@@ -90,6 +119,11 @@ static int stm32_copro_set_hold_boot(struct udevice *dev, bool hold)
|
|
|
|
val = hold ? RCC_GCR_HOLD_BOOT : RCC_GCR_RELEASE_BOOT;
|
|
|
|
+ if (priv->secured_soc) {
|
|
+ return stm32_smc_exec(STM32_SMC_RCC, STM32_SMC_REG_WRITE,
|
|
+ priv->hold_boot_offset, val);
|
|
+ }
|
|
+
|
|
/*
|
|
* Note: shall run an SMC call (STM32_SMC_RCC) if platform is secured.
|
|
* To be updated when the code for this SMC service is available which
|
|
@@ -141,6 +175,7 @@ static void *stm32_copro_device_to_virt(struct udevice *dev, ulong da,
|
|
static int stm32_copro_load(struct udevice *dev, ulong addr, ulong size)
|
|
{
|
|
struct stm32_copro_privdata *priv;
|
|
+ ulong rsc_table_size;
|
|
int ret;
|
|
|
|
priv = dev_get_priv(dev);
|
|
@@ -155,6 +190,12 @@ static int stm32_copro_load(struct udevice *dev, ulong addr, ulong size)
|
|
return ret;
|
|
}
|
|
|
|
+ if (rproc_elf32_load_rsc_table(dev, addr, size, &priv->rsc_table_addr,
|
|
+ &rsc_table_size)) {
|
|
+ priv->rsc_table_addr = 0;
|
|
+ dev_warn(dev, "No valid resource table for this firmware\n");
|
|
+ }
|
|
+
|
|
return rproc_elf32_load_image(dev, addr, size);
|
|
}
|
|
|
|
@@ -180,7 +221,12 @@ static int stm32_copro_start(struct udevice *dev)
|
|
* rebooting autonomously
|
|
*/
|
|
ret = stm32_copro_set_hold_boot(dev, true);
|
|
- priv->is_running = !ret;
|
|
+ writel(ret ? TAMP_COPRO_STATE_OFF : TAMP_COPRO_STATE_CRUN,
|
|
+ TAMP_COPRO_STATE);
|
|
+ if (!ret)
|
|
+ /* Store rsc_address in bkp register */
|
|
+ writel(priv->rsc_table_addr, TAMP_COPRO_RSC_TBL_ADDRESS);
|
|
+
|
|
return ret;
|
|
}
|
|
|
|
@@ -206,7 +252,7 @@ static int stm32_copro_reset(struct udevice *dev)
|
|
return ret;
|
|
}
|
|
|
|
- priv->is_running = false;
|
|
+ writel(TAMP_COPRO_STATE_OFF, TAMP_COPRO_STATE);
|
|
|
|
return 0;
|
|
}
|
|
@@ -224,14 +270,11 @@ static int stm32_copro_stop(struct udevice *dev)
|
|
/**
|
|
* stm32_copro_is_running() - Is the STM32 remote processor running
|
|
* @dev: corresponding STM32 remote processor device
|
|
- * @return 1 if the remote processor is running, 0 otherwise
|
|
+ * @return 0 if the remote processor is running, 1 otherwise
|
|
*/
|
|
static int stm32_copro_is_running(struct udevice *dev)
|
|
{
|
|
- struct stm32_copro_privdata *priv;
|
|
-
|
|
- priv = dev_get_priv(dev);
|
|
- return priv->is_running;
|
|
+ return (readl(TAMP_COPRO_STATE) == TAMP_COPRO_STATE_OFF);
|
|
}
|
|
|
|
static const struct dm_rproc_ops stm32_copro_ops = {
|
|
diff --git a/drivers/reset/Kconfig b/drivers/reset/Kconfig
|
|
index 75ccd65..4c92c49 100644
|
|
--- a/drivers/reset/Kconfig
|
|
+++ b/drivers/reset/Kconfig
|
|
@@ -148,4 +148,12 @@ config RESET_IMX7
|
|
help
|
|
Support for reset controller on i.MX7/8 SoCs.
|
|
|
|
+config RESET_SCMI
|
|
+ bool "Enable SCMI reset domain driver"
|
|
+ select SCMI_AGENT
|
|
+ help
|
|
+ Enable this option if you want to support reset controller
|
|
+ devices exposed by a SCMI agent based on SCMI reset domain
|
|
+ protocol communication with a SCMI server.
|
|
+
|
|
endmenu
|
|
diff --git a/drivers/reset/Makefile b/drivers/reset/Makefile
|
|
index 0a044d5..1ce9760 100644
|
|
--- a/drivers/reset/Makefile
|
|
+++ b/drivers/reset/Makefile
|
|
@@ -23,3 +23,4 @@ obj-$(CONFIG_RESET_MTMIPS) += reset-mtmips.o
|
|
obj-$(CONFIG_RESET_SUNXI) += reset-sunxi.o
|
|
obj-$(CONFIG_RESET_HISILICON) += reset-hisilicon.o
|
|
obj-$(CONFIG_RESET_IMX7) += reset-imx7.o
|
|
+obj-$(CONFIG_RESET_SCMI) += reset-scmi.o
|
|
diff --git a/drivers/reset/reset-scmi.c b/drivers/reset/reset-scmi.c
|
|
new file mode 100644
|
|
index 0000000..8f4c895
|
|
--- /dev/null
|
|
+++ b/drivers/reset/reset-scmi.c
|
|
@@ -0,0 +1,86 @@
|
|
+// SPDX-License-Identifier: GPL-2.0+
|
|
+/*
|
|
+ * Copyright (C) 2019 Linaro Limited
|
|
+ */
|
|
+#include <asm/types.h>
|
|
+#include <common.h>
|
|
+#include <dm.h>
|
|
+#include <errno.h>
|
|
+#include <reset-uclass.h>
|
|
+#include <scmi_agent.h>
|
|
+
|
|
+enum scmi_reset_domain_message_id {
|
|
+ SCMI_RESET_DOMAIN_RESET = 0x4,
|
|
+};
|
|
+
|
|
+#define SCMI_RD_RESET_FLAG_ASSERT BIT(1)
|
|
+#define SCMI_RD_RESET_FLAG_DEASSERT 0
|
|
+
|
|
+struct scmi_rd_reset_in {
|
|
+ u32 domain_id;
|
|
+ u32 flags;
|
|
+ u32 reset_state;
|
|
+};
|
|
+
|
|
+struct scmi_rd_reset_out {
|
|
+ s32 status;
|
|
+};
|
|
+
|
|
+static int scmi_reset_set_state(struct reset_ctl *rst, int assert_not_deassert)
|
|
+{
|
|
+ struct scmi_rd_reset_in in = {
|
|
+ .domain_id = rst->id,
|
|
+ .flags = assert_not_deassert ? SCMI_RD_RESET_FLAG_ASSERT :
|
|
+ SCMI_RD_RESET_FLAG_DEASSERT,
|
|
+ .reset_state = 0,
|
|
+ };
|
|
+ struct scmi_rd_reset_out out;
|
|
+ struct scmi_msg scmi_msg = {
|
|
+ .protocol_id = SCMI_PROTOCOL_ID_RESET_DOMAIN,
|
|
+ .message_id = SCMI_RESET_DOMAIN_RESET,
|
|
+ .in_msg = (u8 *)&in,
|
|
+ .in_msg_sz = sizeof(in),
|
|
+ .out_msg = (u8 *)&out,
|
|
+ .out_msg_sz = sizeof(out),
|
|
+ };
|
|
+ int rc;
|
|
+
|
|
+ rc = scmi_agent_process_msg(rst->dev->parent, &scmi_msg);
|
|
+ if (rc)
|
|
+ return rc;
|
|
+
|
|
+ return scmi_to_linux_errno(out.status);
|
|
+}
|
|
+
|
|
+static int scmi_reset_assert(struct reset_ctl *rst)
|
|
+{
|
|
+ return scmi_reset_set_state(rst, SCMI_RD_RESET_FLAG_ASSERT);
|
|
+}
|
|
+
|
|
+static int scmi_reset_deassert(struct reset_ctl *rst)
|
|
+{
|
|
+ return scmi_reset_set_state(rst, SCMI_RD_RESET_FLAG_DEASSERT);
|
|
+}
|
|
+
|
|
+static int scmi_reset_request(struct reset_ctl *reset_ctl)
|
|
+{
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+static int scmi_reset_free(struct reset_ctl *reset_ctl)
|
|
+{
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+static const struct reset_ops scmi_reset_domain_ops = {
|
|
+ .request = scmi_reset_request,
|
|
+ .free = scmi_reset_free,
|
|
+ .rst_assert = scmi_reset_assert,
|
|
+ .rst_deassert = scmi_reset_deassert,
|
|
+};
|
|
+
|
|
+U_BOOT_DRIVER(scmi_reset_domain) = {
|
|
+ .name = "scmi_reset_domain",
|
|
+ .id = UCLASS_RESET,
|
|
+ .ops = &scmi_reset_domain_ops,
|
|
+};
|
|
diff --git a/drivers/tee/optee/core.c b/drivers/tee/optee/core.c
|
|
index 7f870f2..8a0009b 100644
|
|
--- a/drivers/tee/optee/core.c
|
|
+++ b/drivers/tee/optee/core.c
|
|
@@ -510,7 +510,7 @@ static bool is_optee_api(optee_invoke_fn *invoke_fn)
|
|
res.a2 == OPTEE_MSG_UID_2 && res.a3 == OPTEE_MSG_UID_3;
|
|
}
|
|
|
|
-static void print_os_revision(optee_invoke_fn *invoke_fn)
|
|
+static void print_os_revision(struct udevice *dev, optee_invoke_fn *invoke_fn)
|
|
{
|
|
union {
|
|
struct arm_smccc_res smccc;
|
|
@@ -525,11 +525,12 @@ static void print_os_revision(optee_invoke_fn *invoke_fn)
|
|
&res.smccc);
|
|
|
|
if (res.result.build_id)
|
|
- debug("OP-TEE revision %lu.%lu (%08lx)\n", res.result.major,
|
|
- res.result.minor, res.result.build_id);
|
|
+ dev_info(dev, "OP-TEE: revision %lu.%lu (%08lx)\n",
|
|
+ res.result.major, res.result.minor,
|
|
+ res.result.build_id);
|
|
else
|
|
- debug("OP-TEE revision %lu.%lu\n", res.result.major,
|
|
- res.result.minor);
|
|
+ dev_info(dev, "OP-TEE: revision %lu.%lu\n",
|
|
+ res.result.major, res.result.minor);
|
|
}
|
|
|
|
static bool api_revision_is_compatible(optee_invoke_fn *invoke_fn)
|
|
@@ -624,7 +625,7 @@ static int optee_probe(struct udevice *dev)
|
|
return -ENOENT;
|
|
}
|
|
|
|
- print_os_revision(pdata->invoke_fn);
|
|
+ print_os_revision(dev, pdata->invoke_fn);
|
|
|
|
if (!api_revision_is_compatible(pdata->invoke_fn)) {
|
|
debug("%s: OP-TEE api revision mismatch\n", __func__);
|
|
diff --git a/drivers/usb/dwc3/core.c b/drivers/usb/dwc3/core.c
|
|
index 77c555e..988cf02 100644
|
|
--- a/drivers/usb/dwc3/core.c
|
|
+++ b/drivers/usb/dwc3/core.c
|
|
@@ -864,8 +864,8 @@ int dwc3_setup_phy(struct udevice *dev, struct phy **array, int *num_phys)
|
|
for (i = 0; i < count; i++) {
|
|
ret = generic_phy_init(&usb_phys[i]);
|
|
if (ret) {
|
|
- pr_err("Can't init USB PHY%d for %s\n",
|
|
- i, dev->name);
|
|
+ pr_debug("Can't init USB PHY%d for %s\n",
|
|
+ i, dev->name);
|
|
goto phys_init_err;
|
|
}
|
|
}
|
|
@@ -873,8 +873,8 @@ int dwc3_setup_phy(struct udevice *dev, struct phy **array, int *num_phys)
|
|
for (i = 0; i < count; i++) {
|
|
ret = generic_phy_power_on(&usb_phys[i]);
|
|
if (ret) {
|
|
- pr_err("Can't power USB PHY%d for %s\n",
|
|
- i, dev->name);
|
|
+ pr_debug("Can't power USB PHY%d for %s\n",
|
|
+ i, dev->name);
|
|
goto phys_poweron_err;
|
|
}
|
|
}
|
|
@@ -910,8 +910,8 @@ int dwc3_shutdown_phy(struct udevice *dev, struct phy *usb_phys, int num_phys)
|
|
ret = generic_phy_power_off(&usb_phys[i]);
|
|
ret |= generic_phy_exit(&usb_phys[i]);
|
|
if (ret) {
|
|
- pr_err("Can't shutdown USB PHY%d for %s\n",
|
|
- i, dev->name);
|
|
+ pr_debug("Can't shutdown USB PHY%d for %s\n",
|
|
+ i, dev->name);
|
|
}
|
|
}
|
|
|
|
diff --git a/drivers/usb/gadget/dwc2_udc_otg.c b/drivers/usb/gadget/dwc2_udc_otg.c
|
|
index 35f4147..35495e4 100644
|
|
--- a/drivers/usb/gadget/dwc2_udc_otg.c
|
|
+++ b/drivers/usb/gadget/dwc2_udc_otg.c
|
|
@@ -980,7 +980,7 @@ int dwc2_phy_setup(struct udevice *dev, struct phy **array, int *num_phys)
|
|
for (i = 0; i < count; i++) {
|
|
ret = generic_phy_init(&usb_phys[i]);
|
|
if (ret) {
|
|
- dev_err(dev, "Can't init USB PHY%d for %s\n",
|
|
+ dev_dbg(dev, "Can't init USB PHY%d for %s\n",
|
|
i, dev->name);
|
|
goto phys_init_err;
|
|
}
|
|
@@ -989,7 +989,7 @@ int dwc2_phy_setup(struct udevice *dev, struct phy **array, int *num_phys)
|
|
for (i = 0; i < count; i++) {
|
|
ret = generic_phy_power_on(&usb_phys[i]);
|
|
if (ret) {
|
|
- dev_err(dev, "Can't power USB PHY%d for %s\n",
|
|
+ dev_dbg(dev, "Can't power USB PHY%d for %s\n",
|
|
i, dev->name);
|
|
goto phys_poweron_err;
|
|
}
|
|
@@ -1027,7 +1027,7 @@ void dwc2_phy_shutdown(struct udevice *dev, struct phy *usb_phys, int num_phys)
|
|
ret = generic_phy_power_off(&usb_phys[i]);
|
|
ret |= generic_phy_exit(&usb_phys[i]);
|
|
if (ret) {
|
|
- dev_err(dev, "Can't shutdown USB PHY%d for %s\n",
|
|
+ dev_dbg(dev, "Can't shutdown USB PHY%d for %s\n",
|
|
i, dev->name);
|
|
}
|
|
}
|
|
diff --git a/drivers/usb/gadget/g_dnl.c b/drivers/usb/gadget/g_dnl.c
|
|
index e9e1600..7a51b53 100644
|
|
--- a/drivers/usb/gadget/g_dnl.c
|
|
+++ b/drivers/usb/gadget/g_dnl.c
|
|
@@ -89,6 +89,14 @@ static struct usb_gadget_strings *g_dnl_composite_strings[] = {
|
|
NULL,
|
|
};
|
|
|
|
+void g_dnl_set_product(const char *s)
|
|
+{
|
|
+ if (s)
|
|
+ g_dnl_string_defs[1].s = s;
|
|
+ else
|
|
+ g_dnl_string_defs[1].s = product;
|
|
+}
|
|
+
|
|
static int g_dnl_unbind(struct usb_composite_dev *cdev)
|
|
{
|
|
struct usb_gadget *gadget = cdev->gadget;
|
|
diff --git a/drivers/usb/host/dwc2.c b/drivers/usb/host/dwc2.c
|
|
index b9c56f7..2fbb8b8 100644
|
|
--- a/drivers/usb/host/dwc2.c
|
|
+++ b/drivers/usb/host/dwc2.c
|
|
@@ -5,13 +5,15 @@
|
|
*/
|
|
|
|
#include <common.h>
|
|
+#include <clk.h>
|
|
#include <cpu_func.h>
|
|
#include <dm.h>
|
|
#include <errno.h>
|
|
-#include <usb.h>
|
|
+#include <generic-phy.h>
|
|
#include <malloc.h>
|
|
#include <memalign.h>
|
|
#include <phys2bus.h>
|
|
+#include <usb.h>
|
|
#include <usbroothubdes.h>
|
|
#include <wait_bit.h>
|
|
#include <asm/io.h>
|
|
@@ -36,6 +38,8 @@ struct dwc2_priv {
|
|
#ifdef CONFIG_DM_REGULATOR
|
|
struct udevice *vbus_supply;
|
|
#endif
|
|
+ struct phy phy;
|
|
+ struct clk_bulk clks;
|
|
#else
|
|
uint8_t *aligned_buffer;
|
|
uint8_t *status_buffer;
|
|
@@ -1146,6 +1150,8 @@ static int dwc2_reset(struct udevice *dev)
|
|
return ret;
|
|
}
|
|
|
|
+ /* force reset to clear all IP register */
|
|
+ reset_assert_bulk(&priv->resets);
|
|
ret = reset_deassert_bulk(&priv->resets);
|
|
if (ret) {
|
|
reset_release_bulk(&priv->resets);
|
|
@@ -1212,6 +1218,8 @@ static int dwc2_init_common(struct udevice *dev, struct dwc2_priv *priv)
|
|
if (readl(®s->gintsts) & DWC2_GINTSTS_CURMODE_HOST)
|
|
mdelay(1000);
|
|
|
|
+ printf("USB DWC2\n");
|
|
+
|
|
return 0;
|
|
}
|
|
|
|
@@ -1321,13 +1329,113 @@ static int dwc2_usb_ofdata_to_platdata(struct udevice *dev)
|
|
return 0;
|
|
}
|
|
|
|
+static int dwc2_setup_phy(struct udevice *dev)
|
|
+{
|
|
+ struct dwc2_priv *priv = dev_get_priv(dev);
|
|
+ int ret;
|
|
+
|
|
+ ret = generic_phy_get_by_index(dev, 0, &priv->phy);
|
|
+ if (ret) {
|
|
+ if (ret == -ENOENT)
|
|
+ return 0; /* no PHY, nothing to do */
|
|
+ dev_err(dev, "Failed to get USB PHY: %d.\n", ret);
|
|
+ return ret;
|
|
+ }
|
|
+
|
|
+ ret = generic_phy_init(&priv->phy);
|
|
+ if (ret) {
|
|
+ dev_dbg(dev, "Failed to init USB PHY: %d.\n", ret);
|
|
+ return ret;
|
|
+ }
|
|
+
|
|
+ ret = generic_phy_power_on(&priv->phy);
|
|
+ if (ret) {
|
|
+ dev_dbg(dev, "Failed to power on USB PHY: %d.\n", ret);
|
|
+ generic_phy_exit(&priv->phy);
|
|
+ return ret;
|
|
+ }
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+static int dwc2_shutdown_phy(struct udevice *dev)
|
|
+{
|
|
+ struct dwc2_priv *priv = dev_get_priv(dev);
|
|
+ int ret;
|
|
+
|
|
+ /* PHY is not valid when generic_phy_get_by_index() = -ENOENT */
|
|
+ if (!generic_phy_valid(&priv->phy))
|
|
+ return 0; /* no PHY, nothing to do */
|
|
+
|
|
+ ret = generic_phy_power_off(&priv->phy);
|
|
+ if (ret) {
|
|
+ dev_dbg(dev, "Failed to power off USB PHY: %d.\n", ret);
|
|
+ return ret;
|
|
+ }
|
|
+
|
|
+ ret = generic_phy_exit(&priv->phy);
|
|
+ if (ret) {
|
|
+ dev_dbg(dev, "Failed to power off USB PHY: %d.\n", ret);
|
|
+ return ret;
|
|
+ }
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+static int dwc2_clk_init(struct udevice *dev)
|
|
+{
|
|
+ struct dwc2_priv *priv = dev_get_priv(dev);
|
|
+ int ret;
|
|
+
|
|
+ ret = clk_get_bulk(dev, &priv->clks);
|
|
+ if (ret == -ENOSYS || ret == -ENOENT)
|
|
+ return 0;
|
|
+ if (ret)
|
|
+ return ret;
|
|
+
|
|
+ ret = clk_enable_bulk(&priv->clks);
|
|
+ if (ret) {
|
|
+ clk_release_bulk(&priv->clks);
|
|
+ return ret;
|
|
+ }
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+
|
|
static int dwc2_usb_probe(struct udevice *dev)
|
|
{
|
|
struct dwc2_priv *priv = dev_get_priv(dev);
|
|
struct usb_bus_priv *bus_priv = dev_get_uclass_priv(dev);
|
|
+ int ret;
|
|
|
|
bus_priv->desc_before_addr = true;
|
|
|
|
+ ret = dwc2_clk_init(dev);
|
|
+ if (ret)
|
|
+ return ret;
|
|
+
|
|
+ ret = dwc2_setup_phy(dev);
|
|
+ if (ret)
|
|
+ return ret;
|
|
+
|
|
+ if (CONFIG_IS_ENABLED(ARCH_STM32MP) &&
|
|
+ device_is_compatible(dev, "st,stm32mp1-hsotg")) {
|
|
+ struct udevice *usb33d_supply;
|
|
+
|
|
+ ret = device_get_supply_regulator(dev, "usb33d-supply",
|
|
+ &usb33d_supply);
|
|
+ if (ret) {
|
|
+ dev_err(dev,
|
|
+ "can't get voltage level detector supply\n");
|
|
+ } else {
|
|
+ ret = regulator_set_enable(usb33d_supply, true);
|
|
+ if (ret) {
|
|
+ dev_err(dev,
|
|
+ "can't enable voltage level detector supply\n");
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+
|
|
return dwc2_init_common(dev, priv);
|
|
}
|
|
|
|
@@ -1340,9 +1448,17 @@ static int dwc2_usb_remove(struct udevice *dev)
|
|
if (ret)
|
|
return ret;
|
|
|
|
+ ret = dwc2_shutdown_phy(dev);
|
|
+ if (ret) {
|
|
+ dev_dbg(dev, "Failed to shutdown USB PHY: %d.\n", ret);
|
|
+ return ret;
|
|
+ }
|
|
+
|
|
dwc2_uninit_common(priv->regs);
|
|
|
|
reset_release_bulk(&priv->resets);
|
|
+ clk_disable_bulk(&priv->clks);
|
|
+ clk_release_bulk(&priv->clks);
|
|
|
|
return 0;
|
|
}
|
|
diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c
|
|
index ef20c3c..0c31775 100644
|
|
--- a/drivers/usb/host/ehci-hcd.c
|
|
+++ b/drivers/usb/host/ehci-hcd.c
|
|
@@ -1698,13 +1698,13 @@ int ehci_setup_phy(struct udevice *dev, struct phy *phy, int index)
|
|
} else {
|
|
ret = generic_phy_init(phy);
|
|
if (ret) {
|
|
- dev_err(dev, "failed to init usb phy\n");
|
|
+ dev_dbg(dev, "failed to init usb phy\n");
|
|
return ret;
|
|
}
|
|
|
|
ret = generic_phy_power_on(phy);
|
|
if (ret) {
|
|
- dev_err(dev, "failed to power on usb phy\n");
|
|
+ dev_dbg(dev, "failed to power on usb phy\n");
|
|
return generic_phy_exit(phy);
|
|
}
|
|
}
|
|
@@ -1722,13 +1722,13 @@ int ehci_shutdown_phy(struct udevice *dev, struct phy *phy)
|
|
if (generic_phy_valid(phy)) {
|
|
ret = generic_phy_power_off(phy);
|
|
if (ret) {
|
|
- dev_err(dev, "failed to power off usb phy\n");
|
|
+ dev_dbg(dev, "failed to power off usb phy\n");
|
|
return ret;
|
|
}
|
|
|
|
ret = generic_phy_exit(phy);
|
|
if (ret) {
|
|
- dev_err(dev, "failed to power off usb phy\n");
|
|
+ dev_dbg(dev, "failed to power off usb phy\n");
|
|
return ret;
|
|
}
|
|
}
|
|
diff --git a/drivers/usb/host/ohci-generic.c b/drivers/usb/host/ohci-generic.c
|
|
index 916ea0b..e8cf26a 100644
|
|
--- a/drivers/usb/host/ohci-generic.c
|
|
+++ b/drivers/usb/host/ohci-generic.c
|
|
@@ -38,13 +38,13 @@ static int ohci_setup_phy(struct udevice *dev, int index)
|
|
} else {
|
|
ret = generic_phy_init(&priv->phy);
|
|
if (ret) {
|
|
- dev_err(dev, "failed to init usb phy\n");
|
|
+ dev_dbg(dev, "failed to init usb phy\n");
|
|
return ret;
|
|
}
|
|
|
|
ret = generic_phy_power_on(&priv->phy);
|
|
if (ret) {
|
|
- dev_err(dev, "failed to power on usb phy\n");
|
|
+ dev_dbg(dev, "failed to power on usb phy\n");
|
|
return generic_phy_exit(&priv->phy);
|
|
}
|
|
}
|
|
@@ -60,13 +60,13 @@ static int ohci_shutdown_phy(struct udevice *dev)
|
|
if (generic_phy_valid(&priv->phy)) {
|
|
ret = generic_phy_power_off(&priv->phy);
|
|
if (ret) {
|
|
- dev_err(dev, "failed to power off usb phy\n");
|
|
+ dev_dbg(dev, "failed to power off usb phy\n");
|
|
return ret;
|
|
}
|
|
|
|
ret = generic_phy_exit(&priv->phy);
|
|
if (ret) {
|
|
- dev_err(dev, "failed to power off usb phy\n");
|
|
+ dev_dbg(dev, "failed to power off usb phy\n");
|
|
return ret;
|
|
}
|
|
}
|
|
diff --git a/drivers/usb/musb-new/sunxi.c b/drivers/usb/musb-new/sunxi.c
|
|
index 45eecfe..3b36ab3 100644
|
|
--- a/drivers/usb/musb-new/sunxi.c
|
|
+++ b/drivers/usb/musb-new/sunxi.c
|
|
@@ -252,7 +252,7 @@ static int sunxi_musb_enable(struct musb *musb)
|
|
|
|
ret = generic_phy_power_on(&glue->phy);
|
|
if (ret) {
|
|
- pr_err("failed to power on USB PHY\n");
|
|
+ pr_debug("failed to power on USB PHY\n");
|
|
return ret;
|
|
}
|
|
}
|
|
@@ -276,7 +276,7 @@ static void sunxi_musb_disable(struct musb *musb)
|
|
if (is_host_enabled(musb)) {
|
|
ret = generic_phy_power_off(&glue->phy);
|
|
if (ret) {
|
|
- pr_err("failed to power off USB PHY\n");
|
|
+ pr_debug("failed to power off USB PHY\n");
|
|
return;
|
|
}
|
|
}
|
|
@@ -310,7 +310,7 @@ static int sunxi_musb_init(struct musb *musb)
|
|
|
|
ret = generic_phy_init(&glue->phy);
|
|
if (ret) {
|
|
- dev_err(dev, "failed to init USB PHY\n");
|
|
+ dev_dbg(dev, "failed to init USB PHY\n");
|
|
goto err_rst;
|
|
}
|
|
|
|
@@ -347,7 +347,7 @@ static int sunxi_musb_exit(struct musb *musb)
|
|
if (generic_phy_valid(&glue->phy)) {
|
|
ret = generic_phy_exit(&glue->phy);
|
|
if (ret) {
|
|
- dev_err(dev, "failed to power off usb phy\n");
|
|
+ dev_dbg(dev, "failed to power off usb phy\n");
|
|
return ret;
|
|
}
|
|
}
|
|
diff --git a/drivers/video/orisetech_otm8009a.c b/drivers/video/orisetech_otm8009a.c
|
|
index 89d9cfd..629bf76 100644
|
|
--- a/drivers/video/orisetech_otm8009a.c
|
|
+++ b/drivers/video/orisetech_otm8009a.c
|
|
@@ -60,9 +60,6 @@
|
|
struct otm8009a_panel_priv {
|
|
struct udevice *reg;
|
|
struct gpio_desc reset;
|
|
- unsigned int lanes;
|
|
- enum mipi_dsi_pixel_format format;
|
|
- unsigned long mode_flags;
|
|
};
|
|
|
|
static const struct display_timing default_timing = {
|
|
@@ -291,17 +288,8 @@ static int otm8009a_panel_enable_backlight(struct udevice *dev)
|
|
static int otm8009a_panel_get_display_timing(struct udevice *dev,
|
|
struct display_timing *timings)
|
|
{
|
|
- struct mipi_dsi_panel_plat *plat = dev_get_platdata(dev);
|
|
- struct mipi_dsi_device *device = plat->device;
|
|
- struct otm8009a_panel_priv *priv = dev_get_priv(dev);
|
|
-
|
|
memcpy(timings, &default_timing, sizeof(*timings));
|
|
|
|
- /* fill characteristics of DSI data link */
|
|
- device->lanes = priv->lanes;
|
|
- device->format = priv->format;
|
|
- device->mode_flags = priv->mode_flags;
|
|
-
|
|
return 0;
|
|
}
|
|
|
|
@@ -333,6 +321,7 @@ static int otm8009a_panel_ofdata_to_platdata(struct udevice *dev)
|
|
static int otm8009a_panel_probe(struct udevice *dev)
|
|
{
|
|
struct otm8009a_panel_priv *priv = dev_get_priv(dev);
|
|
+ struct mipi_dsi_panel_plat *plat = dev_get_platdata(dev);
|
|
int ret;
|
|
|
|
if (IS_ENABLED(CONFIG_DM_REGULATOR) && priv->reg) {
|
|
@@ -348,9 +337,10 @@ static int otm8009a_panel_probe(struct udevice *dev)
|
|
dm_gpio_set_value(&priv->reset, false);
|
|
mdelay(10); /* >5ms */
|
|
|
|
- priv->lanes = 2;
|
|
- priv->format = MIPI_DSI_FMT_RGB888;
|
|
- priv->mode_flags = MIPI_DSI_MODE_VIDEO |
|
|
+ /* fill characteristics of DSI data link */
|
|
+ plat->lanes = 2;
|
|
+ plat->format = MIPI_DSI_FMT_RGB888;
|
|
+ plat->mode_flags = MIPI_DSI_MODE_VIDEO |
|
|
MIPI_DSI_MODE_VIDEO_BURST |
|
|
MIPI_DSI_MODE_LPM;
|
|
|
|
diff --git a/drivers/video/raydium-rm68200.c b/drivers/video/raydium-rm68200.c
|
|
index 91555e2..76b0ed2 100644
|
|
--- a/drivers/video/raydium-rm68200.c
|
|
+++ b/drivers/video/raydium-rm68200.c
|
|
@@ -73,9 +73,6 @@ struct rm68200_panel_priv {
|
|
struct udevice *reg;
|
|
struct udevice *backlight;
|
|
struct gpio_desc reset;
|
|
- unsigned int lanes;
|
|
- enum mipi_dsi_pixel_format format;
|
|
- unsigned long mode_flags;
|
|
};
|
|
|
|
static const struct display_timing default_timing = {
|
|
@@ -257,17 +254,8 @@ static int rm68200_panel_enable_backlight(struct udevice *dev)
|
|
static int rm68200_panel_get_display_timing(struct udevice *dev,
|
|
struct display_timing *timings)
|
|
{
|
|
- struct mipi_dsi_panel_plat *plat = dev_get_platdata(dev);
|
|
- struct mipi_dsi_device *device = plat->device;
|
|
- struct rm68200_panel_priv *priv = dev_get_priv(dev);
|
|
-
|
|
memcpy(timings, &default_timing, sizeof(*timings));
|
|
|
|
- /* fill characteristics of DSI data link */
|
|
- device->lanes = priv->lanes;
|
|
- device->format = priv->format;
|
|
- device->mode_flags = priv->mode_flags;
|
|
-
|
|
return 0;
|
|
}
|
|
|
|
@@ -306,6 +294,7 @@ static int rm68200_panel_ofdata_to_platdata(struct udevice *dev)
|
|
static int rm68200_panel_probe(struct udevice *dev)
|
|
{
|
|
struct rm68200_panel_priv *priv = dev_get_priv(dev);
|
|
+ struct mipi_dsi_panel_plat *plat = dev_get_platdata(dev);
|
|
int ret;
|
|
|
|
if (IS_ENABLED(CONFIG_DM_REGULATOR) && priv->reg) {
|
|
@@ -320,9 +309,10 @@ static int rm68200_panel_probe(struct udevice *dev)
|
|
dm_gpio_set_value(&priv->reset, false);
|
|
mdelay(10);
|
|
|
|
- priv->lanes = 2;
|
|
- priv->format = MIPI_DSI_FMT_RGB888;
|
|
- priv->mode_flags = MIPI_DSI_MODE_VIDEO |
|
|
+ /* fill characteristics of DSI data link */
|
|
+ plat->lanes = 2;
|
|
+ plat->format = MIPI_DSI_FMT_RGB888;
|
|
+ plat->mode_flags = MIPI_DSI_MODE_VIDEO |
|
|
MIPI_DSI_MODE_VIDEO_BURST |
|
|
MIPI_DSI_MODE_LPM;
|
|
|
|
diff --git a/drivers/video/stm32/stm32_dsi.c b/drivers/video/stm32/stm32_dsi.c
|
|
index 12895a8..022ae96 100644
|
|
--- a/drivers/video/stm32/stm32_dsi.c
|
|
+++ b/drivers/video/stm32/stm32_dsi.c
|
|
@@ -268,7 +268,6 @@ static int dsi_get_lane_mbps(void *priv_data, struct display_timing *timings,
|
|
u32 val;
|
|
|
|
/* Update lane capabilities according to hw version */
|
|
- dsi->hw_version = dsi_read(dsi, DSI_VERSION) & VERSION;
|
|
dsi->lane_min_kbps = LANE_MIN_KBPS;
|
|
dsi->lane_max_kbps = LANE_MAX_KBPS;
|
|
if (dsi->hw_version == HWVER_131) {
|
|
@@ -351,6 +350,9 @@ static int stm32_dsi_attach(struct udevice *dev)
|
|
|
|
mplat = dev_get_platdata(priv->panel);
|
|
mplat->device = &priv->device;
|
|
+ device->lanes = mplat->lanes;
|
|
+ device->format = mplat->format;
|
|
+ device->mode_flags = mplat->mode_flags;
|
|
|
|
ret = panel_get_display_timing(priv->panel, &timings);
|
|
if (ret) {
|
|
@@ -472,6 +474,17 @@ static int stm32_dsi_probe(struct udevice *dev)
|
|
/* Reset */
|
|
reset_deassert(&rst);
|
|
|
|
+ /* check hardware version */
|
|
+ priv->hw_version = dsi_read(priv, DSI_VERSION) & VERSION;
|
|
+ if (priv->hw_version != HWVER_130 &&
|
|
+ priv->hw_version != HWVER_131) {
|
|
+ dev_err(dev, "bad dsi hardware version\n");
|
|
+ clk_disable(&clk);
|
|
+ if (IS_ENABLED(CONFIG_DM_REGULATOR))
|
|
+ regulator_set_enable(priv->vdd_reg, false);
|
|
+ return -ENODEV;
|
|
+ }
|
|
+
|
|
return 0;
|
|
err_clk:
|
|
clk_disable(&clk);
|
|
diff --git a/env/mmc.c b/env/mmc.c
|
|
index b24c35c..f64c993 100644
|
|
--- a/env/mmc.c
|
|
+++ b/env/mmc.c
|
|
@@ -24,14 +24,25 @@
|
|
|
|
DECLARE_GLOBAL_DATA_PTR;
|
|
|
|
+#if !defined(CONFIG_SYS_MMC_ENV_DEV)
|
|
+#define CONFIG_SYS_MMC_ENV_DEV 0
|
|
+#endif
|
|
+
|
|
+__weak int mmc_get_env_dev(void)
|
|
+{
|
|
+ return CONFIG_SYS_MMC_ENV_DEV;
|
|
+}
|
|
+
|
|
#if CONFIG_IS_ENABLED(OF_CONTROL)
|
|
-static inline int mmc_offset_try_partition(const char *str, s64 *val)
|
|
+static inline int mmc_offset_try_partition(const char *str, int copy, s64 *val)
|
|
{
|
|
disk_partition_t info;
|
|
struct blk_desc *desc;
|
|
int len, i, ret;
|
|
+ char dev_str[4];
|
|
|
|
- ret = blk_get_device_by_str("mmc", STR(CONFIG_SYS_MMC_ENV_DEV), &desc);
|
|
+ snprintf(dev_str, sizeof(dev_str), "%d", mmc_get_env_dev());
|
|
+ ret = blk_get_device_by_str("mmc", dev_str, &desc);
|
|
if (ret < 0)
|
|
return (ret);
|
|
|
|
@@ -45,10 +56,10 @@ static inline int mmc_offset_try_partition(const char *str, s64 *val)
|
|
}
|
|
|
|
/* round up to info.blksz */
|
|
- len = (CONFIG_ENV_SIZE + info.blksz - 1) & ~(info.blksz - 1);
|
|
+ len = DIV_ROUND_UP(CONFIG_ENV_SIZE, info.blksz);
|
|
|
|
/* use the top of the partion for the environment */
|
|
- *val = (info.start + info.size - 1) - len / info.blksz;
|
|
+ *val = (info.start + info.size - (1 + copy) * len) * info.blksz;
|
|
|
|
return 0;
|
|
}
|
|
@@ -73,7 +84,7 @@ static inline s64 mmc_offset(int copy)
|
|
str = fdtdec_get_config_string(gd->fdt_blob, dt_prop.partition);
|
|
if (str) {
|
|
/* try to place the environment at end of the partition */
|
|
- err = mmc_offset_try_partition(str, &val);
|
|
+ err = mmc_offset_try_partition(str, copy, &val);
|
|
if (!err)
|
|
return val;
|
|
}
|
|
@@ -114,11 +125,6 @@ __weak int mmc_get_env_addr(struct mmc *mmc, int copy, u32 *env_addr)
|
|
return 0;
|
|
}
|
|
|
|
-__weak int mmc_get_env_dev(void)
|
|
-{
|
|
- return CONFIG_SYS_MMC_ENV_DEV;
|
|
-}
|
|
-
|
|
#ifdef CONFIG_SYS_MMC_ENV_PART
|
|
__weak uint mmc_get_env_part(struct mmc *mmc)
|
|
{
|
|
diff --git a/include/asm-generic/gpio.h b/include/asm-generic/gpio.h
|
|
index d6cf187..ec48770 100644
|
|
--- a/include/asm-generic/gpio.h
|
|
+++ b/include/asm-generic/gpio.h
|
|
@@ -117,11 +117,14 @@ struct udevice;
|
|
struct gpio_desc {
|
|
struct udevice *dev; /* Device, NULL for invalid GPIO */
|
|
unsigned long flags;
|
|
-#define GPIOD_REQUESTED (1 << 0) /* Requested/claimed */
|
|
-#define GPIOD_IS_OUT (1 << 1) /* GPIO is an output */
|
|
-#define GPIOD_IS_IN (1 << 2) /* GPIO is an input */
|
|
-#define GPIOD_ACTIVE_LOW (1 << 3) /* value has active low */
|
|
-#define GPIOD_IS_OUT_ACTIVE (1 << 4) /* set output active */
|
|
+#define GPIOD_IS_OUT BIT(1) /* GPIO is an output */
|
|
+#define GPIOD_IS_IN BIT(2) /* GPIO is an input */
|
|
+#define GPIOD_ACTIVE_LOW BIT(3) /* GPIO is active when value is low */
|
|
+#define GPIOD_IS_OUT_ACTIVE BIT(4) /* set output active */
|
|
+#define GPIOD_OPEN_DRAIN BIT(5) /* GPIO is open drain type */
|
|
+#define GPIOD_OPEN_SOURCE BIT(6) /* GPIO is open source type */
|
|
+#define GPIOD_PULL_UP BIT(7) /* GPIO has pull-up enabled */
|
|
+#define GPIOD_PULL_DOWN BIT(8) /* GPIO has pull-down enabled */
|
|
|
|
uint offset; /* GPIO offset within the device */
|
|
/*
|
|
@@ -130,6 +133,12 @@ struct gpio_desc {
|
|
*/
|
|
};
|
|
|
|
+/* helper to compute the value of the gpio output */
|
|
+#define GPIOD_FLAGS_OUTPUT_MASK (GPIOD_ACTIVE_LOW | GPIOD_IS_OUT_ACTIVE)
|
|
+#define GPIOD_FLAGS_OUTPUT(flags) \
|
|
+ (((((flags) & GPIOD_FLAGS_OUTPUT_MASK) == GPIOD_IS_OUT_ACTIVE) || \
|
|
+ (((flags) & GPIOD_FLAGS_OUTPUT_MASK) == GPIOD_ACTIVE_LOW)))
|
|
+
|
|
/**
|
|
* dm_gpio_is_valid() - Check if a GPIO is valid
|
|
*
|
|
@@ -254,8 +263,6 @@ struct dm_gpio_ops {
|
|
int value);
|
|
int (*get_value)(struct udevice *dev, unsigned offset);
|
|
int (*set_value)(struct udevice *dev, unsigned offset, int value);
|
|
- int (*get_open_drain)(struct udevice *dev, unsigned offset);
|
|
- int (*set_open_drain)(struct udevice *dev, unsigned offset, int value);
|
|
/**
|
|
* get_function() Get the GPIO function
|
|
*
|
|
@@ -290,6 +297,37 @@ struct dm_gpio_ops {
|
|
*/
|
|
int (*xlate)(struct udevice *dev, struct gpio_desc *desc,
|
|
struct ofnode_phandle_args *args);
|
|
+
|
|
+ /**
|
|
+ * set_dir_flags() - Set GPIO dir flags
|
|
+ *
|
|
+ * This function should set up the GPIO configuration according to the
|
|
+ * information provide by the direction flags bitfield.
|
|
+ *
|
|
+ * This method is optional.
|
|
+ *
|
|
+ * @dev: GPIO device
|
|
+ * @offset: GPIO offset within that device
|
|
+ * @flags: GPIO configuration to use
|
|
+ * @return 0 if OK, -ve on error
|
|
+ */
|
|
+ int (*set_dir_flags)(struct udevice *dev, unsigned int offset,
|
|
+ ulong flags);
|
|
+
|
|
+ /**
|
|
+ * get_dir_flags() - Get GPIO dir flags
|
|
+ *
|
|
+ * This function return the GPIO direction flags used.
|
|
+ *
|
|
+ * This method is optional.
|
|
+ *
|
|
+ * @dev: GPIO device
|
|
+ * @offset: GPIO offset within that device
|
|
+ * @flags: place to put the used direction flags by GPIO
|
|
+ * @return 0 if OK, -ve on error
|
|
+ */
|
|
+ int (*get_dir_flags)(struct udevice *dev, unsigned int offset,
|
|
+ ulong *flags);
|
|
};
|
|
|
|
/**
|
|
@@ -587,63 +625,41 @@ int dm_gpio_get_value(const struct gpio_desc *desc);
|
|
int dm_gpio_set_value(const struct gpio_desc *desc, int value);
|
|
|
|
/**
|
|
- * dm_gpio_get_open_drain() - Check if open-drain-mode of a GPIO is active
|
|
- *
|
|
- * This checks if open-drain-mode for a GPIO is enabled or not. This method is
|
|
- * optional.
|
|
- *
|
|
- * @desc: GPIO description containing device, offset and flags,
|
|
- * previously returned by gpio_request_by_name()
|
|
- * @return Value of open drain mode for GPIO (0 for inactive, 1 for active) or
|
|
- * -ve on error
|
|
- */
|
|
-int dm_gpio_get_open_drain(struct gpio_desc *desc);
|
|
-
|
|
-/**
|
|
- * dm_gpio_set_open_drain() - Switch open-drain-mode of a GPIO on or off
|
|
- *
|
|
- * This enables or disables open-drain mode for a GPIO. This method is
|
|
- * optional; if the driver does not support it, nothing happens when the method
|
|
- * is called.
|
|
+ * dm_gpio_set_dir() - Set the direction for a GPIO
|
|
*
|
|
- * In open-drain mode, instead of actively driving the output (Push-pull
|
|
- * output), the GPIO's pin is connected to the collector (for a NPN transistor)
|
|
- * or the drain (for a MOSFET) of a transistor, respectively. The pin then
|
|
- * either forms an open circuit or a connection to ground, depending on the
|
|
- * state of the transistor.
|
|
+ * This sets up the direction according to the GPIO flags: desc->flags.
|
|
*
|
|
* @desc: GPIO description containing device, offset and flags,
|
|
* previously returned by gpio_request_by_name()
|
|
* @return 0 if OK, -ve on error
|
|
*/
|
|
-int dm_gpio_set_open_drain(struct gpio_desc *desc, int value);
|
|
+int dm_gpio_set_dir(struct gpio_desc *desc);
|
|
|
|
/**
|
|
- * dm_gpio_set_dir() - Set the direction for a GPIO
|
|
+ * dm_gpio_set_dir_flags() - Set direction using description and added flags
|
|
*
|
|
- * This sets up the direction according tot the provided flags. It will do
|
|
- * nothing unless the direction is actually specified.
|
|
+ * This sets up the direction according to the provided flags and the GPIO
|
|
+ * description (desc->flags) which include direction information.
|
|
+ * Note that desc->flags is updated by this function.
|
|
*
|
|
* @desc: GPIO description containing device, offset and flags,
|
|
* previously returned by gpio_request_by_name()
|
|
- * @return 0 if OK, -ve on error
|
|
+ * @flags: New flags to use
|
|
+ * @return 0 if OK, -ve on error, in which case desc->flags is not updated
|
|
*/
|
|
-int dm_gpio_set_dir(struct gpio_desc *desc);
|
|
+int dm_gpio_set_dir_flags(struct gpio_desc *desc, ulong flags);
|
|
|
|
/**
|
|
- * dm_gpio_set_dir_flags() - Set direction using specific flags
|
|
+ * dm_gpio_get_dir_flags() - Get direction flags
|
|
*
|
|
- * This is like dm_gpio_set_dir() except that the flags value is provided
|
|
- * instead of being used from desc->flags. This is needed because in many
|
|
- * cases the GPIO description does not include direction information.
|
|
- * Note that desc->flags is updated by this function.
|
|
+ * read the current direction flags
|
|
*
|
|
* @desc: GPIO description containing device, offset and flags,
|
|
* previously returned by gpio_request_by_name()
|
|
- * @flags: New flags to use
|
|
+ * @flags: place to put the used flags
|
|
* @return 0 if OK, -ve on error, in which case desc->flags is not updated
|
|
*/
|
|
-int dm_gpio_set_dir_flags(struct gpio_desc *desc, ulong flags);
|
|
+int dm_gpio_get_dir_flags(struct gpio_desc *desc, ulong *flags);
|
|
|
|
/**
|
|
* gpio_get_number() - Get the global GPIO number of a GPIO
|
|
diff --git a/include/clk.h b/include/clk.h
|
|
index a5ee53d..950b5da 100644
|
|
--- a/include/clk.h
|
|
+++ b/include/clk.h
|
|
@@ -9,6 +9,7 @@
|
|
#define _CLK_H_
|
|
|
|
#include <dm/ofnode.h>
|
|
+#include <linux/err.h>
|
|
#include <linux/errno.h>
|
|
#include <linux/types.h>
|
|
|
|
@@ -221,6 +222,8 @@ static inline int clk_get_by_index(struct udevice *dev, int index,
|
|
|
|
static inline int clk_get_bulk(struct udevice *dev, struct clk_bulk *bulk)
|
|
{
|
|
+ if (bulk)
|
|
+ bulk->count = 0;
|
|
return -ENOSYS;
|
|
}
|
|
|
|
@@ -272,6 +275,7 @@ static inline int clk_release_bulk(struct clk_bulk *bulk)
|
|
return clk_release_all(bulk->clks, bulk->count);
|
|
}
|
|
|
|
+#if CONFIG_IS_ENABLED(CLK)
|
|
/**
|
|
* clk_request - Request a clock by provider-specific ID.
|
|
*
|
|
@@ -393,19 +397,6 @@ int clk_disable_bulk(struct clk_bulk *bulk);
|
|
*/
|
|
bool clk_is_match(const struct clk *p, const struct clk *q);
|
|
|
|
-int soc_clk_dump(void);
|
|
-
|
|
-/**
|
|
- * clk_valid() - check if clk is valid
|
|
- *
|
|
- * @clk: the clock to check
|
|
- * @return true if valid, or false
|
|
- */
|
|
-static inline bool clk_valid(struct clk *clk)
|
|
-{
|
|
- return clk && !!clk->dev;
|
|
-}
|
|
-
|
|
/**
|
|
* clk_get_by_id() - Get the clock by its ID
|
|
*
|
|
@@ -425,6 +416,93 @@ int clk_get_by_id(ulong id, struct clk **clkp);
|
|
* @return true on binded, or false on no
|
|
*/
|
|
bool clk_dev_binded(struct clk *clk);
|
|
+
|
|
+#else /* CONFIG_IS_ENABLED(CLK) */
|
|
+
|
|
+static inline int clk_request(struct udevice *dev, struct clk *clk)
|
|
+{
|
|
+ return -ENOSYS;
|
|
+}
|
|
+
|
|
+static inline int clk_free(struct clk *clk)
|
|
+{
|
|
+ return -ENOSYS;
|
|
+}
|
|
+
|
|
+static inline ulong clk_get_rate(struct clk *clk)
|
|
+{
|
|
+ return -ENOSYS;
|
|
+}
|
|
+
|
|
+static inline struct clk *clk_get_parent(struct clk *clk)
|
|
+{
|
|
+ return ERR_PTR(-ENOSYS);
|
|
+}
|
|
+
|
|
+static inline long long clk_get_parent_rate(struct clk *clk)
|
|
+{
|
|
+ return -ENOSYS;
|
|
+}
|
|
+
|
|
+static inline ulong clk_set_rate(struct clk *clk, ulong rate)
|
|
+{
|
|
+ return -ENOSYS;
|
|
+}
|
|
+
|
|
+static inline int clk_set_parent(struct clk *clk, struct clk *parent)
|
|
+{
|
|
+ return -ENOSYS;
|
|
+}
|
|
+
|
|
+static inline int clk_enable(struct clk *clk)
|
|
+{
|
|
+ return -ENOSYS;
|
|
+}
|
|
+
|
|
+static inline int clk_enable_bulk(struct clk_bulk *bulk)
|
|
+{
|
|
+ return bulk && bulk->count == 0 ? 0 : -ENOSYS;
|
|
+}
|
|
+
|
|
+static inline int clk_disable(struct clk *clk)
|
|
+{
|
|
+ return -ENOSYS;
|
|
+}
|
|
+
|
|
+static inline int clk_disable_bulk(struct clk_bulk *bulk)
|
|
+{
|
|
+ return bulk && bulk->count == 0 ? 0 : -ENOSYS;
|
|
+}
|
|
+
|
|
+static inline bool clk_is_match(const struct clk *p, const struct clk *q)
|
|
+{
|
|
+ return false;
|
|
+}
|
|
+
|
|
+static inline int clk_get_by_id(ulong id, struct clk **clkp)
|
|
+{
|
|
+ return -ENOSYS;
|
|
+}
|
|
+
|
|
+static inline bool clk_dev_binded(struct clk *clk)
|
|
+{
|
|
+ return false;
|
|
+}
|
|
+#endif /* CONFIG_IS_ENABLED(CLK) */
|
|
+
|
|
+/**
|
|
+ * clk_valid() - check if clk is valid
|
|
+ *
|
|
+ * @clk: the clock to check
|
|
+ * @return true if valid, or false
|
|
+ */
|
|
+static inline bool clk_valid(struct clk *clk)
|
|
+{
|
|
+ return clk && !!clk->dev;
|
|
+}
|
|
+
|
|
+int soc_clk_dump(void);
|
|
+
|
|
#endif
|
|
|
|
#define clk_prepare_enable(clk) clk_enable(clk)
|
|
diff --git a/include/configs/odroid.h b/include/configs/odroid.h
|
|
index 77fca32..5d78825 100644
|
|
--- a/include/configs/odroid.h
|
|
+++ b/include/configs/odroid.h
|
|
@@ -64,7 +64,6 @@
|
|
""PARTS_BOOT" part 0 1;" \
|
|
""PARTS_ROOT" part 0 2\0" \
|
|
|
|
-#define CONFIG_SET_DFU_ALT_INFO
|
|
#define CONFIG_SET_DFU_ALT_BUF_LEN (SZ_1K)
|
|
|
|
#define CONFIG_DFU_ALT_BOOT_EMMC \
|
|
diff --git a/include/configs/odroid_xu3.h b/include/configs/odroid_xu3.h
|
|
index 47c3054..564319c 100644
|
|
--- a/include/configs/odroid_xu3.h
|
|
+++ b/include/configs/odroid_xu3.h
|
|
@@ -76,7 +76,6 @@
|
|
|
|
/* Enable: board/samsung/common/misc.c to use set_dfu_alt_info() */
|
|
#define CONFIG_MISC_COMMON
|
|
-#define CONFIG_SET_DFU_ALT_INFO
|
|
#define CONFIG_SET_DFU_ALT_BUF_LEN (SZ_1K)
|
|
|
|
/* Set soc_rev, soc_id, board_rev, board_name, fdtfile */
|
|
diff --git a/include/configs/omap3_igep00x0.h b/include/configs/omap3_igep00x0.h
|
|
index 4ad7dc1..8dc30be 100644
|
|
--- a/include/configs/omap3_igep00x0.h
|
|
+++ b/include/configs/omap3_igep00x0.h
|
|
@@ -71,8 +71,6 @@
|
|
|
|
#endif
|
|
|
|
-#define CONFIG_SYS_MTDPARTS_RUNTIME
|
|
-
|
|
/* OneNAND config */
|
|
#define CONFIG_USE_ONENAND_BOARD_INIT
|
|
#define CONFIG_SYS_ONENAND_BASE ONENAND_MAP
|
|
diff --git a/include/configs/stm32f429-evaluation.h b/include/configs/stm32f429-evaluation.h
|
|
index 7a17222..a715031 100644
|
|
--- a/include/configs/stm32f429-evaluation.h
|
|
+++ b/include/configs/stm32f429-evaluation.h
|
|
@@ -7,6 +7,11 @@
|
|
#ifndef __CONFIG_H
|
|
#define __CONFIG_H
|
|
|
|
+#include <linux/sizes.h>
|
|
+
|
|
+/* For booting Linux, use the first 16MB of memory */
|
|
+#define CONFIG_SYS_BOOTMAPSZ SZ_16M
|
|
+
|
|
#define CONFIG_SYS_FLASH_BASE 0x08000000
|
|
|
|
#define CONFIG_SYS_INIT_SP_ADDR 0x10010000
|
|
@@ -40,12 +45,10 @@
|
|
#define CONFIG_EXTRA_ENV_SETTINGS \
|
|
"kernel_addr_r=0x00008000\0" \
|
|
"fdtfile=stm32429i-eval.dtb\0" \
|
|
- "fdt_addr_r=0x00700000\0" \
|
|
- "scriptaddr=0x00800000\0" \
|
|
- "pxefile_addr_r=0x00800000\0" \
|
|
- "fdt_high=0xffffffffffffffff\0" \
|
|
- "initrd_high=0xffffffffffffffff\0" \
|
|
- "ramdisk_addr_r=0x00900000\0" \
|
|
+ "fdt_addr_r=0x00408000\0" \
|
|
+ "scriptaddr=0x00418000\0" \
|
|
+ "pxefile_addr_r=0x00428000\0" \
|
|
+ "ramdisk_addr_r=0x00438000\0" \
|
|
BOOTENV
|
|
|
|
/*
|
|
diff --git a/include/configs/stm32f469-discovery.h b/include/configs/stm32f469-discovery.h
|
|
index 463f1c4..8212fb6 100644
|
|
--- a/include/configs/stm32f469-discovery.h
|
|
+++ b/include/configs/stm32f469-discovery.h
|
|
@@ -7,6 +7,11 @@
|
|
#ifndef __CONFIG_H
|
|
#define __CONFIG_H
|
|
|
|
+#include <linux/sizes.h>
|
|
+
|
|
+/* For booting Linux, use the first 12MB of memory */
|
|
+#define CONFIG_SYS_BOOTMAPSZ SZ_8M + SZ_4M
|
|
+
|
|
#define CONFIG_SYS_FLASH_BASE 0x08000000
|
|
|
|
#define CONFIG_SYS_INIT_SP_ADDR 0x10010000
|
|
@@ -40,12 +45,10 @@
|
|
#define CONFIG_EXTRA_ENV_SETTINGS \
|
|
"kernel_addr_r=0x00008000\0" \
|
|
"fdtfile=stm32f469-disco.dtb\0" \
|
|
- "fdt_addr_r=0x00700000\0" \
|
|
- "scriptaddr=0x00800000\0" \
|
|
- "pxefile_addr_r=0x00800000\0" \
|
|
- "fdt_high=0xffffffffffffffff\0" \
|
|
- "initrd_high=0xffffffffffffffff\0" \
|
|
- "ramdisk_addr_r=0x00900000\0" \
|
|
+ "fdt_addr_r=0x00408000\0" \
|
|
+ "scriptaddr=0x00418000\0" \
|
|
+ "pxefile_addr_r=0x00428000\0" \
|
|
+ "ramdisk_addr_r=0x00438000\0" \
|
|
BOOTENV
|
|
|
|
/*
|
|
diff --git a/include/configs/stm32f746-disco.h b/include/configs/stm32f746-disco.h
|
|
index 337b999..45343d2 100644
|
|
--- a/include/configs/stm32f746-disco.h
|
|
+++ b/include/configs/stm32f746-disco.h
|
|
@@ -7,6 +7,11 @@
|
|
#ifndef __CONFIG_H
|
|
#define __CONFIG_H
|
|
|
|
+#include <linux/sizes.h>
|
|
+
|
|
+/* For booting Linux, use the first 6MB of memory */
|
|
+#define CONFIG_SYS_BOOTMAPSZ SZ_4M + SZ_2M
|
|
+
|
|
#define CONFIG_SYS_FLASH_BASE 0x08000000
|
|
#define CONFIG_SYS_INIT_SP_ADDR 0x20050000
|
|
|
|
@@ -48,12 +53,10 @@
|
|
#define CONFIG_EXTRA_ENV_SETTINGS \
|
|
"kernel_addr_r=0xC0008000\0" \
|
|
"fdtfile=stm32f746-disco.dtb\0" \
|
|
- "fdt_addr_r=0xC0500000\0" \
|
|
- "scriptaddr=0xC0008000\0" \
|
|
- "pxefile_addr_r=0xC0008000\0" \
|
|
- "fdt_high=0xffffffffffffffff\0" \
|
|
- "initrd_high=0xffffffffffffffff\0" \
|
|
- "ramdisk_addr_r=0xC0600000\0" \
|
|
+ "fdt_addr_r=0xC0408000\0" \
|
|
+ "scriptaddr=0xC0418000\0" \
|
|
+ "pxefile_addr_r=0xC0428000\0" \
|
|
+ "ramdisk_addr_r=0xC0438000\0" \
|
|
BOOTENV
|
|
|
|
/*
|
|
diff --git a/include/configs/stm32h743-disco.h b/include/configs/stm32h743-disco.h
|
|
index 74c69eb..39c93ee 100644
|
|
--- a/include/configs/stm32h743-disco.h
|
|
+++ b/include/configs/stm32h743-disco.h
|
|
@@ -8,6 +8,10 @@
|
|
#define __CONFIG_H
|
|
|
|
#include <config.h>
|
|
+#include <linux/sizes.h>
|
|
+
|
|
+/* For booting Linux, use the first 16MB of memory */
|
|
+#define CONFIG_SYS_BOOTMAPSZ SZ_16M
|
|
|
|
#define CONFIG_SYS_FLASH_BASE 0x08000000
|
|
#define CONFIG_SYS_INIT_SP_ADDR 0x24040000
|
|
@@ -35,12 +39,10 @@
|
|
#define CONFIG_EXTRA_ENV_SETTINGS \
|
|
"kernel_addr_r=0xD0008000\0" \
|
|
"fdtfile=stm32h743i-disco.dtb\0" \
|
|
- "fdt_addr_r=0xD0700000\0" \
|
|
- "scriptaddr=0xD0800000\0" \
|
|
- "pxefile_addr_r=0xD0800000\0" \
|
|
- "fdt_high=0xffffffffffffffff\0" \
|
|
- "initrd_high=0xffffffffffffffff\0" \
|
|
- "ramdisk_addr_r=0xD0900000\0" \
|
|
+ "fdt_addr_r=0xD0408000\0" \
|
|
+ "scriptaddr=0xD0418000\0" \
|
|
+ "pxefile_addr_r=0xD0428000\0" \
|
|
+ "ramdisk_addr_r=0xD0438000\0" \
|
|
BOOTENV
|
|
|
|
/*
|
|
diff --git a/include/configs/stm32h743-eval.h b/include/configs/stm32h743-eval.h
|
|
index b7c8492..8eb94c1 100644
|
|
--- a/include/configs/stm32h743-eval.h
|
|
+++ b/include/configs/stm32h743-eval.h
|
|
@@ -8,6 +8,10 @@
|
|
#define __CONFIG_H
|
|
|
|
#include <config.h>
|
|
+#include <linux/sizes.h>
|
|
+
|
|
+/* For booting Linux, use the first 16MB of memory */
|
|
+#define CONFIG_SYS_BOOTMAPSZ SZ_16M
|
|
|
|
#define CONFIG_SYS_FLASH_BASE 0x08000000
|
|
#define CONFIG_SYS_INIT_SP_ADDR 0x24040000
|
|
@@ -35,12 +39,10 @@
|
|
#define CONFIG_EXTRA_ENV_SETTINGS \
|
|
"kernel_addr_r=0xD0008000\0" \
|
|
"fdtfile=stm32h743i-eval.dtb\0" \
|
|
- "fdt_addr_r=0xD0700000\0" \
|
|
- "scriptaddr=0xD0800000\0" \
|
|
- "pxefile_addr_r=0xD0800000\0" \
|
|
- "fdt_high=0xffffffffffffffff\0" \
|
|
- "initrd_high=0xffffffffffffffff\0" \
|
|
- "ramdisk_addr_r=0xD0900000\0" \
|
|
+ "fdt_addr_r=0xD0408000\0" \
|
|
+ "scriptaddr=0xD0418000\0" \
|
|
+ "pxefile_addr_r=0xD0428000\0" \
|
|
+ "ramdisk_addr_r=0xD0438000\0" \
|
|
BOOTENV
|
|
|
|
/*
|
|
diff --git a/include/configs/stm32mp1.h b/include/configs/stm32mp1.h
|
|
index d42a786..7b4fe48 100644
|
|
--- a/include/configs/stm32mp1.h
|
|
+++ b/include/configs/stm32mp1.h
|
|
@@ -23,27 +23,30 @@
|
|
#define CONFIG_SYS_SDRAM_BASE STM32_DDR_BASE
|
|
#define CONFIG_SYS_INIT_SP_ADDR CONFIG_SYS_TEXT_BASE
|
|
|
|
-#ifdef CONFIG_STM32MP1_OPTEE
|
|
-#define CONFIG_SYS_MEM_TOP_HIDE SZ_32M
|
|
-#endif /* CONFIG_STM32MP1_OPTEE */
|
|
-
|
|
/*
|
|
* Console I/O buffer size
|
|
*/
|
|
#define CONFIG_SYS_CBSIZE SZ_1K
|
|
|
|
/*
|
|
- * Needed by "loadb"
|
|
+ * default load address used for command tftp, bootm , loadb, ...
|
|
*/
|
|
-#define CONFIG_SYS_LOAD_ADDR STM32_DDR_BASE
|
|
+#define CONFIG_LOADADDR 0xc2000000
|
|
+#define CONFIG_SYS_LOAD_ADDR CONFIG_LOADADDR
|
|
|
|
/* ATAGs */
|
|
#define CONFIG_CMDLINE_TAG
|
|
#define CONFIG_SETUP_MEMORY_TAGS
|
|
#define CONFIG_INITRD_TAG
|
|
|
|
+/*
|
|
+ * For booting Linux, use the first 256 MB of memory, since this is
|
|
+ * the maximum mapped by the Linux kernel during initialization.
|
|
+ */
|
|
+#define CONFIG_SYS_BOOTMAPSZ SZ_256M
|
|
+
|
|
/* Extend size of kernel image for uncompression */
|
|
-#define CONFIG_SYS_BOOTM_LEN SZ_32M
|
|
+#define CONFIG_SYS_BOOTM_LEN SZ_32M
|
|
|
|
/* SPL support */
|
|
#ifdef CONFIG_SPL
|
|
@@ -70,6 +73,11 @@
|
|
#define CONFIG_SYS_NAND_ONFI_DETECTION
|
|
#define CONFIG_SYS_MAX_NAND_DEVICE 1
|
|
|
|
+/* SPI FLASH support */
|
|
+#if defined(CONFIG_SPL_BUILD)
|
|
+#define CONFIG_SYS_SPI_U_BOOT_OFFS 0x80000
|
|
+#endif
|
|
+
|
|
/* Ethernet need */
|
|
#ifdef CONFIG_DWC_ETH_QOS
|
|
#define CONFIG_SYS_NONCACHED_MEMORY (1 * SZ_1M) /* 1M */
|
|
@@ -78,13 +86,6 @@
|
|
#define CONFIG_SYS_AUTOLOAD "no"
|
|
#endif
|
|
|
|
-/* Dynamic MTD partition support */
|
|
-#if defined(CONFIG_STM32_QSPI) || defined(CONFIG_NAND_STM32_FMC2)
|
|
-#define CONFIG_SYS_MTDPARTS_RUNTIME
|
|
-#endif
|
|
-
|
|
-#define CONFIG_SET_DFU_ALT_INFO
|
|
-
|
|
#ifdef CONFIG_DM_VIDEO
|
|
#define CONFIG_VIDEO_BMP_RLE8
|
|
#define CONFIG_BMP_16BPP
|
|
@@ -98,20 +99,44 @@
|
|
|
|
#if !defined(CONFIG_SPL_BUILD)
|
|
|
|
-#define BOOT_TARGET_DEVICES(func) \
|
|
- func(MMC, mmc, 1) \
|
|
- func(UBIFS, ubifs, 0) \
|
|
- func(MMC, mmc, 0) \
|
|
- func(MMC, mmc, 2) \
|
|
- func(PXE, pxe, na)
|
|
+#ifdef CONFIG_CMD_MMC
|
|
+#define BOOT_TARGET_MMC0(func) func(MMC, mmc, 0)
|
|
+#define BOOT_TARGET_MMC1(func) func(MMC, mmc, 1)
|
|
+#define BOOT_TARGET_MMC2(func) func(MMC, mmc, 2)
|
|
+#else
|
|
+#define BOOT_TARGET_MMC0(func)
|
|
+#define BOOT_TARGET_MMC1(func)
|
|
+#define BOOT_TARGET_MMC2(func)
|
|
+#endif
|
|
+
|
|
+#ifdef CONFIG_NET
|
|
+#define BOOT_TARGET_PXE(func) func(PXE, pxe, na)
|
|
+#else
|
|
+#define BOOT_TARGET_PXE(func)
|
|
+#endif
|
|
+
|
|
+#ifdef CONFIG_CMD_UBIFS
|
|
+#define BOOT_TARGET_UBIFS(func) func(UBIFS, ubifs, 0)
|
|
+#else
|
|
+#define BOOT_TARGET_UBIFS(func)
|
|
+#endif
|
|
+
|
|
+#define BOOT_TARGET_DEVICES(func) \
|
|
+ BOOT_TARGET_MMC1(func) \
|
|
+ BOOT_TARGET_UBIFS(func) \
|
|
+ BOOT_TARGET_MMC0(func) \
|
|
+ BOOT_TARGET_MMC2(func) \
|
|
+ BOOT_TARGET_PXE(func)
|
|
|
|
/*
|
|
* bootcmd for stm32mp1:
|
|
+ * CONFIG_BOOTCOMMAND="run bootcmd_stm32mp"
|
|
* for serial/usb: execute the stm32prog command
|
|
* for mmc boot (eMMC, SD card), boot only on the same device
|
|
- * for nand boot, boot with on ubifs partition on nand
|
|
- * for nor boot, use the default order
|
|
+ * for nand or spi-nand boot, boot with on ubifs partition on UBI partition
|
|
+ * for nor boot, use SD card = mmc0
|
|
*/
|
|
+
|
|
#define STM32MP_BOOTCMD "bootcmd_stm32mp=" \
|
|
"echo \"Boot over ${boot_device}${boot_instance}!\";" \
|
|
"if test ${boot_device} = serial || test ${boot_device} = usb;" \
|
|
@@ -120,65 +145,86 @@
|
|
"run env_check;" \
|
|
"if test ${boot_device} = mmc;" \
|
|
"then env set boot_targets \"mmc${boot_instance}\"; fi;" \
|
|
- "if test ${boot_device} = nand;" \
|
|
+ "if test ${boot_device} = nand ||" \
|
|
+ " test ${boot_device} = spi-nand ;" \
|
|
"then env set boot_targets ubifs0; fi;" \
|
|
+ "if test ${boot_device} = nor;" \
|
|
+ "then env set boot_targets mmc0; fi;" \
|
|
"run distro_bootcmd;" \
|
|
"fi;\0"
|
|
|
|
-#include <config_distro_bootcmd.h>
|
|
+/* DTIMG command added only for Android distribution */
|
|
+#ifdef CONFIG_CMD_DTIMG
|
|
+/*
|
|
+ * bootcmd for android on MMC:
|
|
+ * CONFIG_BOOTCOMMAND="run bootcmd_android"
|
|
+ * overidde DISTRO script "mmc_boot" to boot android on mmc
|
|
+ * using system_${suffix} partition (with "_a") by default
|
|
+ * - display splash screen
|
|
+ * - load device tree form dtimg
|
|
+ * - load kernel and set bootargs
|
|
+ * - start kernel
|
|
+ */
|
|
|
|
-#ifdef CONFIG_STM32MP1_OPTEE
|
|
-/* with OPTEE: define specific MTD partitions = teeh, teed, teex */
|
|
-#define STM32MP_MTDPARTS \
|
|
- "mtdparts_nor0=256k(fsbl1),256k(fsbl2),2m(ssbl),256k(u-boot-env),256k(teeh),256k(teed),256k(teex),-(nor_user)\0" \
|
|
- "mtdparts_nand0=2m(fsbl),2m(ssbl1),2m(ssbl2),512k(teeh),512k(teed),512k(teex),-(UBI)\0" \
|
|
- "mtdparts_spi-nand0=2m(fsbl),2m(ssbl1),2m(ssbl2),"\
|
|
- "512k(teeh),512k(teed),512k(teex),-(UBI)\0"
|
|
-
|
|
-#else /* CONFIG_STM32MP1_OPTEE */
|
|
-#define STM32MP_MTDPARTS \
|
|
- "mtdparts_nor0=256k(fsbl1),256k(fsbl2),2m(ssbl),256k(u-boot-env),-(nor_user)\0" \
|
|
- "mtdparts_nand0=2m(fsbl),2m(ssbl1),2m(ssbl2),-(UBI)\0" \
|
|
- "mtdparts_spi-nand0=2m(fsbl),2m(ssbl1),2m(ssbl2),-(UBI)\0"
|
|
-
|
|
-#endif /* CONFIG_STM32MP1_OPTEE */
|
|
-
|
|
-#ifndef CONFIG_SYS_MTDPARTS_RUNTIME
|
|
-#undef STM32MP_MTDPARTS
|
|
-#define STM32MP_MTDPARTS
|
|
-#endif
|
|
+#define STM32MP_ANDROID \
|
|
+ "suffix=a\0" \
|
|
+ "dtimg_addr=0xc4500000\0" \
|
|
+ "android_mmc_splash="\
|
|
+ "if part start mmc ${devnum} splash splash_start && " \
|
|
+ "part size mmc ${devnum} splash splash_size;"\
|
|
+ "then " \
|
|
+ "mmc read ${splashimage} ${splash_start} ${splash_size};" \
|
|
+ "cls; bmp display ${splashimage} m m;" \
|
|
+ "fi\0" \
|
|
+ "android_mmc_fdt="\
|
|
+ "if part start mmc ${devnum} dt_${suffix} dt_start &&" \
|
|
+ "part size mmc ${devnum} dt_${suffix} dt_size;"\
|
|
+ "then " \
|
|
+ "mmc read ${dtimg_addr} ${dt_start} ${dt_size};" \
|
|
+ "dtimg getindex ${dtimg_addr} ${board_id} ${board_rev}" \
|
|
+ " dt_index;" \
|
|
+ "dtimg start ${dtimg_addr} ${dt_index} fdt_addr_r;"\
|
|
+ "fi\0" \
|
|
+ "android_mmc_kernel="\
|
|
+ "if part start mmc ${devnum} boot_${suffix} boot_start &&" \
|
|
+ "part size mmc ${devnum} boot_${suffix} boot_size;"\
|
|
+ "then " \
|
|
+ "mmc read ${kernel_addr_r} ${boot_start} ${boot_size};" \
|
|
+ "part nb mmc ${devnum} system_${suffix} rootpart_nb;" \
|
|
+ "env set bootargs" \
|
|
+ "root=/dev/mmcblk${devnum}p${rootpart_nb} " \
|
|
+ "androidboot.serialno=${serial#} " \
|
|
+ "androidboot.slot_suffix=_${suffix};"\
|
|
+ "fi\0" \
|
|
+ "android_mmc_boot="\
|
|
+ "mmc dev ${devnum};"\
|
|
+ "run android_mmc_splash;" \
|
|
+ "run android_mmc_fdt;" \
|
|
+ "run android_mmc_kernel;" \
|
|
+ "bootm ${kernel_addr_r} - ${fdt_addr_r};\0" \
|
|
+ "bootcmd_android=" \
|
|
+ "env set mmc_boot run android_mmc_boot;" \
|
|
+ "run bootcmd_stm32mp\0"
|
|
+
|
|
+#else
|
|
+#define STM32MP_ANDROID
|
|
+#endif/* CONFIG_CMD_DTIMG */
|
|
|
|
-#define STM32MP_DFU_ALT_RAM \
|
|
- "dfu_alt_info_ram=ram 0=" \
|
|
- "uImage ram ${kernel_addr_r} 0x2000000;" \
|
|
- "devicetree.dtb ram ${fdt_addr_r} 0x100000;" \
|
|
- "uramdisk.image.gz ram ${ramdisk_addr_r} 0x10000000\0"
|
|
-
|
|
-#ifdef CONFIG_SET_DFU_ALT_INFO
|
|
-#define STM32MP_DFU_ALT_INFO \
|
|
- "dfu_alt_info_nor0=mtd nor0=" \
|
|
- "nor_fsbl1 part 1;nor_fsbl2 part 2;" \
|
|
- "nor_ssbl part 3;nor_env part 4\0" \
|
|
- "dfu_alt_info_nand0=mtd nand0="\
|
|
- "nand_fsbl part 1;nand_ssbl1 part 2;" \
|
|
- "nand_ssbl2 part 3;nand_UBI partubi 4\0" \
|
|
- "dfu_alt_info_spi-nand0=mtd spi-nand0="\
|
|
- "spi-nand_fsbl part 1;spi-nand_ssbl1 part 2;" \
|
|
- "spi-nand_ssbl2 part 3;spi-nand_UBI partubi 4\0" \
|
|
- "dfu_alt_info_mmc0=mmc 0=" \
|
|
- "sdcard_fsbl1 part 0 1;sdcard_fsbl2 part 0 2;" \
|
|
- "sdcard_ssbl part 0 3;sdcard_bootfs part 0 4;" \
|
|
- "sdcard_vendorfs part 0 5;sdcard_rootfs part 0 6;" \
|
|
- "sdcard_userfs part 0 7\0" \
|
|
- "dfu_alt_info_mmc1=mmc 1=" \
|
|
- "emmc_fsbl1 raw 0x0 0x200 mmcpart 1;" \
|
|
- "emmc_fsbl2 raw 0x0 0x200 mmcpart 2;emmc_ssbl part 1 1;" \
|
|
- "emmc_bootfs part 1 2;emmc_vendorfs part 1 3;" \
|
|
- "emmc_rootfs part 1 4;emmc_userfs part 1 5\0"
|
|
+#ifdef CONFIG_FASTBOOT_CMD_OEM_FORMAT
|
|
+/* eMMC default partitions for fastboot command: oem format */
|
|
+#define PARTS_DEFAULT \
|
|
+ "partitions=" \
|
|
+ "name=ssbl,size=2M;" \
|
|
+ "name=bootfs,size=64MB,bootable;" \
|
|
+ "name=vendorfs,size=16M;" \
|
|
+ "name=rootfs,size=746M;" \
|
|
+ "name=userfs,size=-\0"
|
|
#else
|
|
-#define STM32MP_DFU_ALT_INFO
|
|
+#define PARTS_DEFAULT
|
|
#endif
|
|
|
|
+#include <config_distro_bootcmd.h>
|
|
+
|
|
/*
|
|
* memory layout for 32M uncompressed/compressed kernel,
|
|
* 1M fdt, 1M script, 1M pxe and 1M for splashimage
|
|
@@ -192,16 +238,18 @@
|
|
"pxefile_addr_r=0xc4200000\0" \
|
|
"splashimage=0xc4300000\0" \
|
|
"ramdisk_addr_r=0xc4400000\0" \
|
|
- "fdt_high=0xffffffff\0" \
|
|
- "initrd_high=0xffffffff\0" \
|
|
"altbootcmd=run bootcmd\0" \
|
|
- "env_default=1\0" \
|
|
- "env_check=if test $env_default -eq 1;"\
|
|
- " then env set env_default 0;env save;fi\0" \
|
|
+ "env_check=" \
|
|
+ "env exists env_ver || env set env_ver ${ver};" \
|
|
+ "if env info -p -d -q; then env save; fi;" \
|
|
+ "if test \"$env_ver\" != \"$ver\"; then" \
|
|
+ " echo \"*** Warning: old environment ${env_ver}\";" \
|
|
+ " echo '* set default: env default -a; env save; reset';" \
|
|
+ " echo '* update current: env set env_ver ${ver}; env save';" \
|
|
+ "fi;\0" \
|
|
STM32MP_BOOTCMD \
|
|
- STM32MP_MTDPARTS \
|
|
- STM32MP_DFU_ALT_RAM \
|
|
- STM32MP_DFU_ALT_INFO \
|
|
+ STM32MP_ANDROID \
|
|
+ PARTS_DEFAULT \
|
|
BOOTENV \
|
|
"boot_net_usb_start=true\0"
|
|
|
|
diff --git a/include/dfu.h b/include/dfu.h
|
|
index 5649663..bb512a8 100644
|
|
--- a/include/dfu.h
|
|
+++ b/include/dfu.h
|
|
@@ -205,6 +205,9 @@ void dfu_initiated_callback(struct dfu_entity *dfu);
|
|
*/
|
|
void dfu_flush_callback(struct dfu_entity *dfu);
|
|
|
|
+int dfu_transaction_initiate(struct dfu_entity *dfu, bool read);
|
|
+void dfu_transaction_cleanup(struct dfu_entity *dfu);
|
|
+
|
|
/*
|
|
* dfu_defer_flush - pointer to store dfu_entity for deferred flashing.
|
|
* It should be NULL when not used.
|
|
diff --git a/include/dm/of_access.h b/include/dm/of_access.h
|
|
index 13fedb7..1eb1ce1 100644
|
|
--- a/include/dm/of_access.h
|
|
+++ b/include/dm/of_access.h
|
|
@@ -104,6 +104,46 @@ const void *of_get_property(const struct device_node *np, const char *name,
|
|
int *lenp);
|
|
|
|
/**
|
|
+ * of_get_first_property()- get to the pointer of the first property
|
|
+ *
|
|
+ * Get pointer to the first property of the node, it is used to iterate
|
|
+ * and read all the property with of_get_next_property_by_prop().
|
|
+ *
|
|
+ * @np: Pointer to device node
|
|
+ * @return pointer to property or NULL if not found
|
|
+ */
|
|
+const struct property *of_get_first_property(const struct device_node *np);
|
|
+
|
|
+/**
|
|
+ * of_get_next_property() - get to the pointer of the next property
|
|
+ *
|
|
+ * Get pointer to the next property of the node, it is used to iterate
|
|
+ * and read all the property with of_get_property_by_prop().
|
|
+ *
|
|
+ * @np: Pointer to device node
|
|
+ * @property: pointer of the current property
|
|
+ * @return pointer to next property or NULL if not found
|
|
+ */
|
|
+const struct property *of_get_next_property(const struct device_node *np,
|
|
+ const struct property *property);
|
|
+
|
|
+/**
|
|
+ * of_get_property_by_prop() - get a property value of a node property
|
|
+ *
|
|
+ * Get value for the property identified by node and property pointer.
|
|
+ *
|
|
+ * @node: node to read
|
|
+ * @property: pointer of the property to read
|
|
+ * @propname: place to property name on success
|
|
+ * @lenp: place to put length on success
|
|
+ * @return pointer to property value or NULL if error
|
|
+ */
|
|
+const void *of_get_property_by_prop(const struct device_node *np,
|
|
+ const struct property *property,
|
|
+ const char **name,
|
|
+ int *lenp);
|
|
+
|
|
+/**
|
|
* of_device_is_compatible() - Check if the node matches given constraints
|
|
* @device: pointer to node
|
|
* @compat: required compatible string, NULL or "" for any match
|
|
diff --git a/include/dm/ofnode.h b/include/dm/ofnode.h
|
|
index 5c4cbf0..9ee5556 100644
|
|
--- a/include/dm/ofnode.h
|
|
+++ b/include/dm/ofnode.h
|
|
@@ -59,6 +59,31 @@ struct ofnode_phandle_args {
|
|
};
|
|
|
|
/**
|
|
+ * ofprop - reference to a property of a device tree node
|
|
+ *
|
|
+ * This struct hold the reference on one property of one node,
|
|
+ * using struct ofnode and an offset within the flat device tree or either
|
|
+ * a pointer to a struct property in the live device tree.
|
|
+ *
|
|
+ * Thus we can reference arguments in both the live tree and the flat tree.
|
|
+ *
|
|
+ * The property reference can also hold a null reference. This corresponds to
|
|
+ * a struct property NULL pointer or an offset of -1.
|
|
+ *
|
|
+ * @node: Pointer to device node
|
|
+ * @offset: Pointer into flat device tree, used for flat tree.
|
|
+ * @prop: Pointer to property, used for live treee.
|
|
+ */
|
|
+
|
|
+struct ofprop {
|
|
+ ofnode node;
|
|
+ union {
|
|
+ int offset;
|
|
+ const struct property *prop;
|
|
+ };
|
|
+};
|
|
+
|
|
+/**
|
|
* _ofnode_to_np() - convert an ofnode to a live DT node pointer
|
|
*
|
|
* This cannot be called if the reference contains an offset.
|
|
@@ -543,7 +568,7 @@ int ofnode_decode_display_timing(ofnode node, int index,
|
|
struct display_timing *config);
|
|
|
|
/**
|
|
- * ofnode_get_property()- - get a pointer to the value of a node property
|
|
+ * ofnode_get_property() - get a pointer to the value of a node property
|
|
*
|
|
* @node: node to read
|
|
* @propname: property to read
|
|
@@ -553,6 +578,42 @@ int ofnode_decode_display_timing(ofnode node, int index,
|
|
const void *ofnode_get_property(ofnode node, const char *propname, int *lenp);
|
|
|
|
/**
|
|
+ * ofnode_get_first_property()- get the reference of the first property
|
|
+ *
|
|
+ * Get reference to the first property of the node, it is used to iterate
|
|
+ * and read all the property with ofnode_get_property_by_prop().
|
|
+ *
|
|
+ * @node: node to read
|
|
+ * @prop: place to put argument reference
|
|
+ * @return 0 if OK, -ve on error. -FDT_ERR_NOTFOUND if not found
|
|
+ */
|
|
+int ofnode_get_first_property(ofnode node, struct ofprop *prop);
|
|
+
|
|
+/**
|
|
+ * ofnode_get_next_property() - get the reference of the next property
|
|
+ *
|
|
+ * Get reference to the next property of the node, it is used to iterate
|
|
+ * and read all the property with ofnode_get_property_by_prop().
|
|
+ *
|
|
+ * @prop: reference of current argument and place to put reference of next one
|
|
+ * @return 0 if OK, -ve on error. -FDT_ERR_NOTFOUND if not found
|
|
+ */
|
|
+int ofnode_get_next_property(struct ofprop *prop);
|
|
+
|
|
+/**
|
|
+ * ofnode_get_property_by_prop() - get a pointer to the value of a property
|
|
+ *
|
|
+ * Get value for the property identified by the provided reference.
|
|
+ *
|
|
+ * @prop: reference on property
|
|
+ * @propname: If non-NULL, place to property name on success,
|
|
+ * @lenp: If non-NULL, place to put length on success
|
|
+ * @return 0 if OK, -ve on error. -FDT_ERR_NOTFOUND if not found
|
|
+ */
|
|
+const void *ofnode_get_property_by_prop(const struct ofprop *prop,
|
|
+ const char **propname, int *lenp);
|
|
+
|
|
+/**
|
|
* ofnode_is_available() - check if a node is marked available
|
|
*
|
|
* @node: node to check
|
|
diff --git a/include/dm/read.h b/include/dm/read.h
|
|
index d37fcb5..3c6bed7 100644
|
|
--- a/include/dm/read.h
|
|
+++ b/include/dm/read.h
|
|
@@ -466,6 +466,42 @@ int dev_read_phandle(struct udevice *dev);
|
|
const void *dev_read_prop(struct udevice *dev, const char *propname, int *lenp);
|
|
|
|
/**
|
|
+ * dev_read_first_prop()- get the reference of the first property
|
|
+ *
|
|
+ * Get reference to the first property of the node, it is used to iterate
|
|
+ * and read all the property with dev_read_prop_by_prop().
|
|
+ *
|
|
+ * @dev: device to check
|
|
+ * @prop: place to put argument reference
|
|
+ * @return 0 if OK, -ve on error. -FDT_ERR_NOTFOUND if not found
|
|
+ */
|
|
+int dev_read_first_prop(struct udevice *dev, struct ofprop *prop);
|
|
+
|
|
+/**
|
|
+ * ofnode_get_next_property() - get the reference of the next property
|
|
+ *
|
|
+ * Get reference to the next property of the node, it is used to iterate
|
|
+ * and read all the property with dev_read_prop_by_prop().
|
|
+ *
|
|
+ * @prop: reference of current argument and place to put reference of next one
|
|
+ * @return 0 if OK, -ve on error. -FDT_ERR_NOTFOUND if not found
|
|
+ */
|
|
+int dev_read_next_prop(struct ofprop *prop);
|
|
+
|
|
+/**
|
|
+ * dev_read_prop_by_prop() - get a pointer to the value of a property
|
|
+ *
|
|
+ * Get value for the property identified by the provided reference.
|
|
+ *
|
|
+ * @prop: reference on property
|
|
+ * @propname: If non-NULL, place to property name on success,
|
|
+ * @lenp: If non-NULL, place to put length on success
|
|
+ * @return 0 if OK, -ve on error. -FDT_ERR_NOTFOUND if not found
|
|
+ */
|
|
+const void *dev_read_prop_by_prop(struct ofprop *prop,
|
|
+ const char **propname, int *lenp);
|
|
+
|
|
+/**
|
|
* dev_read_alias_seq() - Get the alias sequence number of a node
|
|
*
|
|
* This works out whether a node is pointed to by an alias, and if so, the
|
|
@@ -812,6 +848,23 @@ static inline const void *dev_read_prop(struct udevice *dev,
|
|
return ofnode_get_property(dev_ofnode(dev), propname, lenp);
|
|
}
|
|
|
|
+static inline int dev_read_first_prop(struct udevice *dev, struct ofprop *prop)
|
|
+{
|
|
+ return ofnode_get_first_property(dev_ofnode(dev), prop);
|
|
+}
|
|
+
|
|
+static inline int dev_read_next_prop(struct ofprop *prop)
|
|
+{
|
|
+ return ofnode_get_next_property(prop);
|
|
+}
|
|
+
|
|
+static inline const void *dev_read_prop_by_prop(struct ofprop *prop,
|
|
+ const char **propname,
|
|
+ int *lenp)
|
|
+{
|
|
+ return ofnode_get_property_by_prop(prop, propname, lenp);
|
|
+}
|
|
+
|
|
static inline int dev_read_alias_seq(struct udevice *dev, int *devnump)
|
|
{
|
|
return fdtdec_get_alias_seq(gd->fdt_blob, dev->uclass->uc_drv->name,
|
|
@@ -889,4 +942,18 @@ static inline int dev_read_alias_highest_id(const char *stem)
|
|
ofnode_valid(subnode); \
|
|
subnode = ofnode_next_subnode(subnode))
|
|
|
|
+/**
|
|
+ * dev_for_each_property() - Helper function to iterate through property
|
|
+ *
|
|
+ * This creates a for() loop which works through the property in a device's
|
|
+ * device-tree node.
|
|
+ *
|
|
+ * @prop: struct ofprop holding the current property
|
|
+ * @dev: device to use for interation (struct udevice *)
|
|
+ */
|
|
+#define dev_for_each_property(prop, dev) \
|
|
+ for (int ret_prop = dev_read_first_prop(dev, &prop); \
|
|
+ !ret_prop; \
|
|
+ ret_prop = dev_read_next_prop(&prop))
|
|
+
|
|
#endif
|
|
diff --git a/include/dt-bindings/clock/stm32mp1-clks.h b/include/dt-bindings/clock/stm32mp1-clks.h
|
|
index 4cdaf13..ec7b1a9 100644
|
|
--- a/include/dt-bindings/clock/stm32mp1-clks.h
|
|
+++ b/include/dt-bindings/clock/stm32mp1-clks.h
|
|
@@ -179,6 +179,12 @@
|
|
#define DAC12_K 168
|
|
#define ETHPTP_K 169
|
|
|
|
+#define PCLK1 170
|
|
+#define PCLK2 171
|
|
+#define PCLK3 172
|
|
+#define PCLK4 173
|
|
+#define PCLK5 174
|
|
+
|
|
/* PLL */
|
|
#define PLL1 176
|
|
#define PLL2 177
|
|
@@ -248,4 +254,31 @@
|
|
|
|
#define STM32MP1_LAST_CLK 232
|
|
|
|
+/* SCMI clock identifiers */
|
|
+#define CK_SCMI0_HSE 0
|
|
+#define CK_SCMI0_HSI 1
|
|
+#define CK_SCMI0_CSI 2
|
|
+#define CK_SCMI0_LSE 3
|
|
+#define CK_SCMI0_LSI 4
|
|
+#define CK_SCMI0_PLL2_Q 5
|
|
+#define CK_SCMI0_PLL2_R 6
|
|
+#define CK_SCMI0_MPU 7
|
|
+#define CK_SCMI0_AXI 8
|
|
+#define CK_SCMI0_BSEC 9
|
|
+#define CK_SCMI0_CRYP1 10
|
|
+#define CK_SCMI0_GPIOZ 11
|
|
+#define CK_SCMI0_HASH1 12
|
|
+#define CK_SCMI0_I2C4 13
|
|
+#define CK_SCMI0_I2C6 14
|
|
+#define CK_SCMI0_IWDG1 15
|
|
+#define CK_SCMI0_RNG1 16
|
|
+#define CK_SCMI0_RTC 17
|
|
+#define CK_SCMI0_RTCAPB 18
|
|
+#define CK_SCMI0_SPI6 19
|
|
+#define CK_SCMI0_USART1 20
|
|
+
|
|
+#define CK_SCMI1_PLL3_Q 0
|
|
+#define CK_SCMI1_PLL3_R 1
|
|
+#define CK_SCMI1_MCU 2
|
|
+
|
|
#endif /* _DT_BINDINGS_STM32MP1_CLKS_H_ */
|
|
diff --git a/include/dt-bindings/gpio/gpio.h b/include/dt-bindings/gpio/gpio.h
|
|
index 2cc10ae..c029467 100644
|
|
--- a/include/dt-bindings/gpio/gpio.h
|
|
+++ b/include/dt-bindings/gpio/gpio.h
|
|
@@ -33,4 +33,10 @@
|
|
#define GPIO_PERSISTENT 0
|
|
#define GPIO_TRANSITORY 8
|
|
|
|
+/* Bit 4 express pull up */
|
|
+#define GPIO_PULL_UP 16
|
|
+
|
|
+/* Bit 5 express pull down */
|
|
+#define GPIO_PULL_DOWN 32
|
|
+
|
|
#endif
|
|
diff --git a/include/dt-bindings/gpio/sandbox-gpio.h b/include/dt-bindings/gpio/sandbox-gpio.h
|
|
new file mode 100644
|
|
index 0000000..e4bfdb3
|
|
--- /dev/null
|
|
+++ b/include/dt-bindings/gpio/sandbox-gpio.h
|
|
@@ -0,0 +1,24 @@
|
|
+/* SPDX-License-Identifier: GPL-2.0 */
|
|
+/*
|
|
+ * This header provides constants for binding sandbox,gpio
|
|
+ *
|
|
+ */
|
|
+#ifndef _DT_BINDINGS_GPIO_SANDBOX_GPIO_H
|
|
+#define _DT_BINDINGS_GPIO_SANDBOX_GPIO_H
|
|
+
|
|
+/*
|
|
+ * Add a specific binding for sandbox gpio.
|
|
+ * The value need to be after the generic defines of
|
|
+ * dt-bindings/gpio/gpio.h
|
|
+ */
|
|
+
|
|
+/* Bit 16 express GPIO input mode */
|
|
+#define GPIO_IN 0x10000
|
|
+
|
|
+/* Bit 17 express GPIO output mode */
|
|
+#define GPIO_OUT 0x20000
|
|
+
|
|
+/* Bit 18 express GPIO output is active */
|
|
+#define GPIO_OUT_ACTIVE 0x40000
|
|
+
|
|
+#endif
|
|
diff --git a/include/dt-bindings/mfd/stm32h7-rcc.h b/include/dt-bindings/mfd/stm32h7-rcc.h
|
|
index 06e8476..a1efc30 100644
|
|
--- a/include/dt-bindings/mfd/stm32h7-rcc.h
|
|
+++ b/include/dt-bindings/mfd/stm32h7-rcc.h
|
|
@@ -13,7 +13,6 @@
|
|
#define STM32H7_RCC_AHB3_QUADSPI 14
|
|
#define STM32H7_RCC_AHB3_SDMMC1 16
|
|
#define STM32H7_RCC_AHB3_CPU 31
|
|
-#define STM32H7_RCC_AHB3_CPU1 31
|
|
|
|
#define STM32H7_AHB3_RESET(bit) (STM32H7_RCC_AHB3_##bit + (0x7C * 8))
|
|
|
|
diff --git a/include/dt-bindings/pinctrl/stm32-pinfunc.h b/include/dt-bindings/pinctrl/stm32-pinfunc.h
|
|
index e6fb8ad..370a25a 100644
|
|
--- a/include/dt-bindings/pinctrl/stm32-pinfunc.h
|
|
+++ b/include/dt-bindings/pinctrl/stm32-pinfunc.h
|
|
@@ -26,6 +26,7 @@
|
|
#define AF14 0xf
|
|
#define AF15 0x10
|
|
#define ANALOG 0x11
|
|
+#define RSVD 0x12
|
|
|
|
/* define Pins number*/
|
|
#define PIN_NO(port, line) (((port) - 'A') * 0x10 + (line))
|
|
diff --git a/include/dt-bindings/reset/stm32mp1-resets.h b/include/dt-bindings/reset/stm32mp1-resets.h
|
|
index f0c3aae..bc71924 100644
|
|
--- a/include/dt-bindings/reset/stm32mp1-resets.h
|
|
+++ b/include/dt-bindings/reset/stm32mp1-resets.h
|
|
@@ -105,4 +105,17 @@
|
|
#define GPIOJ_R 19785
|
|
#define GPIOK_R 19786
|
|
|
|
+/* SCMI reset domain identifiers */
|
|
+#define RST_SCMI0_SPI6 0
|
|
+#define RST_SCMI0_I2C4 1
|
|
+#define RST_SCMI0_I2C6 2
|
|
+#define RST_SCMI0_USART1 3
|
|
+#define RST_SCMI0_STGEN 4
|
|
+#define RST_SCMI0_GPIOZ 5
|
|
+#define RST_SCMI0_CRYP1 6
|
|
+#define RST_SCMI0_HASH1 7
|
|
+#define RST_SCMI0_RNG1 8
|
|
+#define RST_SCMI0_MDMA 9
|
|
+#define RST_SCMI0_MCU 10
|
|
+
|
|
#endif /* _DT_BINDINGS_STM32MP1_RESET_H_ */
|
|
diff --git a/include/dt-bindings/rtc/rtc-stm32.h b/include/dt-bindings/rtc/rtc-stm32.h
|
|
new file mode 100644
|
|
index 0000000..4373c4d
|
|
--- /dev/null
|
|
+++ b/include/dt-bindings/rtc/rtc-stm32.h
|
|
@@ -0,0 +1,13 @@
|
|
+/* SPDX-License-Identifier: GPL-2.0 */
|
|
+/*
|
|
+ * This header provides constants for STM32_RTC bindings.
|
|
+ */
|
|
+
|
|
+#ifndef _DT_BINDINGS_RTC_RTC_STM32_H
|
|
+#define _DT_BINDINGS_RTC_RTC_STM32_H
|
|
+
|
|
+#define RTC_OUT1 0
|
|
+#define RTC_OUT2 1
|
|
+#define RTC_OUT2_RMP 2
|
|
+
|
|
+#endif
|
|
diff --git a/include/dt-bindings/soc/stm32-hdp.h b/include/dt-bindings/soc/stm32-hdp.h
|
|
new file mode 100644
|
|
index 0000000..d986653
|
|
--- /dev/null
|
|
+++ b/include/dt-bindings/soc/stm32-hdp.h
|
|
@@ -0,0 +1,108 @@
|
|
+/* SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) */
|
|
+/*
|
|
+ * Copyright (C) STMicroelectronics 2018 - All Rights Reserved
|
|
+ * Author: Roullier Christophe <christophe.roullier@st.com>
|
|
+ * for STMicroelectronics.
|
|
+ */
|
|
+
|
|
+#ifndef _DT_BINDINGS_STM32_HDP_H
|
|
+#define _DT_BINDINGS_STM32_HDP_H
|
|
+
|
|
+#define STM32_HDP(port, value) ((value) << ((port) * 4))
|
|
+
|
|
+/* define HDP Pins number*/
|
|
+#define HDP0_PWR_PWRWAKE_SYS 0
|
|
+#define HDP0_CM4_SLEEPDEEP 1
|
|
+#define HDP0_PWR_STDBY_WKUP 2
|
|
+#define HDP0_PWR_ENCOMP_VDDCORE 3
|
|
+#define HDP0_BSEC_OUT_SEC_NIDEN 4
|
|
+#define HDP0_RCC_CM4_SLEEPDEEP 6
|
|
+#define HDP0_GPU_DBG7 7
|
|
+#define HDP0_DDRCTRL_LP_REQ 8
|
|
+#define HDP0_PWR_DDR_RET_ENABLE_N 9
|
|
+#define HDP0_GPOVAL_0 15
|
|
+
|
|
+#define HDP1_PWR_PWRWAKE_MCU 0
|
|
+#define HDP1_CM4_HALTED 1
|
|
+#define HDP1_CA7_NAXIERRIRQ 2
|
|
+#define HDP1_PWR_OKIN_MR 3
|
|
+#define HDP1_BSEC_OUT_SEC_DBGEN 4
|
|
+#define HDP1_EXTI_SYS_WAKEUP 5
|
|
+#define HDP1_RCC_PWRDS_MPU 6
|
|
+#define HDP1_GPU_DBG6 7
|
|
+#define HDP1_DDRCTRL_DFI_CTRLUPD_REQ 8
|
|
+#define HDP1_DDRCTRL_CACTIVE_DDRC_ASR 9
|
|
+#define HDP1_GPOVAL_1 15
|
|
+
|
|
+#define HDP2_PWR_PWRWAKE_MPU 0
|
|
+#define HDP2_CM4_RXEV 1
|
|
+#define HDP2_CA7_NPMUIRQ1 2
|
|
+#define HDP2_CA7_NFIQOUT1 3
|
|
+#define HDP2_BSEC_IN_RSTCORE_N 4
|
|
+#define HDP2_EXTI_C2_WAKEUP 5
|
|
+#define HDP2_RCC_PWRDS_MCU 6
|
|
+#define HDP2_GPU_DBG5 7
|
|
+#define HDP2_DDRCTRL_DFI_INIT_COMPLETE 8
|
|
+#define HDP2_DDRCTRL_PERF_OP_IS_REFRESH 9
|
|
+#define HDP2_DDRCTRL_GSKP_DFI_LP_REQ 10
|
|
+#define HDP2_GPOVAL_2 15
|
|
+
|
|
+#define HDP3_PWR_SEL_VTH_VDD_CORE 0
|
|
+#define HDP3_CM4_TXEV 1
|
|
+#define HDP3_CA7_NPMUIRQ0 2
|
|
+#define HDP3_CA7_NFIQOUT0 3
|
|
+#define HDP3_BSEC_OUT_SEC_DFTLOCK 4
|
|
+#define HDP3_EXTI_C1_WAKEUP 5
|
|
+#define HDP3_RCC_PWRDS_SYS 6
|
|
+#define HDP3_GPU_DBG4 7
|
|
+#define HDP3_DDRCTRL_STAT_DDRC_REG_SELREF_TYPE0 8
|
|
+#define HDP3_DDRCTRL_CACTIVE_1 9
|
|
+#define HDP3_GPOVAL_3 15
|
|
+
|
|
+#define HDP4_PWR_PDDS 0
|
|
+#define HDP4_CM4_SLEEPING 1
|
|
+#define HDP4_CA7_NRESET1 2
|
|
+#define HDP4_CA7_NIRQOUT1 3
|
|
+#define HDP4_BSEC_OUT_SEC_DFTEN 4
|
|
+#define HDP4_BSEC_OUT_SEC_DBGSWENABLE 5
|
|
+#define HDP4_ETH_OUT_PMT_INTR_O 6
|
|
+#define HDP4_GPU_DBG3 7
|
|
+#define HDP4_DDRCTRL_STAT_DDRC_REG_SELREF_TYPE1 8
|
|
+#define HDP4_DDRCTRL_CACTIVE_0 9
|
|
+#define HDP4_GPOVAL_4 15
|
|
+
|
|
+#define HDP5_CA7_STANDBYWFIL2 0
|
|
+#define HDP5_PWR_VTH_VDDCORE_ACK 1
|
|
+#define HDP5_CA7_NRESET0 2
|
|
+#define HDP5_CA7_NIRQOUT0 3
|
|
+#define HDP5_BSEC_IN_PWROK 4
|
|
+#define HDP5_BSEC_OUT_SEC_DEVICEEN 5
|
|
+#define HDP5_ETH_OUT_LPI_INTR_O 6
|
|
+#define HDP5_GPU_DBG2 7
|
|
+#define HDP5_DDRCTRL_CACTIVE_DDRC 8
|
|
+#define HDP5_DDRCTRL_WR_CREDIT_CNT 9
|
|
+#define HDP5_GPOVAL_5 15
|
|
+
|
|
+#define HDP6_CA7_STANDBYWFI1 0
|
|
+#define HDP6_CA7_STANDBYWFE1 1
|
|
+#define HDP6_CA7_EVENT0 2
|
|
+#define HDP6_CA7_DBGACK1 3
|
|
+#define HDP6_BSEC_OUT_SEC_SPNIDEN 5
|
|
+#define HDP6_ETH_OUT_MAC_SPEED_O1 6
|
|
+#define HDP6_GPU_DBG1 7
|
|
+#define HDP6_DDRCTRL_CSYSACK_DDRC 8
|
|
+#define HDP6_DDRCTRL_LPR_CREDIT_CNT 9
|
|
+#define HDP6_GPOVAL_6 15
|
|
+
|
|
+#define HDP7_CA7_STANDBYWFI0 0
|
|
+#define HDP7_CA7_STANDBYWFE0 1
|
|
+#define HDP7_CA7_DBGACK0 3
|
|
+#define HDP7_BSEC_OUT_FUSE_OK 4
|
|
+#define HDP7_BSEC_OUT_SEC_SPIDEN 5
|
|
+#define HDP7_ETH_OUT_MAC_SPEED_O0 6
|
|
+#define HDP7_GPU_DBG0 7
|
|
+#define HDP7_DDRCTRL_CSYSREQ_DDRC 8
|
|
+#define HDP7_DDRCTRL_HPR_CREDIT_CNT 9
|
|
+#define HDP7_GPOVAL_7 15
|
|
+
|
|
+#endif /* _DT_BINDINGS_STM32_HDP_H */
|
|
diff --git a/include/env_internal.h b/include/env_internal.h
|
|
index 90a4df8..3f13a90 100644
|
|
--- a/include/env_internal.h
|
|
+++ b/include/env_internal.h
|
|
@@ -209,6 +209,37 @@ struct env_driver {
|
|
|
|
extern struct hsearch_data env_htab;
|
|
|
|
+/**
|
|
+ * env_ext4_get_intf() - Provide the interface for env in EXT4
|
|
+ *
|
|
+ * It is a weak function allowing board to overidde the default interface for
|
|
+ * U-Boot env in EXT4: CONFIG_ENV_EXT4_INTERFACE
|
|
+ *
|
|
+ * @return string of interface, empty if not supported
|
|
+ */
|
|
+const char *env_ext4_get_intf(void);
|
|
+
|
|
+/**
|
|
+ * env_ext4_get_dev_part() - Provide the device and partition for env in EXT4
|
|
+ *
|
|
+ * It is a weak function allowing board to overidde the default device and
|
|
+ * partition used for U-Boot env in EXT4: CONFIG_ENV_EXT4_DEVICE_AND_PART
|
|
+ *
|
|
+ * @return string of device and partition
|
|
+ */
|
|
+const char *env_ext4_get_dev_part(void);
|
|
+
|
|
+/**
|
|
+ * env_get_location()- Provide the best location for the U-Boot environment
|
|
+ *
|
|
+ * It is a weak function allowing board to overidde the environment location
|
|
+ *
|
|
+ * @op: operations performed on the environment
|
|
+ * @prio: priority between the multiple environments, 0 being the
|
|
+ * highest priority
|
|
+ * @return an enum env_location value on success, or -ve error code.
|
|
+ */
|
|
+enum env_location env_get_location(enum env_operation op, int prio);
|
|
#endif /* DO_DEPS_ONLY */
|
|
|
|
#endif /* _ENV_INTERNAL_H_ */
|
|
diff --git a/include/fastboot.h b/include/fastboot.h
|
|
index 1933b1d..966ffc6 100644
|
|
--- a/include/fastboot.h
|
|
+++ b/include/fastboot.h
|
|
@@ -36,6 +36,12 @@ enum {
|
|
#if CONFIG_IS_ENABLED(FASTBOOT_CMD_OEM_FORMAT)
|
|
FASTBOOT_COMMAND_OEM_FORMAT,
|
|
#endif
|
|
+#if CONFIG_IS_ENABLED(FASTBOOT_CMD_OEM_PARTCONF)
|
|
+ FASTBOOT_COMMAND_OEM_PARTCONF,
|
|
+#endif
|
|
+#if CONFIG_IS_ENABLED(FASTBOOT_CMD_OEM_BOOTBUS)
|
|
+ FASTBOOT_COMMAND_OEM_BOOTBUS,
|
|
+#endif
|
|
|
|
FASTBOOT_COMMAND_COUNT
|
|
};
|
|
diff --git a/include/g_dnl.h b/include/g_dnl.h
|
|
index 6d461c7..836ee60 100644
|
|
--- a/include/g_dnl.h
|
|
+++ b/include/g_dnl.h
|
|
@@ -38,6 +38,7 @@ int g_dnl_board_usb_cable_connected(void);
|
|
int g_dnl_register(const char *s);
|
|
void g_dnl_unregister(void);
|
|
void g_dnl_set_serialnumber(char *);
|
|
+void g_dnl_set_product(const char *s);
|
|
|
|
bool g_dnl_detach(void);
|
|
void g_dnl_trigger_detach(void);
|
|
diff --git a/include/i2c.h b/include/i2c.h
|
|
index 33570f5..6642480 100644
|
|
--- a/include/i2c.h
|
|
+++ b/include/i2c.h
|
|
@@ -30,6 +30,32 @@ enum dm_i2c_chip_flags {
|
|
DM_I2C_CHIP_WR_ADDRESS = 1 << 2, /* Send address for each write byte */
|
|
};
|
|
|
|
+/** enum i2c_speed_mode - standard I2C speed modes */
|
|
+enum i2c_speed_mode {
|
|
+ IC_SPEED_MODE_STANDARD,
|
|
+ IC_SPEED_MODE_FAST,
|
|
+ IC_SPEED_MODE_FAST_PLUS,
|
|
+ IC_SPEED_MODE_HIGH,
|
|
+ IC_SPEED_MODE_FAST_ULTRA,
|
|
+
|
|
+ IC_SPEED_MODE_COUNT,
|
|
+};
|
|
+
|
|
+/** enum i2c_speed_rate - standard I2C speeds in Hz */
|
|
+enum i2c_speed_rate {
|
|
+ I2C_SPEED_STANDARD_RATE = 100000,
|
|
+ I2C_SPEED_FAST_RATE = 400000,
|
|
+ I2C_SPEED_FAST_PLUS_RATE = 1000000,
|
|
+ I2C_SPEED_HIGH_RATE = 3400000,
|
|
+ I2C_SPEED_FAST_ULTRA_RATE = 5000000,
|
|
+};
|
|
+
|
|
+/** enum i2c_address_mode - available address modes */
|
|
+enum i2c_address_mode {
|
|
+ I2C_MODE_7_BIT,
|
|
+ I2C_MODE_10_BIT
|
|
+};
|
|
+
|
|
struct udevice;
|
|
/**
|
|
* struct dm_i2c_chip - information about an i2c chip
|
|
diff --git a/include/image-android-dt.h b/include/image-android-dt.h
|
|
index 9a3aa8f..f9abe85 100644
|
|
--- a/include/image-android-dt.h
|
|
+++ b/include/image-android-dt.h
|
|
@@ -17,4 +17,6 @@ bool android_dt_get_fdt_by_index(ulong hdr_addr, u32 index, ulong *addr,
|
|
void android_dt_print_contents(ulong hdr_addr);
|
|
#endif
|
|
|
|
+int android_dt_get_index(ulong hdr_addr, u32 board_id, u32 board_rev);
|
|
+
|
|
#endif /* IMAGE_ANDROID_DT_H */
|
|
diff --git a/include/mipi_dsi.h b/include/mipi_dsi.h
|
|
index f4a63b4..52a7a87 100644
|
|
--- a/include/mipi_dsi.h
|
|
+++ b/include/mipi_dsi.h
|
|
@@ -220,9 +220,15 @@ static inline int mipi_dsi_pixel_format_to_bpp(enum mipi_dsi_pixel_format fmt)
|
|
/**
|
|
* struct mipi_dsi_panel_plat - DSI panel platform data
|
|
* @device: DSI peripheral device
|
|
+ * @lanes: number of active data lanes
|
|
+ * @format: pixel format for video mode
|
|
+ * @mode_flags: DSI operation mode related flags
|
|
*/
|
|
struct mipi_dsi_panel_plat {
|
|
struct mipi_dsi_device *device;
|
|
+ unsigned int lanes;
|
|
+ enum mipi_dsi_pixel_format format;
|
|
+ unsigned long mode_flags;
|
|
};
|
|
|
|
/**
|
|
diff --git a/include/mtd.h b/include/mtd.h
|
|
index 65fcd3c..b0f8693 100644
|
|
--- a/include/mtd.h
|
|
+++ b/include/mtd.h
|
|
@@ -11,4 +11,6 @@
|
|
int mtd_probe(struct udevice *dev);
|
|
int mtd_probe_devices(void);
|
|
|
|
+void board_mtdparts_default(const char **mtdids, const char **mtdparts);
|
|
+
|
|
#endif /* _MTD_H_ */
|
|
diff --git a/include/power/stpmic1.h b/include/power/stpmic1.h
|
|
index dc8b5a7..1493a67 100644
|
|
--- a/include/power/stpmic1.h
|
|
+++ b/include/power/stpmic1.h
|
|
@@ -37,6 +37,7 @@
|
|
#define STPMIC1_BUCK_VOUT(sel) (sel << STPMIC1_BUCK_VOUT_SHIFT)
|
|
|
|
#define STPMIC1_BUCK2_1200000V STPMIC1_BUCK_VOUT(24)
|
|
+#define STPMIC1_BUCK2_1250000V STPMIC1_BUCK_VOUT(26)
|
|
#define STPMIC1_BUCK2_1350000V STPMIC1_BUCK_VOUT(30)
|
|
|
|
#define STPMIC1_BUCK3_1800000V STPMIC1_BUCK_VOUT(39)
|
|
diff --git a/include/remoteproc.h b/include/remoteproc.h
|
|
index 046cd9e..a903acb 100644
|
|
--- a/include/remoteproc.h
|
|
+++ b/include/remoteproc.h
|
|
@@ -277,6 +277,64 @@ int rproc_elf_load_image(struct udevice *dev, unsigned long addr, ulong size);
|
|
* image.
|
|
*/
|
|
ulong rproc_elf_get_boot_addr(struct udevice *dev, ulong addr);
|
|
+
|
|
+/**
|
|
+ * rproc_elf32_load_rsc_table() - load the resource table from an ELF32 image
|
|
+ *
|
|
+ * Search for the resource table in an ELF32 image, and if found, copy it to
|
|
+ * device memory.
|
|
+ *
|
|
+ * @dev: device loading the resource table
|
|
+ * @fw_addr: ELF image address
|
|
+ * @fw_size: size of the ELF image
|
|
+ * @rsc_addr: pointer to the found resource table address. Updated on
|
|
+ * operation success
|
|
+ * @rsc_size: pointer to the found resource table size. Updated on operation
|
|
+ * success
|
|
+ *
|
|
+ * @return 0 if a valid resource table is successfully loaded, -ENODATA if there
|
|
+ * is no resource table (which is optional), or another appropriate error value.
|
|
+ */
|
|
+int rproc_elf32_load_rsc_table(struct udevice *dev, ulong fw_addr,
|
|
+ ulong fw_size, ulong *rsc_addr, ulong *rsc_size);
|
|
+/**
|
|
+ * rproc_elf64_load_rsc_table() - load the resource table from an ELF64 image
|
|
+ *
|
|
+ * Search for the resource table in an ELF64 image, and if found, copy it to
|
|
+ * device memory.
|
|
+ *
|
|
+ * @dev: device loading the resource table
|
|
+ * @fw_addr: ELF image address
|
|
+ * @fw_size: size of the ELF image
|
|
+ * @rsc_addr: pointer to the found resource table address. Updated on
|
|
+ * operation success
|
|
+ * @rsc_size: pointer to the found resource table size. Updated on operation
|
|
+ * success
|
|
+ *
|
|
+ * @return 0 if a valid resource table is successfully loaded, -ENODATA if there
|
|
+ * is no resource table (which is optional), or another appropriate error value.
|
|
+ */
|
|
+int rproc_elf64_load_rsc_table(struct udevice *dev, ulong fw_addr,
|
|
+ ulong fw_size, ulong *rsc_addr, ulong *rsc_size);
|
|
+/**
|
|
+ * rproc_elf_load_rsc_table() - load the resource table from an ELF image
|
|
+ *
|
|
+ * Auto detects if the image is ELF32 or ELF64 image and search accordingly for
|
|
+ * the resource table, and if found, copy it to device memory.
|
|
+ *
|
|
+ * @dev: device loading the resource table
|
|
+ * @fw_addr: ELF image address
|
|
+ * @fw_size: size of the ELF image
|
|
+ * @rsc_addr: pointer to the found resource table address. Updated on
|
|
+ * operation success
|
|
+ * @rsc_size: pointer to the found resource table size. Updated on operation
|
|
+ * success
|
|
+ *
|
|
+ * @return 0 if a valid resource table is successfully loaded, -ENODATA if there
|
|
+ * is no resource table (which is optional), or another appropriate error value.
|
|
+ */
|
|
+int rproc_elf_load_rsc_table(struct udevice *dev, ulong fw_addr,
|
|
+ ulong fw_size, ulong *rsc_addr, ulong *rsc_size);
|
|
#else
|
|
static inline int rproc_init(void) { return -ENOSYS; }
|
|
static inline int rproc_dev_init(int id) { return -ENOSYS; }
|
|
@@ -304,6 +362,18 @@ static inline int rproc_elf_load_image(struct udevice *dev, ulong addr,
|
|
{ return -ENOSYS; }
|
|
static inline ulong rproc_elf_get_boot_addr(struct udevice *dev, ulong addr)
|
|
{ return 0; }
|
|
+static inline int rproc_elf32_load_rsc_table(struct udevice *dev, ulong fw_addr,
|
|
+ ulong fw_size, ulong *rsc_addr,
|
|
+ ulong *rsc_size)
|
|
+{ return -ENOSYS; }
|
|
+static inline int rproc_elf64_load_rsc_table(struct udevice *dev, ulong fw_addr,
|
|
+ ulong fw_size, ulong *rsc_addr,
|
|
+ ulong *rsc_size)
|
|
+{ return -ENOSYS; }
|
|
+static inline int rproc_elf_load_rsc_table(struct udevice *dev, ulong fw_addr,
|
|
+ ulong fw_size, ulong *rsc_addr,
|
|
+ ulong *rsc_size)
|
|
+{ return -ENOSYS; }
|
|
#endif
|
|
|
|
#endif /* _RPROC_H_ */
|
|
diff --git a/include/scmi_agent.h b/include/scmi_agent.h
|
|
new file mode 100644
|
|
index 0000000..78fcc3b
|
|
--- /dev/null
|
|
+++ b/include/scmi_agent.h
|
|
@@ -0,0 +1,82 @@
|
|
+/* SPDX-License-Identifier: GPL-2.0+ OR BSD-3-Clause */
|
|
+/*
|
|
+ * Copyright (c) 2015-2019, Arm Limited and Contributors. All rights reserved.
|
|
+ * Copyright (C) 2019, Linaro Limited
|
|
+ */
|
|
+#ifndef SCMI_AGENT_H
|
|
+#define SCMI_AGENT_H
|
|
+
|
|
+#include <asm/types.h>
|
|
+
|
|
+/**
|
|
+ * An SCMI agent represent on communication path from a device driver to
|
|
+ * the remote SCMI server which driver sends messages to and receives
|
|
+ * response messages from.
|
|
+ */
|
|
+struct scmi_agent;
|
|
+
|
|
+enum scmi_std_protocol {
|
|
+ SCMI_PROTOCOL_ID_BASE = 0x10,
|
|
+ SCMI_PROTOCOL_ID_POWER_DOMAIN = 0x11,
|
|
+ SCMI_PROTOCOL_ID_SYSTEM = 0x12,
|
|
+ SCMI_PROTOCOL_ID_PERF = 0x13,
|
|
+ SCMI_PROTOCOL_ID_CLOCK = 0x14,
|
|
+ SCMI_PROTOCOL_ID_SENSOR = 0x15,
|
|
+ SCMI_PROTOCOL_ID_RESET_DOMAIN = 0x16,
|
|
+};
|
|
+
|
|
+enum scmi_status_code {
|
|
+ SCMI_SUCCESS = 0,
|
|
+ SCMI_NOT_SUPPORTED = -1,
|
|
+ SCMI_INVALID_PARAMETERS = -2,
|
|
+ SCMI_DENIED = -3,
|
|
+ SCMI_NOT_FOUND = -4,
|
|
+ SCMI_OUT_OF_RANGE = -5,
|
|
+ SCMI_BUSY = -6,
|
|
+ SCMI_COMMS_ERROR = -7,
|
|
+ SCMI_GENERIC_ERROR = -8,
|
|
+ SCMI_HARDWARE_ERROR = -9,
|
|
+ SCMI_PROTOCOL_ERROR = -10,
|
|
+};
|
|
+
|
|
+/*
|
|
+ * struct scmi_msg - Context of a SCMI message sent and the response received
|
|
+ *
|
|
+ * @protocol_id: SCMI protocol ID
|
|
+ * @message_id: SCMI message ID for a defined protocol ID
|
|
+ * @in_msg: pointer to the message payload sent by the driver
|
|
+ * @in_msg_sz: byte size of the message payload sent
|
|
+ * @out_msg: pointer to buffer to store response message payload
|
|
+ * @out_msg_size: Byte size of the response buffer or payload
|
|
+ */
|
|
+struct scmi_msg {
|
|
+ unsigned int protocol_id;
|
|
+ unsigned int message_id;
|
|
+ u8 *in_msg;
|
|
+ size_t in_msg_sz;
|
|
+ u8 *out_msg;
|
|
+ size_t out_msg_sz;
|
|
+};
|
|
+
|
|
+/**
|
|
+ * scmi_send_and_process_msg() - send and process a SCMI message
|
|
+ *
|
|
+ * Send a message to a SCMI server through a target SCMI agent device.
|
|
+ * Caller sets scmi_msg::out_msg_sz to the output message buffer size.
|
|
+ * On return, scmi_msg::out_msg_sz stores the response payload size.
|
|
+ *
|
|
+ * @dev: SCMI agent device
|
|
+ * @msg: Message structure reference
|
|
+ * @return 0 on success, a negative errno otherwise
|
|
+ */
|
|
+int scmi_agent_process_msg(struct udevice *dev, struct scmi_msg *msg);
|
|
+
|
|
+/**
|
|
+ * scmi_to_linux_errno() - Convert an SCMI error code into a Linux errno code
|
|
+ *
|
|
+ * @scmi_errno: SCMI error code value
|
|
+ * @return 0 for successful status and a negative errno otherwise
|
|
+ */
|
|
+int scmi_to_linux_errno(int32_t scmi_errno);
|
|
+
|
|
+#endif /* SCMI_AGENT_H */
|
|
diff --git a/lib/libfdt/fdt_ro.c b/lib/libfdt/fdt_ro.c
|
|
index 560041b..be03aea 100644
|
|
--- a/lib/libfdt/fdt_ro.c
|
|
+++ b/lib/libfdt/fdt_ro.c
|
|
@@ -183,8 +183,8 @@ int fdt_get_mem_rsv(const void *fdt, int n, uint64_t *address, uint64_t *size)
|
|
if (fdt_chk_extra() && !re)
|
|
return -FDT_ERR_BADOFFSET;
|
|
|
|
- *address = fdt64_ld(&re->address);
|
|
- *size = fdt64_ld(&re->size);
|
|
+ *address = fdt64_to_cpu(re->address);
|
|
+ *size = fdt64_to_cpu(re->size);
|
|
return 0;
|
|
}
|
|
|
|
@@ -194,7 +194,7 @@ int fdt_num_mem_rsv(const void *fdt)
|
|
const struct fdt_reserve_entry *re;
|
|
|
|
for (i = 0; (re = fdt_mem_rsv(fdt, i)) != NULL; i++) {
|
|
- if (fdt64_ld(&re->size) == 0)
|
|
+ if (fdt64_to_cpu(re->size) == 0)
|
|
return i;
|
|
}
|
|
return -FDT_ERR_TRUNCATED;
|
|
@@ -372,7 +372,7 @@ static const struct fdt_property *fdt_get_property_by_offset_(const void *fdt,
|
|
prop = fdt_offset_ptr_(fdt, offset);
|
|
|
|
if (lenp)
|
|
- *lenp = fdt32_ld(&prop->len);
|
|
+ *lenp = fdt32_to_cpu(prop->len);
|
|
|
|
return prop;
|
|
}
|
|
@@ -410,7 +410,7 @@ static const struct fdt_property *fdt_get_property_namelen_(const void *fdt,
|
|
offset = -FDT_ERR_INTERNAL;
|
|
break;
|
|
}
|
|
- if (fdt_string_eq_(fdt, fdt32_ld(&prop->nameoff),
|
|
+ if (fdt_string_eq_(fdt, fdt32_to_cpu(prop->nameoff),
|
|
name, namelen)) {
|
|
if (poffset)
|
|
*poffset = offset;
|
|
@@ -463,7 +463,7 @@ const void *fdt_getprop_namelen(const void *fdt, int nodeoffset,
|
|
|
|
/* Handle realignment */
|
|
if (fdt_chk_version() && fdt_version(fdt) < 0x10 &&
|
|
- (poffset + sizeof(*prop)) % 8 && fdt32_ld(&prop->len) >= 8)
|
|
+ (poffset + sizeof(*prop)) % 8 && fdt32_to_cpu(prop->len) >= 8)
|
|
return prop->data + 4;
|
|
return prop->data;
|
|
}
|
|
@@ -481,7 +481,7 @@ const void *fdt_getprop_by_offset(const void *fdt, int offset,
|
|
int namelen;
|
|
|
|
if (fdt_chk_extra()) {
|
|
- name = fdt_get_string(fdt, fdt32_ld(&prop->nameoff),
|
|
+ name = fdt_get_string(fdt, fdt32_to_cpu(prop->nameoff),
|
|
&namelen);
|
|
if (!name) {
|
|
if (lenp)
|
|
@@ -490,13 +490,13 @@ const void *fdt_getprop_by_offset(const void *fdt, int offset,
|
|
}
|
|
*namep = name;
|
|
} else {
|
|
- *namep = fdt_string(fdt, fdt32_ld(&prop->nameoff));
|
|
+ *namep = fdt_string(fdt, fdt32_to_cpu(prop->nameoff));
|
|
}
|
|
}
|
|
|
|
/* Handle realignment */
|
|
if (fdt_chk_version() && fdt_version(fdt) < 0x10 &&
|
|
- (offset + sizeof(*prop)) % 8 && fdt32_ld(&prop->len) >= 8)
|
|
+ (offset + sizeof(*prop)) % 8 && fdt32_to_cpu(prop->len) >= 8)
|
|
return prop->data + 4;
|
|
return prop->data;
|
|
}
|
|
@@ -521,7 +521,7 @@ uint32_t fdt_get_phandle(const void *fdt, int nodeoffset)
|
|
return 0;
|
|
}
|
|
|
|
- return fdt32_ld(php);
|
|
+ return fdt32_to_cpu(*php);
|
|
}
|
|
|
|
const char *fdt_get_alias_namelen(const void *fdt,
|
|
diff --git a/lib/optee/optee.c b/lib/optee/optee.c
|
|
index c883c49..79b058a 100644
|
|
--- a/lib/optee/optee.c
|
|
+++ b/lib/optee/optee.c
|
|
@@ -91,7 +91,7 @@ static int optee_copy_firmware_node(const void *old_blob, void *fdt_blob)
|
|
|
|
offs = fdt_add_subnode(fdt_blob, offs, "optee");
|
|
if (offs < 0)
|
|
- return ret;
|
|
+ return offs;
|
|
|
|
/* copy the compatible property */
|
|
prop = fdt_getprop(old_blob, old_offs, "compatible", &len);
|
|
diff --git a/scripts/config_whitelist.txt b/scripts/config_whitelist.txt
|
|
index cf1808e..db089be 100644
|
|
--- a/scripts/config_whitelist.txt
|
|
+++ b/scripts/config_whitelist.txt
|
|
@@ -1547,7 +1547,6 @@ CONFIG_SETUP_MEMORY_TAGS
|
|
CONFIG_SET_BIST
|
|
CONFIG_SET_BOOTARGS
|
|
CONFIG_SET_DFU_ALT_BUF_LEN
|
|
-CONFIG_SET_DFU_ALT_INFO
|
|
CONFIG_SFIO
|
|
CONFIG_SF_DATAFLASH
|
|
CONFIG_SGI_IP28
|
|
@@ -3228,7 +3227,6 @@ CONFIG_SYS_MRAM_SIZE
|
|
CONFIG_SYS_MSC0_VAL
|
|
CONFIG_SYS_MSC1_VAL
|
|
CONFIG_SYS_MSC2_VAL
|
|
-CONFIG_SYS_MTDPARTS_RUNTIME
|
|
CONFIG_SYS_MX5_CLK32
|
|
CONFIG_SYS_MX5_HCLK
|
|
CONFIG_SYS_MX6_CLK32
|
|
diff --git a/scripts/dtc/libfdt/fdt_ro.c b/scripts/dtc/libfdt/fdt_ro.c
|
|
index e398815..d9d52e0 100644
|
|
--- a/scripts/dtc/libfdt/fdt_ro.c
|
|
+++ b/scripts/dtc/libfdt/fdt_ro.c
|
|
@@ -179,8 +179,8 @@ int fdt_get_mem_rsv(const void *fdt, int n, uint64_t *address, uint64_t *size)
|
|
if (fdt_chk_extra() && !re)
|
|
return -FDT_ERR_BADOFFSET;
|
|
|
|
- *address = fdt64_ld(&re->address);
|
|
- *size = fdt64_ld(&re->size);
|
|
+ *address = fdt64_to_cpu(re->address);
|
|
+ *size = fdt64_to_cpu(re->size);
|
|
return 0;
|
|
}
|
|
|
|
@@ -190,7 +190,7 @@ int fdt_num_mem_rsv(const void *fdt)
|
|
const struct fdt_reserve_entry *re;
|
|
|
|
for (i = 0; (re = fdt_mem_rsv(fdt, i)) != NULL; i++) {
|
|
- if (fdt64_ld(&re->size) == 0)
|
|
+ if (fdt64_to_cpu(re->size) == 0)
|
|
return i;
|
|
}
|
|
return -FDT_ERR_TRUNCATED;
|
|
@@ -368,7 +368,7 @@ static const struct fdt_property *fdt_get_property_by_offset_(const void *fdt,
|
|
prop = fdt_offset_ptr_(fdt, offset);
|
|
|
|
if (lenp)
|
|
- *lenp = fdt32_ld(&prop->len);
|
|
+ *lenp = fdt32_to_cpu(prop->len);
|
|
|
|
return prop;
|
|
}
|
|
@@ -406,7 +406,7 @@ static const struct fdt_property *fdt_get_property_namelen_(const void *fdt,
|
|
offset = -FDT_ERR_INTERNAL;
|
|
break;
|
|
}
|
|
- if (fdt_string_eq_(fdt, fdt32_ld(&prop->nameoff),
|
|
+ if (fdt_string_eq_(fdt, fdt32_to_cpu(prop->nameoff),
|
|
name, namelen)) {
|
|
if (poffset)
|
|
*poffset = offset;
|
|
@@ -459,7 +459,7 @@ const void *fdt_getprop_namelen(const void *fdt, int nodeoffset,
|
|
|
|
/* Handle realignment */
|
|
if (fdt_chk_version() && fdt_version(fdt) < 0x10 &&
|
|
- (poffset + sizeof(*prop)) % 8 && fdt32_ld(&prop->len) >= 8)
|
|
+ (poffset + sizeof(*prop)) % 8 && fdt32_to_cpu(prop->len) >= 8)
|
|
return prop->data + 4;
|
|
return prop->data;
|
|
}
|
|
@@ -477,7 +477,7 @@ const void *fdt_getprop_by_offset(const void *fdt, int offset,
|
|
int namelen;
|
|
|
|
if (fdt_chk_extra()) {
|
|
- name = fdt_get_string(fdt, fdt32_ld(&prop->nameoff),
|
|
+ name = fdt_get_string(fdt, fdt32_to_cpu(prop->nameoff),
|
|
&namelen);
|
|
if (!name) {
|
|
if (lenp)
|
|
@@ -486,13 +486,13 @@ const void *fdt_getprop_by_offset(const void *fdt, int offset,
|
|
}
|
|
*namep = name;
|
|
} else {
|
|
- *namep = fdt_string(fdt, fdt32_ld(&prop->nameoff));
|
|
+ *namep = fdt_string(fdt, fdt32_to_cpu(prop->nameoff));
|
|
}
|
|
}
|
|
|
|
/* Handle realignment */
|
|
if (fdt_chk_version() && fdt_version(fdt) < 0x10 &&
|
|
- (offset + sizeof(*prop)) % 8 && fdt32_ld(&prop->len) >= 8)
|
|
+ (offset + sizeof(*prop)) % 8 && fdt32_to_cpu(prop->len) >= 8)
|
|
return prop->data + 4;
|
|
return prop->data;
|
|
}
|
|
@@ -517,7 +517,7 @@ uint32_t fdt_get_phandle(const void *fdt, int nodeoffset)
|
|
return 0;
|
|
}
|
|
|
|
- return fdt32_ld(php);
|
|
+ return fdt32_to_cpu(*php);
|
|
}
|
|
|
|
const char *fdt_get_alias_namelen(const void *fdt,
|
|
diff --git a/scripts/dtc/libfdt/libfdt.h b/scripts/dtc/libfdt/libfdt.h
|
|
index 36fadcd..fa63fff 100644
|
|
--- a/scripts/dtc/libfdt/libfdt.h
|
|
+++ b/scripts/dtc/libfdt/libfdt.h
|
|
@@ -117,23 +117,6 @@ static inline void *fdt_offset_ptr_w(void *fdt, int offset, int checklen)
|
|
|
|
uint32_t fdt_next_tag(const void *fdt, int offset, int *nextoffset);
|
|
|
|
-/*
|
|
- * Alignment helpers:
|
|
- * These helpers access words from a device tree blob. They're
|
|
- * built to work even with unaligned pointers on platforms (ike
|
|
- * ARM) that don't like unaligned loads and stores
|
|
- */
|
|
-
|
|
-static inline uint32_t fdt32_ld(const fdt32_t *p)
|
|
-{
|
|
- const uint8_t *bp = (const uint8_t *)p;
|
|
-
|
|
- return ((uint32_t)bp[0] << 24)
|
|
- | ((uint32_t)bp[1] << 16)
|
|
- | ((uint32_t)bp[2] << 8)
|
|
- | bp[3];
|
|
-}
|
|
-
|
|
static inline void fdt32_st(void *property, uint32_t value)
|
|
{
|
|
uint8_t *bp = (uint8_t *)property;
|
|
@@ -144,20 +127,6 @@ static inline void fdt32_st(void *property, uint32_t value)
|
|
bp[3] = value & 0xff;
|
|
}
|
|
|
|
-static inline uint64_t fdt64_ld(const fdt64_t *p)
|
|
-{
|
|
- const uint8_t *bp = (const uint8_t *)p;
|
|
-
|
|
- return ((uint64_t)bp[0] << 56)
|
|
- | ((uint64_t)bp[1] << 48)
|
|
- | ((uint64_t)bp[2] << 40)
|
|
- | ((uint64_t)bp[3] << 32)
|
|
- | ((uint64_t)bp[4] << 24)
|
|
- | ((uint64_t)bp[5] << 16)
|
|
- | ((uint64_t)bp[6] << 8)
|
|
- | bp[7];
|
|
-}
|
|
-
|
|
static inline void fdt64_st(void *property, uint64_t value)
|
|
{
|
|
uint8_t *bp = (uint8_t *)property;
|
|
@@ -232,7 +201,7 @@ int fdt_next_subnode(const void *fdt, int offset);
|
|
/* General functions */
|
|
/**********************************************************************/
|
|
#define fdt_get_header(fdt, field) \
|
|
- (fdt32_ld(&((const struct fdt_header *)(fdt))->field))
|
|
+ (fdt32_to_cpu(((const struct fdt_header *)(fdt))->field))
|
|
#define fdt_magic(fdt) (fdt_get_header(fdt, magic))
|
|
#define fdt_totalsize(fdt) (fdt_get_header(fdt, totalsize))
|
|
#define fdt_off_dt_struct(fdt) (fdt_get_header(fdt, off_dt_struct))
|
|
diff --git a/test/dm/Makefile b/test/dm/Makefile
|
|
index 0c2fd5c..6a1af15 100644
|
|
--- a/test/dm/Makefile
|
|
+++ b/test/dm/Makefile
|
|
@@ -29,6 +29,7 @@ obj-$(CONFIG_LED) += led.o
|
|
obj-$(CONFIG_DM_MAILBOX) += mailbox.o
|
|
obj-$(CONFIG_DM_MMC) += mmc.o
|
|
obj-y += ofnode.o
|
|
+obj-y += ofread.o
|
|
obj-$(CONFIG_OSD) += osd.o
|
|
obj-$(CONFIG_DM_VIDEO) += panel.o
|
|
obj-$(CONFIG_DM_PCI) += pci.o
|
|
diff --git a/test/dm/gpio.c b/test/dm/gpio.c
|
|
index bb4b20c..5992d93 100644
|
|
--- a/test/dm/gpio.c
|
|
+++ b/test/dm/gpio.c
|
|
@@ -23,9 +23,9 @@ static int dm_test_gpio(struct unit_test_state *uts)
|
|
char buf[80];
|
|
|
|
/*
|
|
- * We expect to get 3 banks. One is anonymous (just numbered) and
|
|
- * comes from platdata. The other two are named a (20 gpios)
|
|
- * and b (10 gpios) and come from the device tree. See
|
|
+ * We expect to get 4 banks. One is anonymous (just numbered) and
|
|
+ * comes from platdata. The other are named a (20 gpios),
|
|
+ * b (10 gpios) and c (10 gpios) and come from the device tree. See
|
|
* test/dm/test.dts.
|
|
*/
|
|
ut_assertok(gpio_lookup_name("b4", &dev, &offset, &gpio));
|
|
@@ -73,11 +73,16 @@ static int dm_test_gpio(struct unit_test_state *uts)
|
|
ut_asserteq(1, ops->get_value(dev, offset));
|
|
|
|
/* Make it an open drain output, and reset it */
|
|
- ut_asserteq(0, sandbox_gpio_get_open_drain(dev, offset));
|
|
- ut_assertok(ops->set_open_drain(dev, offset, 1));
|
|
- ut_asserteq(1, sandbox_gpio_get_open_drain(dev, offset));
|
|
- ut_assertok(ops->set_open_drain(dev, offset, 0));
|
|
- ut_asserteq(0, sandbox_gpio_get_open_drain(dev, offset));
|
|
+ ut_asserteq(GPIOD_IS_OUT | GPIOD_IS_OUT_ACTIVE,
|
|
+ sandbox_gpio_get_dir_flags(dev, offset));
|
|
+ ut_assertok(ops->set_dir_flags(dev, offset,
|
|
+ GPIOD_IS_OUT | GPIOD_OPEN_DRAIN));
|
|
+ ut_asserteq(GPIOD_IS_OUT | GPIOD_OPEN_DRAIN,
|
|
+ sandbox_gpio_get_dir_flags(dev, offset));
|
|
+ ut_assertok(ops->set_dir_flags(dev, offset,
|
|
+ GPIOD_IS_OUT | GPIOD_IS_OUT_ACTIVE));
|
|
+ ut_asserteq(GPIOD_IS_OUT | GPIOD_IS_OUT_ACTIVE,
|
|
+ sandbox_gpio_get_dir_flags(dev, offset));
|
|
|
|
/* Make it an input */
|
|
ut_assertok(ops->direction_input(dev, offset));
|
|
@@ -214,11 +219,14 @@ static int dm_test_gpio_phandles(struct unit_test_state *uts)
|
|
desc_list2,
|
|
ARRAY_SIZE(desc_list2),
|
|
0));
|
|
+ ut_asserteq(GPIOF_INPUT, gpio_get_function(gpio_a, 4, NULL));
|
|
ut_assertok(gpio_free_list(dev, desc_list, 3));
|
|
+ ut_asserteq(GPIOF_UNUSED, gpio_get_function(gpio_a, 4, NULL));
|
|
ut_asserteq(3, gpio_request_list_by_name(dev, "test-gpios", desc_list,
|
|
ARRAY_SIZE(desc_list),
|
|
GPIOD_IS_OUT |
|
|
GPIOD_IS_OUT_ACTIVE));
|
|
+ ut_asserteq(GPIOF_OUTPUT, gpio_get_function(gpio_a, 4, NULL));
|
|
ut_asserteq_ptr(gpio_a, desc_list[0].dev);
|
|
ut_asserteq(1, desc_list[0].offset);
|
|
ut_asserteq_ptr(gpio_a, desc_list[1].dev);
|
|
@@ -228,10 +236,14 @@ static int dm_test_gpio_phandles(struct unit_test_state *uts)
|
|
ut_asserteq(1, dm_gpio_get_value(desc_list));
|
|
ut_assertok(gpio_free_list(dev, desc_list, 3));
|
|
|
|
+ ut_asserteq(GPIOD_IS_OUT | GPIOD_IS_OUT_ACTIVE,
|
|
+ sandbox_gpio_get_dir_flags(gpio_a, 1));
|
|
ut_asserteq(6, gpio_request_list_by_name(dev, "test2-gpios", desc_list,
|
|
ARRAY_SIZE(desc_list), 0));
|
|
- /* This was set to output previously, so still will be */
|
|
- ut_asserteq(GPIOF_OUTPUT, gpio_get_function(gpio_a, 1, NULL));
|
|
+
|
|
+ /* This was set to output previously but flags resetted to 0 = INPUT */
|
|
+ ut_asserteq(0, sandbox_gpio_get_dir_flags(gpio_a, 1));
|
|
+ ut_asserteq(GPIOF_INPUT, gpio_get_function(gpio_a, 1, NULL));
|
|
|
|
/* Active low should invert the input value */
|
|
ut_asserteq(GPIOF_INPUT, gpio_get_function(gpio_b, 6, NULL));
|
|
@@ -243,7 +255,42 @@ static int dm_test_gpio_phandles(struct unit_test_state *uts)
|
|
ut_asserteq(GPIOF_OUTPUT, gpio_get_function(gpio_b, 9, NULL));
|
|
ut_asserteq(1, dm_gpio_get_value(&desc_list[5]));
|
|
|
|
-
|
|
return 0;
|
|
}
|
|
DM_TEST(dm_test_gpio_phandles, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);
|
|
+
|
|
+/* Check the gpio pin configuration get from device tree information */
|
|
+static int dm_test_gpio_get_dir_flags(struct unit_test_state *uts)
|
|
+{
|
|
+ struct gpio_desc desc_list[6];
|
|
+ struct udevice *dev;
|
|
+ ulong flags;
|
|
+
|
|
+ ut_assertok(uclass_get_device(UCLASS_TEST_FDT, 0, &dev));
|
|
+
|
|
+ ut_asserteq(6, gpio_request_list_by_name(dev, "test3-gpios", desc_list,
|
|
+ ARRAY_SIZE(desc_list), 0));
|
|
+
|
|
+ ut_assertok(dm_gpio_get_dir_flags(&desc_list[0], &flags));
|
|
+ ut_asserteq(GPIOD_IS_OUT | GPIOD_OPEN_DRAIN, flags);
|
|
+
|
|
+ ut_assertok(dm_gpio_get_dir_flags(&desc_list[1], &flags));
|
|
+ ut_asserteq(GPIOD_IS_OUT | GPIOD_OPEN_SOURCE, flags);
|
|
+
|
|
+ ut_assertok(dm_gpio_get_dir_flags(&desc_list[2], &flags));
|
|
+ ut_asserteq(GPIOD_IS_OUT, flags);
|
|
+
|
|
+ ut_assertok(dm_gpio_get_dir_flags(&desc_list[3], &flags));
|
|
+ ut_asserteq(GPIOD_IS_IN | GPIOD_PULL_UP, flags);
|
|
+
|
|
+ ut_assertok(dm_gpio_get_dir_flags(&desc_list[4], &flags));
|
|
+ ut_asserteq(GPIOD_IS_IN | GPIOD_PULL_DOWN, flags);
|
|
+
|
|
+ ut_assertok(dm_gpio_get_dir_flags(&desc_list[5], &flags));
|
|
+ ut_asserteq(GPIOD_IS_IN, flags);
|
|
+
|
|
+ ut_assertok(gpio_free_list(dev, desc_list, 6));
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+DM_TEST(dm_test_gpio_get_dir_flags, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);
|
|
diff --git a/test/dm/ofread.c b/test/dm/ofread.c
|
|
new file mode 100644
|
|
index 0000000..f2a1382
|
|
--- /dev/null
|
|
+++ b/test/dm/ofread.c
|
|
@@ -0,0 +1,50 @@
|
|
+// SPDX-License-Identifier: GPL-2.0+
|
|
+
|
|
+#include <common.h>
|
|
+#include <dm.h>
|
|
+#include <dm/test.h>
|
|
+#include <test/ut.h>
|
|
+
|
|
+static int dm_test_ofnode_get_property_by_prop(struct unit_test_state *uts)
|
|
+{
|
|
+ ofnode node;
|
|
+ struct ofprop prop;
|
|
+ const void *value;
|
|
+ const char *propname;
|
|
+ int res, len, count = 0;
|
|
+
|
|
+ node = ofnode_path("/cros-ec/flash");
|
|
+ for (res = ofnode_get_first_property(node, &prop);
|
|
+ !res;
|
|
+ res = ofnode_get_next_property(&prop)) {
|
|
+ value = ofnode_get_property_by_prop(&prop, &propname, &len);
|
|
+ ut_assertnonnull(value);
|
|
+ switch (count) {
|
|
+ case 0:
|
|
+ ut_asserteq_str("image-pos", propname);
|
|
+ ut_asserteq(4, len);
|
|
+ break;
|
|
+ case 1:
|
|
+ ut_asserteq_str("size", propname);
|
|
+ ut_asserteq(4, len);
|
|
+ break;
|
|
+ case 2:
|
|
+ ut_asserteq_str("erase-value", propname);
|
|
+ ut_asserteq(4, len);
|
|
+ break;
|
|
+ case 3:
|
|
+ /* only for platdata */
|
|
+ ut_asserteq_str("name", propname);
|
|
+ ut_asserteq(6, len);
|
|
+ ut_asserteq_str("flash", value);
|
|
+ break;
|
|
+ default:
|
|
+ break;
|
|
+ }
|
|
+ count++;
|
|
+ }
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+DM_TEST(dm_test_ofnode_get_property_by_prop,
|
|
+ DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);
|
|
diff --git a/test/dm/remoteproc.c b/test/dm/remoteproc.c
|
|
index 1d9a9b3..4067596 100644
|
|
--- a/test/dm/remoteproc.c
|
|
+++ b/test/dm/remoteproc.c
|
|
@@ -103,8 +103,8 @@ static int dm_test_remoteproc_elf(struct unit_test_state *uts)
|
|
0x00, 0x00, 0x00, 0x08,
|
|
/* phoff (program header offset @ 0x40)*/
|
|
0x40, 0x00, 0x00, 0x00,
|
|
- /* shoff (section header offset : none) */
|
|
- 0x00, 0x00, 0x00, 0x00,
|
|
+ /* shoff (section header offset @ 0x90) */
|
|
+ 0x90, 0x00, 0x00, 0x00,
|
|
/* flags */
|
|
0x00, 0x00, 0x00, 0x00,
|
|
/* ehsize (elf header size = 0x34) */
|
|
@@ -113,16 +113,17 @@ static int dm_test_remoteproc_elf(struct unit_test_state *uts)
|
|
0x20, 0x00,
|
|
/* phnum (program header number : 1) */
|
|
0x01, 0x00,
|
|
- /* shentsize (section heade size : none) */
|
|
- 0x00, 0x00,
|
|
- /* shnum (section header number: none) */
|
|
- 0x00, 0x00,
|
|
- /* shstrndx (section header name section index: none) */
|
|
- 0x00, 0x00,
|
|
+ /* shentsize (section header size : 40 bytes) */
|
|
+ 0x28, 0x00,
|
|
+ /* shnum (section header number: 3) */
|
|
+ 0x02, 0x00,
|
|
+ /* shstrndx (section header name section index: 1) */
|
|
+ 0x01, 0x00,
|
|
/* padding */
|
|
0x00, 0x00, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x00,
|
|
+
|
|
/* @0x40 - PROGRAM HEADER TABLE - */
|
|
/* type : PT_LOAD */
|
|
0x01, 0x00, 0x00, 0x00,
|
|
@@ -140,14 +141,63 @@ static int dm_test_remoteproc_elf(struct unit_test_state *uts)
|
|
0x05, 0x00, 0x00, 0x00,
|
|
/* padding */
|
|
0x00, 0x00, 0x00, 0x00,
|
|
+
|
|
+ /* @0x60 - RESOURCE TABLE SECTION - */
|
|
+ /* version */
|
|
+ 0x01, 0x00, 0x00, 0x00,
|
|
+ /* num (0, no entries) */
|
|
+ 0x00, 0x00, 0x00, 0x00,
|
|
+ /* Reserved */
|
|
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
+
|
|
+ /* @0x70 - SECTION'S NAMES SECTION - */
|
|
+ /* section 0 name (".shrtrtab") */
|
|
+ 0x2e, 0x73, 0x68, 0x73, 0x74, 0x72, 0x74, 0x61, 0x62, 0x00,
|
|
+ /* section 1 name (".resource_table") */
|
|
+ 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f,
|
|
+ 0x74, 0x61, 0x62, 0x6c, 0x65, 0x00,
|
|
+ /* padding */
|
|
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
+
|
|
+ /* @0x90 - SECTION HEADER TABLE - */
|
|
+ /* Section 0 : resource table header */
|
|
+ /* sh_name - index into section header string table section */
|
|
+ 0x0a, 0x00, 0x00, 0x00,
|
|
+ /* sh_type and sh_flags */
|
|
+ 0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
|
|
+ /* sh_addr = where the resource table has to be copied to */
|
|
+ 0x00, 0x00, 0x00, 0x00,
|
|
+ /* sh_offset = 0x60 */
|
|
+ 0x60, 0x00, 0x00, 0x00,
|
|
+ /* sh_size = 16 bytes */
|
|
+ 0x10, 0x00, 0x00, 0x00,
|
|
+ /* sh_link, sh_info, sh_addralign, sh_entsize */
|
|
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
+ /* Section 1 : section's names section header */
|
|
+ /* sh_name - index into section header string table section */
|
|
+ 0x00, 0x00, 0x00, 0x00,
|
|
+ /* sh_type and sh_flags */
|
|
+ 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
+ /* sh_addr */
|
|
+ 0x00, 0x00, 0x00, 0x00,
|
|
+ /* sh_offset = 0x70 */
|
|
+ 0x70, 0x00, 0x00, 0x00,
|
|
+ /* sh_size = 27 bytes */
|
|
+ 0x1b, 0x00, 0x00, 0x00,
|
|
+ /* sh_link, sh_info, sh_addralign, sh_entsize */
|
|
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
};
|
|
unsigned int size = ARRAY_SIZE(valid_elf32);
|
|
struct udevice *dev;
|
|
- phys_addr_t loaded_firmware_paddr;
|
|
- void *loaded_firmware;
|
|
- u32 loaded_firmware_size;
|
|
+ phys_addr_t loaded_firmware_paddr, loaded_rsc_table_paddr;
|
|
+ void *loaded_firmware, *loaded_rsc_table;
|
|
+ u32 loaded_firmware_size, rsc_table_size;
|
|
+ ulong rsc_addr, rsc_size;
|
|
Elf32_Ehdr *ehdr = (Elf32_Ehdr *)valid_elf32;
|
|
Elf32_Phdr *phdr = (Elf32_Phdr *)(valid_elf32 + ehdr->e_phoff);
|
|
+ Elf32_Shdr *shdr = (Elf32_Shdr *)(valid_elf32 + ehdr->e_shoff);
|
|
|
|
ut_assertok(uclass_get_device(UCLASS_REMOTEPROC, 0, &dev));
|
|
|
|
@@ -178,6 +228,25 @@ static int dm_test_remoteproc_elf(struct unit_test_state *uts)
|
|
0x08000000);
|
|
unmap_physmem(loaded_firmware, MAP_NOCACHE);
|
|
|
|
+ /* Resource table */
|
|
+ shdr->sh_addr = CONFIG_SYS_SDRAM_BASE;
|
|
+ rsc_table_size = shdr->sh_size;
|
|
+
|
|
+ loaded_rsc_table_paddr = shdr->sh_addr + DEVICE_TO_PHYSICAL_OFFSET;
|
|
+ loaded_rsc_table = map_physmem(loaded_rsc_table_paddr,
|
|
+ rsc_table_size, MAP_NOCACHE);
|
|
+ ut_assertnonnull(loaded_rsc_table);
|
|
+ memset(loaded_rsc_table, 0, rsc_table_size);
|
|
+
|
|
+ /* Load and verify */
|
|
+ ut_assertok(rproc_elf32_load_rsc_table(dev, (ulong)valid_elf32, size,
|
|
+ &rsc_addr, &rsc_size));
|
|
+ ut_asserteq(rsc_addr, CONFIG_SYS_SDRAM_BASE);
|
|
+ ut_asserteq(rsc_size, rsc_table_size);
|
|
+ ut_assertok(memcmp(loaded_firmware, valid_elf32 + shdr->sh_offset,
|
|
+ shdr->sh_size));
|
|
+ unmap_physmem(loaded_firmware, MAP_NOCACHE);
|
|
+
|
|
/* Invalid ELF Magic */
|
|
valid_elf32[0] = 0;
|
|
ut_asserteq(-EPROTONOSUPPORT,
|
|
diff --git a/test/dm/test-fdt.c b/test/dm/test-fdt.c
|
|
index 1fb8b5c..0997d2b 100644
|
|
--- a/test/dm/test-fdt.c
|
|
+++ b/test/dm/test-fdt.c
|
|
@@ -196,7 +196,7 @@ static int dm_test_fdt(struct unit_test_state *uts)
|
|
int ret;
|
|
int i;
|
|
|
|
- ret = dm_scan_fdt(gd->fdt_blob, false);
|
|
+ ret = dm_extended_scan_fdt(gd->fdt_blob, false);
|
|
ut_assert(!ret);
|
|
|
|
ret = uclass_get(UCLASS_TEST_FDT, &uc);
|
|
@@ -227,7 +227,7 @@ static int dm_test_alias_highest_id(struct unit_test_state *uts)
|
|
ut_asserteq(5, ret);
|
|
|
|
ret = dev_read_alias_highest_id("gpio");
|
|
- ut_asserteq(2, ret);
|
|
+ ut_asserteq(3, ret);
|
|
|
|
ret = dev_read_alias_highest_id("pci");
|
|
ut_asserteq(2, ret);
|
|
diff --git a/test/py/tests/test_env.py b/test/py/tests/test_env.py
|
|
index 6ff38f1..cbdb410 100644
|
|
--- a/test/py/tests/test_env.py
|
|
+++ b/test/py/tests/test_env.py
|
|
@@ -336,3 +336,47 @@ def test_env_import_whitelist_delete(state_test_env):
|
|
unset_var(state_test_env, 'foo2')
|
|
unset_var(state_test_env, 'foo3')
|
|
unset_var(state_test_env, 'foo4')
|
|
+
|
|
+@pytest.mark.boardspec('sandbox')
|
|
+@pytest.mark.buildconfigspec('cmd_nvedit_info')
|
|
+def test_env_info(state_test_env):
|
|
+
|
|
+ """Test 'env info' command with several options.
|
|
+ """
|
|
+ c = state_test_env.u_boot_console
|
|
+
|
|
+ response = c.run_command('env info')
|
|
+ assert 'env_valid = invalid' in response
|
|
+ assert 'env_ready = true' in response
|
|
+ assert 'env_use_default = true' in response
|
|
+
|
|
+ response = c.run_command('env info -p -d')
|
|
+ assert 'Default environment is used' in response
|
|
+ assert 'Environment cannot be persisted' in response
|
|
+
|
|
+ response = c.run_command('env info -p -d -q')
|
|
+ assert response == ""
|
|
+
|
|
+@pytest.mark.boardspec('sandbox')
|
|
+@pytest.mark.buildconfigspec('cmd_nvedit_info')
|
|
+@pytest.mark.buildconfigspec('cmd_echo')
|
|
+def test_env_info_quiet(state_test_env):
|
|
+
|
|
+ """Test 'env info' quiet command result with several options for test.
|
|
+ """
|
|
+ c = state_test_env.u_boot_console
|
|
+
|
|
+ response = c.run_command('env info -d -q')
|
|
+ assert response == ""
|
|
+ response = c.run_command('echo $?')
|
|
+ assert response == "0"
|
|
+
|
|
+ response = c.run_command('env info -p -q')
|
|
+ assert response == ""
|
|
+ response = c.run_command('echo $?')
|
|
+ assert response == "1"
|
|
+
|
|
+ response = c.run_command('env info -d -p -q')
|
|
+ assert response == ""
|
|
+ response = c.run_command('echo $?')
|
|
+ assert response == "1"
|
|
diff --git a/test/py/tests/test_pinmux.py b/test/py/tests/test_pinmux.py
|
|
index 25394f1..4e6df99 100644
|
|
--- a/test/py/tests/test_pinmux.py
|
|
+++ b/test/py/tests/test_pinmux.py
|
|
@@ -22,11 +22,21 @@ def test_pinmux_usage_2(u_boot_console):
|
|
def test_pinmux_status_all(u_boot_console):
|
|
"""Test that 'pinmux status -a' displays pin's muxing."""
|
|
output = u_boot_console.run_command('pinmux status -a')
|
|
- assert ('SCL : I2C SCL' in output)
|
|
- assert ('SDA : I2C SDA' in output)
|
|
- assert ('TX : Uart TX' in output)
|
|
- assert ('RX : Uart RX' in output)
|
|
- assert ('W1 : 1-wire gpio' in output)
|
|
+
|
|
+ assert ('pinctrl-gpio:' in output)
|
|
+ assert ('a5 : gpio output .' in output)
|
|
+ assert ('a6 : gpio output .' in output)
|
|
+
|
|
+ assert ('pinctrl:' in output)
|
|
+ assert ('SCL : I2C SCL.' in output)
|
|
+ assert ('SDA : I2C SDA.' in output)
|
|
+ assert ('TX : Uart TX.' in output)
|
|
+ assert ('RX : Uart RX.' in output)
|
|
+ assert ('W1 : 1-wire gpio.' in output)
|
|
+ assert ('GPIO0 : gpio bias-pull-up input-disable.' in output)
|
|
+ assert ('GPIO1 : gpio drive-open-drain.' in output)
|
|
+ assert ('GPIO2 : gpio bias-pull-down input-enable.' in output)
|
|
+ assert ('GPIO3 : gpio bias-disable.' in output)
|
|
|
|
@pytest.mark.buildconfigspec('cmd_pinmux')
|
|
@pytest.mark.boardspec('sandbox')
|
|
@@ -59,8 +69,16 @@ def test_pinmux_status(u_boot_console):
|
|
"""Test that 'pinmux status' displays selected pincontroller's pin
|
|
muxing descriptions."""
|
|
output = u_boot_console.run_command('pinmux status')
|
|
- assert ('SCL : I2C SCL' in output)
|
|
- assert ('SDA : I2C SDA' in output)
|
|
- assert ('TX : Uart TX' in output)
|
|
- assert ('RX : Uart RX' in output)
|
|
- assert ('W1 : 1-wire gpio' in output)
|
|
+
|
|
+ assert (not 'pinctrl-gpio:' in output)
|
|
+ assert (not 'pinctrl:' in output)
|
|
+
|
|
+ assert ('SCL : I2C SCL.' in output)
|
|
+ assert ('SDA : I2C SDA.' in output)
|
|
+ assert ('TX : Uart TX.' in output)
|
|
+ assert ('RX : Uart RX.' in output)
|
|
+ assert ('W1 : 1-wire gpio.' in output)
|
|
+ assert ('GPIO0 : gpio bias-pull-up input-disable.' in output)
|
|
+ assert ('GPIO1 : gpio drive-open-drain.' in output)
|
|
+ assert ('GPIO2 : gpio bias-pull-down input-enable.' in output)
|
|
+ assert ('GPIO3 : gpio bias-disable.' in output)
|
|
diff --git a/tools/fdtgrep.c b/tools/fdtgrep.c
|
|
index 8f44f59..2a8058f 100644
|
|
--- a/tools/fdtgrep.c
|
|
+++ b/tools/fdtgrep.c
|
|
@@ -805,7 +805,7 @@ static int do_fdtgrep(struct display_info *disp, const char *filename)
|
|
* we do another pass to actually record them.
|
|
*/
|
|
for (i = 0; i < 2; i++) {
|
|
- region = malloc(count * sizeof(struct fdt_region));
|
|
+ region = realloc(region, count * sizeof(struct fdt_region));
|
|
if (!region) {
|
|
fprintf(stderr, "Out of memory for %d regions\n",
|
|
count);
|
|
@@ -823,8 +823,10 @@ static int do_fdtgrep(struct display_info *disp, const char *filename)
|
|
}
|
|
if (count <= max_regions)
|
|
break;
|
|
+ }
|
|
+ if (count > max_regions) {
|
|
free(region);
|
|
- fprintf(stderr, "Internal error with fdtgrep_find_region)(\n");
|
|
+ fprintf(stderr, "Internal error with fdtgrep_find_region()\n");
|
|
return -1;
|
|
}
|
|
|
|
diff --git a/tools/stm32image.c b/tools/stm32image.c
|
|
index ff3ec5f..18357c0 100644
|
|
--- a/tools/stm32image.c
|
|
+++ b/tools/stm32image.c
|
|
@@ -45,7 +45,7 @@ static void stm32image_default_header(struct stm32_header *ptr)
|
|
ptr->magic_number = HEADER_MAGIC;
|
|
ptr->header_version[VER_MAJOR_IDX] = HEADER_VERSION_V1;
|
|
ptr->option_flags = HEADER_DEFAULT_OPTION;
|
|
- ptr->ecdsa_algorithm = 1;
|
|
+ ptr->ecdsa_algorithm = cpu_to_le32(1);
|
|
ptr->binary_type = HEADER_TYPE_UBOOT;
|
|
}
|
|
|
|
@@ -131,7 +131,8 @@ static void stm32image_set_header(void *ptr, struct stat *sbuf, int ifd,
|
|
stm32hdr->image_entry_point = cpu_to_le32(params->ep);
|
|
stm32hdr->image_length = cpu_to_le32((uint32_t)sbuf->st_size -
|
|
sizeof(struct stm32_header));
|
|
- stm32hdr->image_checksum = stm32image_checksum(ptr, sbuf->st_size);
|
|
+ stm32hdr->image_checksum =
|
|
+ cpu_to_le32(stm32image_checksum(ptr, sbuf->st_size));
|
|
}
|
|
|
|
/*
|
|
--
|
|
2.7.4
|
|
|