summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Documentation/boards/stm32mp.rst28
-rw-r--r--Makefile2
-rw-r--r--arch/arm/Kconfig19
-rw-r--r--arch/arm/boards/stm32mp157c-dk2/board.c13
-rw-r--r--arch/arm/boards/zii-common/board.c3
-rw-r--r--arch/arm/boards/zii-common/switch-cmd.c2
-rw-r--r--arch/arm/configs/socfpga-arria10_defconfig1
-rw-r--r--arch/arm/configs/stm32mp_defconfig23
-rw-r--r--arch/arm/cpu/Makefile1
-rw-r--r--arch/arm/cpu/psci-client.c190
-rw-r--r--arch/arm/cpu/psci.c46
-rw-r--r--arch/arm/dts/stm32mp157a-dk1.dtsi17
-rw-r--r--arch/arm/dts/stm32mp157c.dtsi8
-rw-r--r--arch/arm/include/asm/psci.h23
-rw-r--r--arch/arm/lib/pbl.lds.S2
-rw-r--r--arch/arm/mach-socfpga/include/mach/arria10-clock-manager.h1
-rw-r--r--arch/arm/mach-socfpga/include/mach/arria10-reset-manager.h4
-rw-r--r--arch/arm/mach-socfpga/include/mach/arria10-xload.h1
-rw-r--r--arch/arm/mach-socfpga/include/mach/cyclone5-system-manager.h11
-rw-r--r--arch/arm/mach-stm32mp/Kconfig2
-rw-r--r--arch/arm/mach-stm32mp/Makefile3
-rw-r--r--arch/arm/mach-stm32mp/include/mach/bbu.h14
-rw-r--r--arch/arm/mach-stm32mp/include/mach/bootsource.h33
-rw-r--r--arch/arm/mach-stm32mp/include/mach/bsec.h41
-rw-r--r--arch/arm/mach-stm32mp/include/mach/revision.h32
-rw-r--r--arch/arm/mach-stm32mp/include/mach/smc.h28
-rw-r--r--arch/arm/mach-stm32mp/init.c260
-rw-r--r--arch/mips/boot/main_entry.c6
-rw-r--r--arch/mips/include/asm/cache.h1
-rw-r--r--arch/mips/lib/cpu-probe.c5
-rw-r--r--arch/mips/lib/reloc.c8
-rw-r--r--arch/mips/mach-loongson/include/mach/loongson1.h50
-rw-r--r--arch/mips/mach-loongson/include/mach/regs-clk.h81
-rw-r--r--arch/mips/mach-loongson/include/mach/regs-mux.h124
-rw-r--r--arch/mips/mach-loongson/include/mach/regs-pwm.h25
-rw-r--r--arch/mips/mach-loongson/include/mach/regs-rtc.h19
-rw-r--r--arch/mips/mach-loongson/include/mach/regs-wdt.h15
-rw-r--r--arch/mips/mach-loongson/loongson1_reset.c6
-rw-r--r--arch/sandbox/board/dev-random.c7
-rw-r--r--arch/sandbox/mach-sandbox/include/mach/linux.h1
-rw-r--r--arch/sandbox/os/common.c10
-rw-r--r--arch/x86/include/asm/linkage.h6
-rw-r--r--arch/x86/mach-efi/reloc_x86_64.c3
-rw-r--r--commands/Kconfig6
-rw-r--r--commands/cp.c3
-rw-r--r--commands/edit.c166
-rw-r--r--common/Kconfig6
-rw-r--r--common/efi-devicepath.c2
-rw-r--r--common/efi-guid.c2
-rw-r--r--common/efi/efi.c3
-rw-r--r--common/partitions.c4
-rw-r--r--drivers/block/efi-block-io.c17
-rw-r--r--drivers/efi/efi-device.c10
-rw-r--r--drivers/hw_random/Kconfig6
-rw-r--r--drivers/mci/Kconfig9
-rw-r--r--drivers/mci/Makefile1
-rw-r--r--drivers/mci/stm32_sdmmc2.c672
-rw-r--r--drivers/mfd/stpmic1.c1
-rw-r--r--drivers/mfd/superio.c2
-rw-r--r--drivers/net/Kconfig27
-rw-r--r--drivers/net/Makefile3
-rw-r--r--drivers/net/designware.h1
-rw-r--r--drivers/net/designware_eqos.c876
-rw-r--r--drivers/net/designware_eqos.h84
-rw-r--r--drivers/net/designware_socfpga.c133
-rw-r--r--drivers/net/designware_stm32.c245
-rw-r--r--drivers/net/designware_tegra186.c347
-rw-r--r--drivers/nvmem/Kconfig8
-rw-r--r--drivers/nvmem/Makefile5
-rw-r--r--drivers/nvmem/bsec.c221
-rw-r--r--drivers/of/of_gpio.c6
-rw-r--r--drivers/of/of_path.c2
-rw-r--r--drivers/pinctrl/pinctrl-at91-pio4.c4
-rw-r--r--drivers/pinctrl/pinctrl-bcm2835.c2
-rw-r--r--drivers/pinctrl/pinctrl-stm32.c182
-rw-r--r--drivers/regulator/Kconfig9
-rw-r--r--drivers/regulator/Makefile4
-rw-r--r--drivers/regulator/helpers.c186
-rw-r--r--drivers/regulator/of_regulator.c229
-rw-r--r--drivers/regulator/stpmic1_regulator.c436
-rw-r--r--drivers/serial/efi-stdio.c78
-rw-r--r--drivers/serial/efi-stdio.h58
-rw-r--r--drivers/serial/serial_cadence.c2
-rw-r--r--drivers/usb/storage/usb.c7
-rw-r--r--drivers/watchdog/stpmic1_wdt.c5
-rw-r--r--dts/Bindings/arm/rockchip.yaml4
-rw-r--r--dts/Bindings/interrupt-controller/atmel,aic.txt7
-rw-r--r--dts/Bindings/media/allwinner,sun4i-a10-csi.yaml9
-rw-r--r--dts/Bindings/pinctrl/aspeed,ast2600-pinctrl.yaml86
-rw-r--r--dts/Bindings/regulator/fixed-regulator.yaml4
-rw-r--r--dts/Bindings/riscv/cpus.yaml29
-rw-r--r--dts/src/arc/hsdk.dts23
-rw-r--r--dts/src/arm/am3874-iceboard.dts9
-rw-r--r--dts/src/arm/bcm2835-rpi-zero-w.dts1
-rw-r--r--dts/src/arm/bcm2837-rpi-cm3.dtsi8
-rw-r--r--dts/src/arm/imx6-logicpd-som.dtsi4
-rw-r--r--dts/src/arm/imx7s.dtsi8
-rw-r--r--dts/src/arm/logicpd-torpedo-som.dtsi4
-rw-r--r--dts/src/arm/mt7629-rfb.dts13
-rw-r--r--dts/src/arm/mt7629.dtsi2
-rw-r--r--dts/src/arm/omap4-droid4-xt894.dts2
-rw-r--r--dts/src/arm/omap4-panda-common.dtsi2
-rw-r--r--dts/src/arm/omap4-sdp.dts2
-rw-r--r--dts/src/arm/omap4-var-som-om44-wlan.dtsi2
-rw-r--r--dts/src/arm/omap5-board-common.dtsi2
-rw-r--r--dts/src/arm/omap54xx-clocks.dtsi2
-rw-r--r--dts/src/arm/stm32mp157-pinctrl.dtsi8
-rw-r--r--dts/src/arm/sun7i-a20.dtsi5
-rw-r--r--dts/src/arm/vf610-zii-scu4-aib.dts2
-rw-r--r--dts/src/arm64/allwinner/sun50i-a64-pine64-plus.dts9
-rw-r--r--dts/src/arm64/allwinner/sun50i-a64-sopine-baseboard.dts6
-rw-r--r--dts/src/arm64/allwinner/sun50i-a64.dtsi9
-rw-r--r--dts/src/arm64/broadcom/stingray/stingray-pinctrl.dtsi5
-rw-r--r--dts/src/arm64/broadcom/stingray/stingray.dtsi3
-rw-r--r--dts/src/arm64/freescale/fsl-lx2160a.dtsi36
-rw-r--r--dts/src/arm64/freescale/imx8mm.dtsi6
-rw-r--r--dts/src/arm64/freescale/imx8mn.dtsi6
-rw-r--r--dts/src/arm64/freescale/imx8mq-zii-ultra.dtsi4
-rw-r--r--dts/src/arm64/freescale/imx8mq.dtsi4
-rw-r--r--dts/src/arm64/marvell/armada-3720-turris-mox.dts13
-rw-r--r--dts/src/arm64/rockchip/rk3399-gru-kevin.dts2
-rw-r--r--dts/src/arm64/rockchip/rk3399-hugsun-x99.dts4
-rw-r--r--dts/src/arm64/rockchip/rk3399-rockpro64.dts12
-rw-r--r--dts/src/riscv/sifive/hifive-unleashed-a00.dts1
-rw-r--r--dts/src/xtensa/virt.dts2
-rw-r--r--fs/devfs-core.c2
-rw-r--r--fs/efivarfs.c2
-rw-r--r--fs/ext4/ext4_common.c32
-rw-r--r--fs/ext4/ext4fs.c61
-rw-r--r--fs/ubootvarfs.c2
-rw-r--r--include/efi.h5
-rw-r--r--include/efi/efi-device.h1
-rw-r--r--include/linux/mfd/stpmic1.h199
-rw-r--r--include/linux/regulator/machine.h207
-rw-r--r--include/linux/regulator/of_regulator.h48
-rw-r--r--include/param.h6
-rw-r--r--include/regulator.h74
-rw-r--r--lib/libfile.c17
-rw-r--r--lib/parameter.c5
-rw-r--r--lib/readline.c8
-rw-r--r--scripts/Kbuild.include5
141 files changed, 5784 insertions, 495 deletions
diff --git a/Documentation/boards/stm32mp.rst b/Documentation/boards/stm32mp.rst
index 774ede6e56..f93ec04eb0 100644
--- a/Documentation/boards/stm32mp.rst
+++ b/Documentation/boards/stm32mp.rst
@@ -1,11 +1,6 @@
STMicroelectronics STM32MP
==========================
-.. note::
-
- Support for the STM32MP architecure in barebox is still in progress.
- Bootstrapping an OS from mainline barebox is not yet supported.
-
The STM32MP is a line of 32-bit ARM SoCs. They reuse peripherals of the
STM32 line of microcontrollers and can have a STM32 MCU embedded as co-processor
as well.
@@ -68,8 +63,21 @@ An appropriate image for the boot media can be generated with following
Image can then be flashed on e.g. a SD-Card.
-TODO
-----
-
-* Extend barebox MMCI support to support the SDMMC2
-* Extend barebox DesignWare MAC support to support the stmmac
+Boot source selection
+---------------------
+
+The STM32MP BootROM samples three boot pins at reset. Usually BOOT1 is
+pulled down and BOOT0 and BOOT2 are connected to a 2P DIP switch::
+
+ +-------+
+ BOOT2 | O O-- |
+ BOOT0 | N O-- | <---- SDMMC
+ +-------+
+ +-------+
+ BOOT2 | O O-- |
+ BOOT0 | N --O | <---- QSPI-NOR Flash
+ +-------+
+ +-------+
+ BOOT2 | O --O |
+ BOOT0 | N --O | <---- DFU on UART and USB OTG
+ +-------+
diff --git a/Makefile b/Makefile
index a780bed0d7..b21ad5f58d 100644
--- a/Makefile
+++ b/Makefile
@@ -1,5 +1,5 @@
VERSION = 2019
-PATCHLEVEL = 10
+PATCHLEVEL = 11
SUBLEVEL = 0
EXTRAVERSION =
NAME = None
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index 652ac24ce3..9589a6a511 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -199,6 +199,10 @@ config ARCH_STM32MP
select HAS_DEBUG_LL
select HAVE_CLK
select GPIOLIB
+ select ARCH_HAS_RESET_CONTROLLER
+ select ARM_AMBA
+ select ARM_SMCCC
+ select ARM_USE_COMPRESSED_DTB
config ARCH_VERSATILE
bool "ARM Versatile boards (ARM926EJ-S)"
@@ -425,10 +429,14 @@ config ARM_SEMIHOSTING
config ARM_SMCCC
bool
+ help
+ This option enables barebox to invoke ARM secure monitor calls.
config ARM_SECURE_MONITOR
select ARM_SMCCC
bool
+ help
+ This option enables barebox to service ARM secure monitor calls.
config ARM_PSCI_OF
bool
@@ -440,7 +448,16 @@ config ARM_PSCI
select ARM_PSCI_OF
help
PSCI is used for controlling secondary CPU cores on some systems. Say
- yes here if you have one of these.
+ yes here if you want barebox to service PSCI calls on such systems.
+
+config ARM_PSCI_CLIENT
+ bool "Enable barebox PSCI client support"
+ select ARM_SMCCC
+ select ARM_PSCI_OF
+ help
+ Say yes here if you want barebox to communicate with a secure monitor
+ for resetting/powering off the system over PSCI. barebox' PSCI version
+ information will also be shared with Linux via device tree fixups.
config ARM_PSCI_DEBUG
bool "Enable PSCI debugging"
diff --git a/arch/arm/boards/stm32mp157c-dk2/board.c b/arch/arm/boards/stm32mp157c-dk2/board.c
index 9cb861af85..f15ae0b4af 100644
--- a/arch/arm/boards/stm32mp157c-dk2/board.c
+++ b/arch/arm/boards/stm32mp157c-dk2/board.c
@@ -4,6 +4,7 @@
#include <init.h>
#include <asm/memory.h>
#include <mach/stm32.h>
+#include <mach/bbu.h>
static int dk2_mem_init(void)
{
@@ -15,3 +16,15 @@ static int dk2_mem_init(void)
return 0;
}
mem_initcall(dk2_mem_init);
+
+static int dk2_postcore_init(void)
+{
+ if (!of_machine_is_compatible("st,stm32mp157c-dk2"))
+ return 0;
+
+ stm32mp_bbu_mmc_register_handler("sd", "/dev/mmc0.ssbl",
+ BBU_HANDLER_FLAG_DEFAULT);
+
+ return 0;
+}
+postcore_initcall(dk2_postcore_init);
diff --git a/arch/arm/boards/zii-common/board.c b/arch/arm/boards/zii-common/board.c
index 9a9564e6d1..eafb5a3aa8 100644
--- a/arch/arm/boards/zii-common/board.c
+++ b/arch/arm/boards/zii-common/board.c
@@ -80,7 +80,8 @@ static int rdu_networkconfig(void)
static char *rdu_netconfig;
struct device_d *sp_dev;
- if (!of_machine_is_compatible("zii,imx6q-zii-rdu2") &&
+ if (!of_machine_is_compatible("zii,imx8mq-ultra") &&
+ !of_machine_is_compatible("zii,imx6q-zii-rdu2") &&
!of_machine_is_compatible("zii,imx6qp-zii-rdu2") &&
!of_machine_is_compatible("zii,imx51-rdu1"))
return 0;
diff --git a/arch/arm/boards/zii-common/switch-cmd.c b/arch/arm/boards/zii-common/switch-cmd.c
index 30438053a1..2b9c34bfac 100644
--- a/arch/arm/boards/zii-common/switch-cmd.c
+++ b/arch/arm/boards/zii-common/switch-cmd.c
@@ -42,7 +42,7 @@ static int do_rdu2_switch_reset(void)
static int do_rdu1_switch_reset(void)
{
struct device_d *sp_dev = get_device_by_name("sp");
- struct rave_sp *sp = sp_dev->priv;
+ struct rave_sp *sp = sp_dev->parent->priv;
u8 cmd[] = {
[0] = RAVE_SP_CMD_RESET_ETH_SWITCH,
[1] = 0
diff --git a/arch/arm/configs/socfpga-arria10_defconfig b/arch/arm/configs/socfpga-arria10_defconfig
index ae420c1dd2..e47a0ab183 100644
--- a/arch/arm/configs/socfpga-arria10_defconfig
+++ b/arch/arm/configs/socfpga-arria10_defconfig
@@ -74,6 +74,7 @@ CONFIG_MCI=y
CONFIG_MCI_STARTUP=y
CONFIG_MCI_MMC_BOOT_PARTITIONS=y
CONFIG_MCI_DW=y
+CONFIG_STATE_DRV=y
# CONFIG_PINCTRL is not set
CONFIG_FS_TFTP=y
CONFIG_FS_NFS=y
diff --git a/arch/arm/configs/stm32mp_defconfig b/arch/arm/configs/stm32mp_defconfig
index 9f30bb1caa..f69f9f966a 100644
--- a/arch/arm/configs/stm32mp_defconfig
+++ b/arch/arm/configs/stm32mp_defconfig
@@ -4,7 +4,6 @@ CONFIG_THUMB2_BAREBOX=y
CONFIG_ARM_BOARD_APPEND_ATAG=y
CONFIG_ARM_OPTIMZED_STRING_FUNCTIONS=y
CONFIG_ARM_UNWIND=y
-CONFIG_ARM_PSCI=y
CONFIG_MMU=y
CONFIG_MALLOC_SIZE=0x0
CONFIG_MALLOC_TLSF=y
@@ -23,10 +22,12 @@ CONFIG_BLSPEC=y
CONFIG_CONSOLE_ACTIVATE_NONE=y
CONFIG_CONSOLE_ALLOW_COLOR=y
CONFIG_PBL_CONSOLE=y
-CONFIG_PARTITION=y
+CONFIG_PARTITION_DISK_EFI=y
+# CONFIG_PARTITION_DISK_EFI_GPT_NO_FORCE is not set
+# CONFIG_PARTITION_DISK_EFI_GPT_COMPARE is not set
CONFIG_DEFAULT_ENVIRONMENT_GENERIC_NEW=y
CONFIG_RESET_SOURCE=y
-CONFIG_DEBUG_INITCALLS=y
+CONFIG_MACHINE_ID=y
CONFIG_CMD_DMESG=y
CONFIG_LONGHELP=y
CONFIG_CMD_IOMEM=y
@@ -82,19 +83,34 @@ CONFIG_NET=y
CONFIG_NET_NETCONSOLE=y
CONFIG_OFDEVICE=y
CONFIG_OF_BAREBOX_DRIVERS=y
+CONFIG_DRIVER_SERIAL_STM32=y
CONFIG_DRIVER_NET_DESIGNWARE=y
CONFIG_DRIVER_NET_DESIGNWARE_GENERIC=y
+CONFIG_DRIVER_NET_DESIGNWARE_EQOS=y
+CONFIG_DRIVER_NET_DESIGNWARE_STM32=y
CONFIG_AT803X_PHY=y
CONFIG_MICREL_PHY=y
+CONFIG_REALTEK_PHY=y
# CONFIG_SPI is not set
+CONFIG_I2C=y
+CONFIG_I2C_STM32=y
+CONFIG_MCI=y
+CONFIG_MCI_STARTUP=y
+CONFIG_MCI_STM32_SDMMC2=y
+CONFIG_MFD_STPMIC1=y
CONFIG_LED=y
CONFIG_LED_GPIO=y
CONFIG_LED_GPIO_OF=y
CONFIG_WATCHDOG=y
CONFIG_WATCHDOG_POLLER=y
CONFIG_STM32_IWDG_WATCHDOG=y
+CONFIG_STPMIC1_WATCHDOG=y
+CONFIG_NVMEM=y
+CONFIG_STM32_BSEC=y
CONFIG_REGULATOR=y
CONFIG_REGULATOR_FIXED=y
+CONFIG_REGULATOR_STPMIC1=y
+CONFIG_RESET_STM32=y
CONFIG_FS_EXT4=y
CONFIG_FS_TFTP=y
CONFIG_FS_NFS=y
@@ -103,3 +119,4 @@ CONFIG_FS_FAT_WRITE=y
CONFIG_FS_FAT_LFN=y
CONFIG_ZLIB=y
CONFIG_CRC8=y
+CONFIG_DIGEST_SHA1_ARM=y
diff --git a/arch/arm/cpu/Makefile b/arch/arm/cpu/Makefile
index e0b16747ad..09b3bc2eea 100644
--- a/arch/arm/cpu/Makefile
+++ b/arch/arm/cpu/Makefile
@@ -16,6 +16,7 @@ pbl-$(CONFIG_BOARD_ARM_GENERIC_DT_AARCH64) += board-dt-2nd-aarch64.o
obj-pbl-y += setupc$(S64).o cache$(S64).o
obj-$(CONFIG_BOOTM_OPTEE) += start-kernel-optee.o
+obj-$(CONFIG_ARM_PSCI_CLIENT) += psci-client.o
#
# Any variants can be called as start-armxyz.S
diff --git a/arch/arm/cpu/psci-client.c b/arch/arm/cpu/psci-client.c
new file mode 100644
index 0000000000..b5d0d37497
--- /dev/null
+++ b/arch/arm/cpu/psci-client.c
@@ -0,0 +1,190 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2017 Masahiro Yamada <yamada.masahiro@socionext.com>
+ * Copyright (C) 2019 Ahmad Fatoum, Pengutronix
+ */
+
+#include <common.h>
+#include <init.h>
+#include <driver.h>
+#include <asm/psci.h>
+#include <asm/secure.h>
+#include <poweroff.h>
+#include <restart.h>
+#include <linux/arm-smccc.h>
+
+static struct restart_handler restart;
+
+static void __noreturn psci_invoke_noreturn(int function)
+{
+ int ret;
+
+ ret = psci_invoke(function, 0, 0, 0, NULL);
+
+ pr_err("psci command failed: %s\n", strerror(-ret));
+ hang();
+}
+
+static void __noreturn psci_poweroff(struct poweroff_handler *handler)
+{
+ psci_invoke_noreturn(ARM_PSCI_0_2_FN_SYSTEM_OFF);
+}
+
+static void __noreturn psci_restart(struct restart_handler *rst)
+{
+ psci_invoke_noreturn(ARM_PSCI_0_2_FN_SYSTEM_RESET);
+}
+
+static u32 version;
+int psci_get_version(void)
+{
+ if (!version)
+ return -EPROBE_DEFER;
+
+ return version;
+}
+
+static u32 (*psci_invoke_fn)(ulong, ulong, ulong, ulong);
+
+static int psci_xlate_error(s32 errnum)
+{
+ switch (errnum) {
+ case ARM_PSCI_RET_NOT_SUPPORTED:
+ return -ENOTSUPP; // Operation not supported
+ case ARM_PSCI_RET_INVAL:
+ return -EINVAL; // Invalid argument
+ case ARM_PSCI_RET_DENIED:
+ return -EPERM; // Operation not permitted
+ case ARM_PSCI_RET_ALREADY_ON:
+ return -EBUSY; // CPU already on
+ case ARM_PSCI_RET_ON_PENDING:
+ return -EALREADY; // CPU_ON in progress
+ case ARM_PSCI_RET_INTERNAL_FAILURE:
+ return -EIO; // Internal failure
+ case ARM_PSCI_RET_NOT_PRESENT:
+ return -ESRCH; // Trusted OS not present on core
+ case ARM_PSCI_RET_DISABLED:
+ return -ENODEV; // CPU is disabled
+ case ARM_PSCI_RET_INVALID_ADDRESS:
+ return -EACCES; // Bad address
+ default:
+ return errnum;
+ };
+}
+
+int psci_invoke(ulong function, ulong arg0, ulong arg1, ulong arg2,
+ ulong *result)
+{
+ ulong ret;
+ if (!psci_invoke_fn)
+ return -EPROBE_DEFER;
+
+ ret = psci_invoke_fn(function, arg0, arg1, arg2);
+ if (result)
+ *result = ret;
+
+ switch (function) {
+ case ARM_PSCI_0_2_FN_PSCI_VERSION:
+ case ARM_PSCI_1_0_FN64_STAT_RESIDENCY:
+ case ARM_PSCI_1_0_FN64_STAT_COUNT:
+ /* These don't return an error code */
+ return 0;
+ }
+
+ return psci_xlate_error(ret);
+}
+
+static u32 invoke_psci_fn_hvc(ulong function, ulong arg0, ulong arg1, ulong arg2)
+{
+ struct arm_smccc_res res;
+ arm_smccc_hvc(function, arg0, arg1, arg2, 0, 0, 0, 0, &res);
+ return res.a0;
+}
+
+static u32 invoke_psci_fn_smc(ulong function, ulong arg0, ulong arg1, ulong arg2)
+{
+ struct arm_smccc_res res;
+ arm_smccc_smc(function, arg0, arg1, arg2, 0, 0, 0, 0, &res);
+ return res.a0;
+}
+
+static int of_psci_do_fixup(struct device_node *root, void *context)
+{
+ return of_psci_fixup(root, *(u32 *)context);
+}
+
+static int __init psci_probe(struct device_d *dev)
+{
+ const char *method;
+ ulong of_version, actual_version;
+ int ret;
+
+ ret = dev_get_drvdata(dev, (const void **)&of_version);
+ if (ret)
+ return -ENODEV;
+
+ ret = of_property_read_string(dev->device_node, "method", &method);
+ if (ret) {
+ dev_warn(dev, "missing \"method\" property\n");
+ return -ENXIO;
+ }
+
+ if (!strcmp(method, "hvc")) {
+ psci_invoke_fn = invoke_psci_fn_hvc;
+ } else if (!strcmp(method, "smc")) {
+ psci_invoke_fn = invoke_psci_fn_smc;
+ } else {
+ pr_warn("invalid \"method\" property: %s\n", method);
+ return -EINVAL;
+ }
+
+
+ if (of_version < ARM_PSCI_VER(0,2)) {
+ version = of_version;
+
+ dev_info(dev, "assuming version %u.%u\n",
+ version >> 16, version & 0xffff);
+ dev_dbg(dev, "Not registering reset handler due to PSCI version\n");
+
+ return 0;
+ }
+
+ psci_invoke(ARM_PSCI_0_2_FN_PSCI_VERSION, 0, 0, 0, &actual_version);
+ version = actual_version;
+
+ dev_info(dev, "detected version %u.%u\n",
+ version >> 16, version & 0xffff);
+
+ if (actual_version != of_version)
+ of_register_fixup(of_psci_do_fixup, &version);
+
+ ret = poweroff_handler_register_fn(psci_poweroff);
+ if (ret)
+ dev_warn(dev, "error registering poweroff handler: %s\n",
+ strerror(-ret));
+
+ restart.name = "psci";
+ restart.restart = psci_restart;
+ restart.priority = 400;
+
+ ret = restart_handler_register(&restart);
+ if (ret)
+ dev_warn(dev, "error registering restart handler: %s\n",
+ strerror(-ret));
+
+ return ret;
+}
+
+static __maybe_unused struct of_device_id psci_dt_ids[] = {
+ { .compatible = "arm,psci", .data = (void*)ARM_PSCI_VER(0,1) },
+ { .compatible = "arm,psci-0.2", .data = (void*)ARM_PSCI_VER(0,2) },
+ { .compatible = "arm,psci-1.0", .data = (void*)ARM_PSCI_VER(1,0) },
+ { /* sentinel */ },
+};
+
+static struct driver_d psci_driver = {
+ .name = "psci",
+ .probe = psci_probe,
+ .of_compatible = DRV_OF_COMPAT(psci_dt_ids),
+};
+coredevice_platform_driver(psci_driver);
diff --git a/arch/arm/cpu/psci.c b/arch/arm/cpu/psci.c
index a976ddbb5c..22ce1dfd0e 100644
--- a/arch/arm/cpu/psci.c
+++ b/arch/arm/cpu/psci.c
@@ -228,7 +228,7 @@ static int armv7_psci_init(void)
}
device_initcall(armv7_psci_init);
-#ifdef DEBUG
+#ifdef CONFIG_ARM_PSCI_DEBUG
#include <command.h>
#include <getopt.h>
@@ -248,8 +248,41 @@ void second_entry(void)
while (1);
}
+static const char *psci_xlate_str(long err)
+{
+ static char errno_string[sizeof "error 0x123456789ABCDEF0"];
+
+ switch(err)
+ {
+ case ARM_PSCI_RET_SUCCESS:
+ return "Success";
+ case ARM_PSCI_RET_NOT_SUPPORTED:
+ return "Operation not supported";
+ case ARM_PSCI_RET_INVAL:
+ return "Invalid argument";
+ case ARM_PSCI_RET_DENIED:
+ return "Operation not permitted";
+ case ARM_PSCI_RET_ALREADY_ON:
+ return "CPU already on";
+ case ARM_PSCI_RET_ON_PENDING:
+ return "CPU_ON in progress";
+ case ARM_PSCI_RET_INTERNAL_FAILURE:
+ return "Internal failure";
+ case ARM_PSCI_RET_NOT_PRESENT:
+ return "Trusted OS not present on core";
+ case ARM_PSCI_RET_DISABLED:
+ return "CPU is disabled";
+ case ARM_PSCI_RET_INVALID_ADDRESS:
+ return "Bad address";
+ }
+
+ sprintf(errno_string, "error 0x%lx", err);
+ return errno_string;
+}
+
static int do_smc(int argc, char *argv[])
{
+ long ret;
int opt;
struct arm_smccc_res res = {
.a0 = 0xdeadbee0,
@@ -258,7 +291,10 @@ static int do_smc(int argc, char *argv[])
.a3 = 0xdeadbee3,
};
- while ((opt = getopt(argc, argv, "nicz")) > 0) {
+ if (argc < 2)
+ return COMMAND_ERROR_USAGE;
+
+ while ((opt = getopt(argc, argv, "nic")) > 0) {
switch (opt) {
case 'n':
armv7_secure_monitor_install();
@@ -271,7 +307,10 @@ static int do_smc(int argc, char *argv[])
case 'c':
arm_smccc_smc(ARM_PSCI_0_2_FN_CPU_ON,
1, (unsigned long)second_entry, 0, 0, 0, 0, 0, &res);
- break;
+ ret = (long)res.a0;
+ printf("CPU_ON returns with: %s\n", psci_xlate_str(ret));
+ if (ret)
+ return COMMAND_ERROR;
}
}
@@ -285,7 +324,6 @@ BAREBOX_CMD_HELP_TEXT("Options:")
BAREBOX_CMD_HELP_OPT ("-n", "Install secure monitor and switch to nonsecure mode")
BAREBOX_CMD_HELP_OPT ("-i", "Show information about installed PSCI version")
BAREBOX_CMD_HELP_OPT ("-c", "Start secondary CPU core")
-BAREBOX_CMD_HELP_OPT ("-z", "Turn off secondary CPU core")
BAREBOX_CMD_HELP_END
BAREBOX_CMD_START(smc)
diff --git a/arch/arm/dts/stm32mp157a-dk1.dtsi b/arch/arm/dts/stm32mp157a-dk1.dtsi
index f7fbdcd174..e9e386a664 100644
--- a/arch/arm/dts/stm32mp157a-dk1.dtsi
+++ b/arch/arm/dts/stm32mp157a-dk1.dtsi
@@ -8,6 +8,10 @@
#include <dt-bindings/gpio/gpio.h>
/ {
+ aliases {
+ mmc0 = &sdmmc1;
+ };
+
chosen {
environment {
compatible = "barebox,environment";
@@ -27,17 +31,4 @@
default-state = "on";
};
};
-
- sram: sram@10050000 {
- compatible = "mmio-sram";
- reg = <0x10050000 0x10000>;
- #address-cells = <1>;
- #size-cells = <1>;
- ranges = <0 0x10050000 0x10000>;
-
- dma_pool: dma_pool@0 {
- reg = <0x0 0x10000>;
- pool;
- };
- };
};
diff --git a/arch/arm/dts/stm32mp157c.dtsi b/arch/arm/dts/stm32mp157c.dtsi
index 8d9c84a047..97c075a020 100644
--- a/arch/arm/dts/stm32mp157c.dtsi
+++ b/arch/arm/dts/stm32mp157c.dtsi
@@ -19,4 +19,12 @@
gpio10 = &gpiok;
gpio25 = &gpioz;
};
+
+ psci {
+ compatible = "arm,psci-0.2";
+ };
+};
+
+&bsec {
+ barebox,provide-mac-address = <&ethernet0 0x39>;
};
diff --git a/arch/arm/include/asm/psci.h b/arch/arm/include/asm/psci.h
index f2db967f3a..b616e4b20e 100644
--- a/arch/arm/include/asm/psci.h
+++ b/arch/arm/include/asm/psci.h
@@ -18,8 +18,9 @@
#ifndef __ARM_PSCI_H__
#define __ARM_PSCI_H__
-#define ARM_PSCI_VER_1_0 (0x00010000)
-#define ARM_PSCI_VER_0_2 (0x00000002)
+#define ARM_PSCI_VER(major, minor) (((major) << 16) | (minor))
+#define ARM_PSCI_VER_1_0 ARM_PSCI_VER(1,0)
+#define ARM_PSCI_VER_0_2 ARM_PSCI_VER(0,2)
/* PSCI 0.1 interface */
#define ARM_PSCI_FN_BASE 0x95c1ba5e
@@ -106,6 +107,24 @@ static inline void psci_set_ops(struct psci_ops *ops)
}
#endif
+#ifdef CONFIG_ARM_PSCI_CLIENT
+int psci_invoke(ulong function, ulong arg0, ulong arg1, ulong arg2,
+ ulong *result);
+
+int psci_get_version(void);
+#else
+static inline int psci_invoke(ulong function, ulong arg0, ulong arg1, ulong arg2,
+ ulong *result)
+{
+ return -ENOSYS;
+}
+
+static inline int psci_get_version(void)
+{
+ return -ENOSYS;
+}
+#endif
+
void psci_cpu_entry(void);
#ifdef CONFIG_ARM_PSCI_DEBUG
diff --git a/arch/arm/lib/pbl.lds.S b/arch/arm/lib/pbl.lds.S
index 01ed384495..b593d0329a 100644
--- a/arch/arm/lib/pbl.lds.S
+++ b/arch/arm/lib/pbl.lds.S
@@ -114,7 +114,7 @@ SECTIONS
}
__piggydata_end = .;
- .image_end : { *(.__image_end) }
+ .image_end : { KEEP(*(.__image_end)) }
pbl_image_size = . - BASE;
diff --git a/arch/arm/mach-socfpga/include/mach/arria10-clock-manager.h b/arch/arm/mach-socfpga/include/mach/arria10-clock-manager.h
index ee2b9b3c5e..c0a57439af 100644
--- a/arch/arm/mach-socfpga/include/mach/arria10-clock-manager.h
+++ b/arch/arm/mach-socfpga/include/mach/arria10-clock-manager.h
@@ -128,6 +128,7 @@ struct arria10_perpll_cfg {
extern int arria10_cm_basic_init(struct arria10_mainpll_cfg *mainpll_cfg,
struct arria10_perpll_cfg *perpll_cfg);
+unsigned int arria10_cm_get_mmc_controller_clk_hz(void);
extern unsigned int cm_get_mmc_controller_clk_hz(void);
extern void arria10_cm_use_intosc(void);
extern uint32_t cm_l4_main_clk_hz;
diff --git a/arch/arm/mach-socfpga/include/mach/arria10-reset-manager.h b/arch/arm/mach-socfpga/include/mach/arria10-reset-manager.h
index ebd2043426..2033de77a3 100644
--- a/arch/arm/mach-socfpga/include/mach/arria10-reset-manager.h
+++ b/arch/arm/mach-socfpga/include/mach/arria10-reset-manager.h
@@ -108,6 +108,10 @@
void arria10_reset_peripherals(void);
void arria10_reset_deassert_dedicated_peripherals(void);
void arria10_reset_deassert_shared_peripherals(void);
+void arria10_reset_deassert_shared_peripherals_q1(uint32_t *mask0, uint32_t *mask1);
+void arria10_reset_deassert_shared_peripherals_q2(uint32_t *mask0, uint32_t *mask1);
+void arria10_reset_deassert_shared_peripherals_q3(uint32_t *mask0, uint32_t *mask1);
+void arria10_reset_deassert_shared_peripherals_q4(uint32_t *mask0, uint32_t *mask1);
void arria10_reset_deassert_fpga_peripherals(void);
#endif
diff --git a/arch/arm/mach-socfpga/include/mach/arria10-xload.h b/arch/arm/mach-socfpga/include/mach/arria10-xload.h
index 71f8397362..7575231bbf 100644
--- a/arch/arm/mach-socfpga/include/mach/arria10-xload.h
+++ b/arch/arm/mach-socfpga/include/mach/arria10-xload.h
@@ -4,6 +4,7 @@
void arria10_init_mmc(void);
int arria10_prepare_mmc(int barebox_part, int rbf_part);
int arria10_read_blocks(void *dst, int blocknum, size_t len);
+int a10_update_bits(unsigned int reg, unsigned int mask, unsigned int val);
struct partition {
uint64_t first_sec;
diff --git a/arch/arm/mach-socfpga/include/mach/cyclone5-system-manager.h b/arch/arm/mach-socfpga/include/mach/cyclone5-system-manager.h
index 24f52effd8..7cec60937b 100644
--- a/arch/arm/mach-socfpga/include/mach/cyclone5-system-manager.h
+++ b/arch/arm/mach-socfpga/include/mach/cyclone5-system-manager.h
@@ -57,15 +57,4 @@ void socfpga_sysmgr_pinmux_init(unsigned long *sys_mgr_init_table, int num);
#define SYSMGR_FPGAINTF_NAND (1<<4)
#define SYSMGR_FPGAINTF_SDMMC (1<<5)
-/* Enumeration: sysmgr::emacgrp::ctrl::physel::enum */
-#define SYSMGR_EMACGRP_CTRL_PHYSEL_ENUM_GMII_MII 0x0
-#define SYSMGR_EMACGRP_CTRL_PHYSEL_ENUM_RGMII 0x1
-#define SYSMGR_EMACGRP_CTRL_PHYSEL_ENUM_RMII 0x2
-#define SYSMGR_EMACGRP_CTRL_PHYSEL0_LSB 0
-#define SYSMGR_EMACGRP_CTRL_PHYSEL1_LSB 2
-#define SYSMGR_EMACGRP_CTRL_PHYSEL_MASK 0x00000003
-
-#define SYSMGR_FPGAGRP_MODULE 0x00000028
-#define SYSMGR_FPGAGRP_MODULE_EMAC 0x00000004
-
#endif /* _SYSTEM_MANAGER_H_ */
diff --git a/arch/arm/mach-stm32mp/Kconfig b/arch/arm/mach-stm32mp/Kconfig
index 6bf950b23f..9b55a3d218 100644
--- a/arch/arm/mach-stm32mp/Kconfig
+++ b/arch/arm/mach-stm32mp/Kconfig
@@ -5,11 +5,11 @@ config ARCH_NR_GPIO
default 416
config ARCH_STM32MP157
+ select ARM_PSCI_CLIENT
bool
config MACH_STM32MP157C_DK2
select ARCH_STM32MP157
- select ARM_USE_COMPRESSED_DTB
bool "STM32MP157C-DK2 board"
endif
diff --git a/arch/arm/mach-stm32mp/Makefile b/arch/arm/mach-stm32mp/Makefile
index 204cad608f..6f49528892 100644
--- a/arch/arm/mach-stm32mp/Makefile
+++ b/arch/arm/mach-stm32mp/Makefile
@@ -1 +1,2 @@
-obj-$(CONFIG_BOOTM) := stm32image.o
+obj-y := init.o
+obj-$(CONFIG_BOOTM) += stm32image.o
diff --git a/arch/arm/mach-stm32mp/include/mach/bbu.h b/arch/arm/mach-stm32mp/include/mach/bbu.h
new file mode 100644
index 0000000000..8b9504400e
--- /dev/null
+++ b/arch/arm/mach-stm32mp/include/mach/bbu.h
@@ -0,0 +1,14 @@
+#ifndef MACH_STM32MP_BBU_H_
+#define MACH_STM32MP_BBU_H_
+
+#include <bbu.h>
+
+static inline int stm32mp_bbu_mmc_register_handler(const char *name,
+ const char *devicefile,
+ unsigned long flags)
+{
+ return bbu_register_std_file_update(name, flags, devicefile,
+ filetype_stm32_image_v1);
+}
+
+#endif /* MACH_STM32MP_BBU_H_ */
diff --git a/arch/arm/mach-stm32mp/include/mach/bootsource.h b/arch/arm/mach-stm32mp/include/mach/bootsource.h
new file mode 100644
index 0000000000..1b6f562ac3
--- /dev/null
+++ b/arch/arm/mach-stm32mp/include/mach/bootsource.h
@@ -0,0 +1,33 @@
+/* SPDX-License-Identifier: GPL-2.0+ OR BSD-3-Clause */
+/*
+ * Copyright (C) 2018, STMicroelectronics - All Rights Reserved
+ */
+
+#ifndef __MACH_STM32_BOOTSOURCE_H__
+#define __MACH_STM32_BOOTSOURCE_H__
+
+enum stm32mp_boot_device {
+ STM32MP_BOOT_FLASH_SD = 0x10, /* .. 0x13 */
+ STM32MP_BOOT_FLASH_EMMC = 0x20, /* .. 0x23 */
+ STM32MP_BOOT_FLASH_NAND = 0x30,
+ STM32MP_BOOT_FLASH_NAND_FMC = 0x31,
+ STM32MP_BOOT_FLASH_NOR = 0x40,
+ STM32MP_BOOT_FLASH_NOR_QSPI = 0x41,
+ STM32MP_BOOT_SERIAL_UART = 0x50, /* .. 0x58 */
+ STM32MP_BOOT_SERIAL_USB = 0x60,
+ STM32MP_BOOT_SERIAL_USB_OTG = 0x62,
+};
+
+enum stm32mp_forced_boot_mode {
+ STM32MP_BOOT_NORMAL = 0x00,
+ STM32MP_BOOT_FASTBOOT = 0x01,
+ STM32MP_BOOT_RECOVERY = 0x02,
+ STM32MP_BOOT_STM32PROG = 0x03,
+ STM32MP_BOOT_UMS_MMC0 = 0x10,
+ STM32MP_BOOT_UMS_MMC1 = 0x11,
+ STM32MP_BOOT_UMS_MMC2 = 0x12,
+};
+
+enum stm32mp_forced_boot_mode st32mp_get_forced_boot_mode(void);
+
+#endif
diff --git a/arch/arm/mach-stm32mp/include/mach/bsec.h b/arch/arm/mach-stm32mp/include/mach/bsec.h
new file mode 100644
index 0000000000..559faaa2ba
--- /dev/null
+++ b/arch/arm/mach-stm32mp/include/mach/bsec.h
@@ -0,0 +1,41 @@
+#ifndef __MACH_STM32_BSEC_H__
+#define __MACH_STM32_BSEC_H__
+
+#include <mach/smc.h>
+
+/* Return status */
+enum bsec_smc {
+ BSEC_SMC_OK = 0,
+ BSEC_SMC_ERROR = -1,
+ BSEC_SMC_DISTURBED = -2,
+ BSEC_SMC_INVALID_PARAM = -3,
+ BSEC_SMC_PROG_FAIL = -4,
+ BSEC_SMC_LOCK_FAIL = -5,
+ BSEC_SMC_WRITE_FAIL = -6,
+ BSEC_SMC_SHADOW_FAIL = -7,
+ BSEC_SMC_TIMEOUT = -8,
+};
+
+/* Service for BSEC */
+enum bsec_field {
+ BSEC_SMC_READ_SHADOW = 1,
+ BSEC_SMC_PROG_OTP = 2,
+ BSEC_SMC_WRITE_SHADOW = 3,
+ BSEC_SMC_READ_OTP = 4,
+ BSEC_SMC_READ_ALL = 5,
+ BSEC_SMC_WRITE_ALL = 6,
+};
+
+static inline enum bsec_smc bsec_read_field(enum bsec_field field, unsigned *val)
+{
+ return stm32mp_smc(STM32_SMC_BSEC, BSEC_SMC_READ_SHADOW,
+ field, 0, val);
+}
+
+static inline enum bsec_smc bsec_write_field(enum bsec_field field, unsigned val)
+{
+ return stm32mp_smc(STM32_SMC_BSEC, BSEC_SMC_WRITE_SHADOW,
+ field, val, NULL);
+}
+
+#endif
diff --git a/arch/arm/mach-stm32mp/include/mach/revision.h b/arch/arm/mach-stm32mp/include/mach/revision.h
new file mode 100644
index 0000000000..387201421d
--- /dev/null
+++ b/arch/arm/mach-stm32mp/include/mach/revision.h
@@ -0,0 +1,32 @@
+/* SPDX-License-Identifier: GPL-2.0+ OR BSD-3-Clause */
+/*
+ * Copyright (C) 2015-2017, STMicroelectronics - All Rights Reserved
+ */
+
+#ifndef __MACH_CPUTYPE_H__
+#define __MACH_CPUTYPE_H__
+
+/* ID = Device Version (bit31:16) + Device Part Number (RPN) (bit15:0)*/
+#define CPU_STM32MP157Cxx 0x05000000
+#define CPU_STM32MP157Axx 0x05000001
+#define CPU_STM32MP153Cxx 0x05000024
+#define CPU_STM32MP153Axx 0x05000025
+#define CPU_STM32MP151Cxx 0x0500002E
+#define CPU_STM32MP151Axx 0x0500002F
+
+/* silicon revisions */
+#define CPU_REV_A 0x1000
+#define CPU_REV_B 0x2000
+
+int stm32mp_silicon_revision(void);
+int stm32mp_cputype(void);
+int stm32mp_package(void);
+
+#define cpu_is_stm32mp157c() (stm32mp_cputype() == CPU_STM32MP157Cxx)
+#define cpu_is_stm32mp157a() (stm32mp_cputype() == CPU_STM32MP157Axx)
+#define cpu_is_stm32mp153c() (stm32mp_cputype() == CPU_STM32MP153Cxx)
+#define cpu_is_stm32mp153a() (stm32mp_cputype() == CPU_STM32MP153Axx)
+#define cpu_is_stm32mp151c() (stm32mp_cputype() == CPU_STM32MP151Cxx)
+#define cpu_is_stm32mp151a() (stm32mp_cputype() == CPU_STM32MP151Axx)
+
+#endif /* __MACH_CPUTYPE_H__ */
diff --git a/arch/arm/mach-stm32mp/include/mach/smc.h b/arch/arm/mach-stm32mp/include/mach/smc.h
new file mode 100644
index 0000000000..6b8e62bd53
--- /dev/null
+++ b/arch/arm/mach-stm32mp/include/mach/smc.h
@@ -0,0 +1,28 @@
+#ifndef __MACH_STM32_SMC_H__
+#define __MACH_STM32_SMC_H__
+
+#include <linux/arm-smccc.h>
+
+/* Secure Service access from Non-secure */
+#define STM32_SMC_RCC 0x82001000
+#define STM32_SMC_PWR 0x82001001
+#define STM32_SMC_RTC 0x82001002
+#define STM32_SMC_BSEC 0x82001003
+
+/* Register access service use for RCC/RTC/PWR */
+#define STM32_SMC_REG_WRITE 0x1
+#define STM32_SMC_REG_SET 0x2
+#define STM32_SMC_REG_CLEAR 0x3
+
+static inline int stm32mp_smc(u32 svc, u8 op, u32 data1, u32 data2, u32 *val)
+{
+ struct arm_smccc_res res;
+
+ arm_smccc_smc(svc, op, data1, data2, 0, 0, 0, 0, &res);
+ if (val)
+ *val = res.a1;
+
+ return (int)res.a0;
+}
+
+#endif
diff --git a/arch/arm/mach-stm32mp/init.c b/arch/arm/mach-stm32mp/init.c
new file mode 100644
index 0000000000..7bad989a60
--- /dev/null
+++ b/arch/arm/mach-stm32mp/init.c
@@ -0,0 +1,260 @@
+// SPDX-License-Identifier: GPL-2.0+ OR BSD-3-Clause
+/*
+ * Copyright (C) 2018, STMicroelectronics - All Rights Reserved
+ * Copyright (C) 2019 Ahmad Fatoum, Pengutronix
+ */
+
+#define pr_fmt(fmt) "stm32mp-init: " fmt
+
+#include <common.h>
+#include <init.h>
+#include <mach/stm32.h>
+#include <mach/bsec.h>
+#include <mach/revision.h>
+#include <mach/bootsource.h>
+#include <bootsource.h>
+
+/* DBGMCU register */
+#define DBGMCU_IDC (STM32_DBGMCU_BASE + 0x00)
+#define DBGMCU_APB4FZ1 (STM32_DBGMCU_BASE + 0x2C)
+#define DBGMCU_APB4FZ1_IWDG2 BIT(2)
+#define DBGMCU_IDC_DEV_ID_MASK GENMASK(11, 0)
+#define DBGMCU_IDC_DEV_ID_SHIFT 0
+#define DBGMCU_IDC_REV_ID_MASK GENMASK(31, 16)
+#define DBGMCU_IDC_REV_ID_SHIFT 16
+
+#define RCC_DBGCFGR (STM32_RCC_BASE + 0x080C)
+#define RCC_DBGCFGR_DBGCKEN BIT(8)
+
+/* BSEC OTP index */
+#define BSEC_OTP_RPN 1
+#define BSEC_OTP_PKG 16
+
+/* Device Part Number (RPN) = OTP_DATA1 lower 8 bits */
+#define RPN_SHIFT 0
+#define RPN_MASK GENMASK(7, 0)
+
+/* Package = bit 27:29 of OTP16
+ * - 100: LBGA448 (FFI) => AA = LFBGA 18x18mm 448 balls p. 0.8mm
+ * - 011: LBGA354 (LCI) => AB = LFBGA 16x16mm 359 balls p. 0.8mm
+ * - 010: TFBGA361 (FFC) => AC = TFBGA 12x12mm 361 balls p. 0.5mm
+ * - 001: TFBGA257 (LCC) => AD = TFBGA 10x10mm 257 balls p. 0.5mm
+ * - others: Reserved
+ */
+#define PKG_SHIFT 27
+#define PKG_MASK GENMASK(2, 0)
+
+#define PKG_AA_LBGA448 4
+#define PKG_AB_LBGA354 3
+#define PKG_AC_TFBGA361 2
+#define PKG_AD_TFBGA257 1
+
+/*
+ * enumerated for boot interface from Bootrom, used in TAMP_BOOT_CONTEXT
+ * - boot device = bit 8:4
+ * - boot instance = bit 3:0
+ */
+#define BOOT_TYPE_MASK 0xF0
+#define BOOT_TYPE_SHIFT 4
+#define BOOT_INSTANCE_MASK 0x0F
+#define BOOT_INSTANCE_SHIFT 0
+
+/* TAMP registers */
+#define TAMP_BACKUP_REGISTER(x) (STM32_TAMP_BASE + 0x100 + 4 * x)
+/* secure access */
+#define TAMP_BACKUP_MAGIC_NUMBER TAMP_BACKUP_REGISTER(4)
+#define TAMP_BACKUP_BRANCH_ADDRESS TAMP_BACKUP_REGISTER(5)
+/* non secure access */
+#define TAMP_BOOT_CONTEXT TAMP_BACKUP_REGISTER(20)
+#define TAMP_BOOTCOUNT TAMP_BACKUP_REGISTER(21)
+
+#define TAMP_BOOT_MODE_MASK GENMASK(15, 8)
+#define TAMP_BOOT_MODE_SHIFT 8
+#define TAMP_BOOT_DEVICE_MASK GENMASK(7, 4)
+#define TAMP_BOOT_INSTANCE_MASK GENMASK(3, 0)
+#define TAMP_BOOT_FORCED_MASK GENMASK(7, 0)
+#define TAMP_BOOT_DEBUG_ON BIT(16)
+
+
+static enum stm32mp_forced_boot_mode __stm32mp_forced_boot_mode;
+enum stm32mp_forced_boot_mode st32mp_get_forced_boot_mode(void)
+{
+ return __stm32mp_forced_boot_mode;
+}
+
+static void setup_boot_mode(void)
+{
+ u32 boot_ctx = readl(TAMP_BOOT_CONTEXT);
+ u32 boot_mode =
+ (boot_ctx & TAMP_BOOT_MODE_MASK) >> TAMP_BOOT_MODE_SHIFT;
+ int instance = (boot_mode & TAMP_BOOT_INSTANCE_MASK) - 1;
+ enum bootsource src = BOOTSOURCE_UNKNOWN;
+
+ switch (boot_mode & TAMP_BOOT_DEVICE_MASK) {
+ case STM32MP_BOOT_SERIAL_UART:
+ src = BOOTSOURCE_SERIAL;
+ break;
+ case STM32MP_BOOT_SERIAL_USB:
+ src = BOOTSOURCE_USB;
+ break;
+ case STM32MP_BOOT_FLASH_SD:
+ case STM32MP_BOOT_FLASH_EMMC:
+ src = BOOTSOURCE_MMC;
+ break;
+ case STM32MP_BOOT_FLASH_NAND:
+ src = BOOTSOURCE_NAND;
+ break;
+ case STM32MP_BOOT_FLASH_NOR:
+ instance = 0;
+ src = BOOTSOURCE_NOR;
+ break;
+ case STM32MP_BOOT_FLASH_NOR_QSPI:
+ instance--;
+ src = BOOTSOURCE_SPI_NOR;
+ break;
+ default:
+ pr_debug("unexpected boot mode\n");
+ break;
+ }
+
+ __stm32mp_forced_boot_mode = boot_ctx & TAMP_BOOT_FORCED_MASK;
+
+ pr_debug("[boot_ctx=0x%x] => mode=0x%x, instance=%d forced=0x%x\n",
+ boot_ctx, boot_mode, instance, __stm32mp_forced_boot_mode);
+
+ bootsource_set(src);
+ bootsource_set_instance(instance);
+
+ /* clear TAMP for next reboot */
+ clrsetbits_le32(TAMP_BOOT_CONTEXT, TAMP_BOOT_FORCED_MASK,
+ STM32MP_BOOT_NORMAL);
+}
+
+static int __stm32mp_cputype;
+int stm32mp_cputype(void)
+{
+ return __stm32mp_cputype;
+}
+
+static int __stm32mp_silicon_revision;
+int stm32mp_silicon_revision(void)
+{
+ return __stm32mp_silicon_revision;
+}
+
+static int __stm32mp_package;
+int stm32mp_package(void)
+{
+ return __stm32mp_package;
+}
+
+static inline u32 read_idc(void)
+{
+ setbits_le32(RCC_DBGCFGR, RCC_DBGCFGR_DBGCKEN);
+ return readl(IOMEM(DBGMCU_IDC));
+}
+
+/* Get Device Part Number (RPN) from OTP */
+static u32 get_cpu_rpn(u32 *rpn)
+{
+ int ret = bsec_read_field(BSEC_OTP_RPN, rpn);
+ if (ret)
+ return ret;
+
+ *rpn = (*rpn >> RPN_SHIFT) & RPN_MASK;
+ return 0;
+}
+
+static u32 get_cpu_revision(void)
+{
+ return (read_idc() & DBGMCU_IDC_REV_ID_MASK) >> DBGMCU_IDC_REV_ID_SHIFT;
+}
+
+static u32 get_cpu_type(u32 *type)
+{
+ u32 id;
+ int ret = get_cpu_rpn(type);
+ if (ret)
+ return ret;
+
+ id = (read_idc() & DBGMCU_IDC_DEV_ID_MASK) >> DBGMCU_IDC_DEV_ID_SHIFT;
+ *type |= id << 16;
+ return 0;
+}
+
+static int get_cpu_package(u32 *pkg)
+{
+ int ret = bsec_read_field(BSEC_OTP_PKG, pkg);
+ if (ret)
+ return ret;
+
+ *pkg = (*pkg >> PKG_SHIFT) & PKG_MASK;
+ return 0;
+}
+
+static int setup_cpu_type(void)
+{
+ const char *cputypestr;
+ const char *cpupkgstr;
+
+ get_cpu_type(&__stm32mp_cputype);
+ switch (__stm32mp_cputype) {
+ case CPU_STM32MP157Cxx:
+ cputypestr = "157C";
+ break;
+ case CPU_STM32MP157Axx:
+ cputypestr = "157A";
+ break;
+ case CPU_STM32MP153Cxx:
+ cputypestr = "153C";
+ break;
+ case CPU_STM32MP153Axx:
+ cputypestr = "153A";
+ break;
+ case CPU_STM32MP151Cxx:
+ cputypestr = "151C";
+ break;
+ case CPU_STM32MP151Axx:
+ cputypestr = "151A";
+ break;
+ default:
+ cputypestr = "????";
+ break;
+ }
+
+ get_cpu_package(&__stm32mp_package );
+ switch (__stm32mp_package) {
+ case PKG_AA_LBGA448:
+ cpupkgstr = "AA";
+ break;
+ case PKG_AB_LBGA354:
+ cpupkgstr = "AB";
+ break;
+ case PKG_AC_TFBGA361:
+ cpupkgstr = "AC";
+ break;
+ case PKG_AD_TFBGA257:
+ cpupkgstr = "AD";
+ break;
+ default:
+ cpupkgstr = "??";
+ break;
+ }
+
+ __stm32mp_silicon_revision = get_cpu_revision();
+
+ pr_debug("cputype = 0x%x, package = 0x%x, revision = 0x%x\n",
+ __stm32mp_cputype, __stm32mp_package, __stm32mp_silicon_revision);
+ pr_info("detected STM32MP%s%s Rev.%c\n", cputypestr, cpupkgstr,
+ (__stm32mp_silicon_revision >> 12) + 'A' - 1);
+ return 0;
+}
+
+static int stm32mp_init(void)
+{
+ setup_cpu_type();
+ setup_boot_mode();
+
+ return 0;
+}
+postcore_initcall(stm32mp_init);
diff --git a/arch/mips/boot/main_entry.c b/arch/mips/boot/main_entry.c
index 4ae4457e7e..2c18bc81c3 100644
--- a/arch/mips/boot/main_entry.c
+++ b/arch/mips/boot/main_entry.c
@@ -77,12 +77,6 @@ void __bare_init main_entry(void *fdt, u32 fdt_size)
cpu_probe();
- if (cpu_has_4k_cache) {
- extern void r4k_cache_init(void);
-
- r4k_cache_init();
- }
-
trap_init();
malloc_end = (unsigned long)_stext;
diff --git a/arch/mips/include/asm/cache.h b/arch/mips/include/asm/cache.h
index cceba0acc0..4bb39b1cd4 100644
--- a/arch/mips/include/asm/cache.h
+++ b/arch/mips/include/asm/cache.h
@@ -2,5 +2,6 @@
#define _ASM_MIPS_CACHE_H
void flush_cache_all(void);
+void r4k_cache_init(void);
#endif /* _ASM_MIPS_CACHE_H */
diff --git a/arch/mips/lib/cpu-probe.c b/arch/mips/lib/cpu-probe.c
index 2556a8b240..ddabddd466 100644
--- a/arch/mips/lib/cpu-probe.c
+++ b/arch/mips/lib/cpu-probe.c
@@ -9,6 +9,8 @@
*/
#include <common.h>
#include <asm/mipsregs.h>
+#include <asm/cache.h>
+#include <asm/cpu-features.h>
#include <asm/cpu-info.h>
#include <asm/cpu.h>
#include <memory.h>
@@ -163,6 +165,9 @@ void cpu_probe(void)
cpu_probe_ingenic(c);
break;
}
+
+ if (cpu_has_4k_cache)
+ r4k_cache_init();
}
unsigned long mips_stack_top;
diff --git a/arch/mips/lib/reloc.c b/arch/mips/lib/reloc.c
index 9a9e404f7e..df9760e38c 100644
--- a/arch/mips/lib/reloc.c
+++ b/arch/mips/lib/reloc.c
@@ -110,11 +110,13 @@ void relocate_code(void *fdt, u32 fdt_size, u32 ram_size)
{
unsigned long addr, length, bss_len;
u32 relocaddr, new_stack;
- uint8_t *buf, *bss_start;
+ uint8_t *buf;
unsigned int type;
long off;
bss_len = (unsigned long)&__bss_stop - (unsigned long)__bss_start;
+ memset(__bss_start, 0, bss_len);
+ cpu_probe();
length = barebox_image_size + bss_len;
relocaddr = ALIGN_DOWN(ram_size - length, SZ_64K);
@@ -149,10 +151,6 @@ void relocate_code(void *fdt, u32 fdt_size, u32 ram_size)
/* Ensure the icache is coherent */
flush_cache_all();
- /* Clear the .bss section */
- bss_start = (uint8_t *)((unsigned long)__bss_start + off);
- memset(bss_start, 0, bss_len);
-
__asm__ __volatile__ (
"move $a0, %0\n"
" move $a1, %1\n"
diff --git a/arch/mips/mach-loongson/include/mach/loongson1.h b/arch/mips/mach-loongson/include/mach/loongson1.h
index 75e1a55047..8b53f47e9e 100644
--- a/arch/mips/mach-loongson/include/mach/loongson1.h
+++ b/arch/mips/mach-loongson/include/mach/loongson1.h
@@ -1,28 +1,54 @@
/* SPDX-License-Identifier: GPL-2.0-or-later */
/*
- * Copyright (c) 2011 Zhang, Keguang <keguang.zhang at gmail.com>
+ * Copyright (c) 2011 Zhang, Keguang <keguang.zhang@gmail.com>
*
* Register mappings for Loongson 1
*/
-#ifndef __ASM_MACH_LOONGSON1_LOONGSON1_H
-#define __ASM_MACH_LOONGSON1_LOONGSON1_H
+#ifndef __ASM_MACH_LOONGSON32_LOONGSON1_H
+#define __ASM_MACH_LOONGSON32_LOONGSON1_H
-#include <asm/addrspace.h>
+#if defined(CONFIG_LOONGSON1_LS1B)
+#define DEFAULT_MEMSIZE 64 /* If no memsize provided */
+#elif defined(CONFIG_LOONGSON1_LS1C)
+#define DEFAULT_MEMSIZE 32
+#endif
/* Loongson 1 Register Bases */
+#define LS1X_MUX_BASE 0x1fd00420
+#define LS1X_INTC_BASE 0x1fd01040
+#define LS1X_GPIO0_BASE 0x1fd010c0
+#define LS1X_GPIO1_BASE 0x1fd010c4
+#define LS1X_DMAC_BASE 0x1fd01160
+#define LS1X_CBUS_BASE 0x1fd011c0
+#define LS1X_EHCI_BASE 0x1fe00000
+#define LS1X_OHCI_BASE 0x1fe08000
+#define LS1X_GMAC0_BASE 0x1fe10000
+#define LS1X_GMAC1_BASE 0x1fe20000
+
#define LS1X_UART0_BASE 0x1fe40000
#define LS1X_UART1_BASE 0x1fe44000
#define LS1X_UART2_BASE 0x1fe48000
#define LS1X_UART3_BASE 0x1fe4c000
+#define LS1X_CAN0_BASE 0x1fe50000
+#define LS1X_CAN1_BASE 0x1fe54000
+#define LS1X_I2C0_BASE 0x1fe58000
+#define LS1X_I2C1_BASE 0x1fe68000
+#define LS1X_I2C2_BASE 0x1fe70000
+#define LS1X_PWM0_BASE 0x1fe5c000
+#define LS1X_PWM1_BASE 0x1fe5c010
+#define LS1X_PWM2_BASE 0x1fe5c020
+#define LS1X_PWM3_BASE 0x1fe5c030
#define LS1X_WDT_BASE 0x1fe5c060
+#define LS1X_RTC_BASE 0x1fe64000
+#define LS1X_AC97_BASE 0x1fe74000
+#define LS1X_NAND_BASE 0x1fe78000
+#define LS1X_CLK_BASE 0x1fe78030
-/* Loongson 1 watchdog register definitions */
-#define LS1X_WDT_REG(x) \
- ((void __iomem *)KSEG1ADDR(LS1X_WDT_BASE + (x)))
-
-#define LS1X_WDT_EN LS1X_WDT_REG(0x0)
-#define LS1X_WDT_SET LS1X_WDT_REG(0x4)
-#define LS1X_WDT_TIMER LS1X_WDT_REG(0x8)
+#include <mach/regs-clk.h>
+#include <mach/regs-mux.h>
+#include <mach/regs-pwm.h>
+#include <mach/regs-rtc.h>
+#include <mach/regs-wdt.h>
-#endif /* __ASM_MACH_LOONGSON1_LOONGSON1_H */
+#endif /* __ASM_MACH_LOONGSON32_LOONGSON1_H */
diff --git a/arch/mips/mach-loongson/include/mach/regs-clk.h b/arch/mips/mach-loongson/include/mach/regs-clk.h
new file mode 100644
index 0000000000..98136fa8be
--- /dev/null
+++ b/arch/mips/mach-loongson/include/mach/regs-clk.h
@@ -0,0 +1,81 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ * Copyright (c) 2011 Zhang, Keguang <keguang.zhang@gmail.com>
+ *
+ * Loongson 1 Clock Register Definitions.
+ */
+
+#ifndef __ASM_MACH_LOONGSON32_REGS_CLK_H
+#define __ASM_MACH_LOONGSON32_REGS_CLK_H
+
+#define LS1X_CLK_REG(x) \
+ ((void __iomem *)KSEG1ADDR(LS1X_CLK_BASE + (x)))
+
+#define LS1X_CLK_PLL_FREQ LS1X_CLK_REG(0x0)
+#define LS1X_CLK_PLL_DIV LS1X_CLK_REG(0x4)
+
+#if defined(CONFIG_LOONGSON1_LS1B)
+/* Clock PLL Divisor Register Bits */
+#define DIV_DC_EN BIT(31)
+#define DIV_DC_RST BIT(30)
+#define DIV_CPU_EN BIT(25)
+#define DIV_CPU_RST BIT(24)
+#define DIV_DDR_EN BIT(19)
+#define DIV_DDR_RST BIT(18)
+#define RST_DC_EN BIT(5)
+#define RST_DC BIT(4)
+#define RST_DDR_EN BIT(3)
+#define RST_DDR BIT(2)
+#define RST_CPU_EN BIT(1)
+#define RST_CPU BIT(0)
+
+#define DIV_DC_SHIFT 26
+#define DIV_CPU_SHIFT 20
+#define DIV_DDR_SHIFT 14
+
+#define DIV_DC_WIDTH 4
+#define DIV_CPU_WIDTH 4
+#define DIV_DDR_WIDTH 4
+
+#define BYPASS_DC_SHIFT 12
+#define BYPASS_DDR_SHIFT 10
+#define BYPASS_CPU_SHIFT 8
+
+#define BYPASS_DC_WIDTH 1
+#define BYPASS_DDR_WIDTH 1
+#define BYPASS_CPU_WIDTH 1
+
+#elif defined(CONFIG_LOONGSON1_LS1C)
+/* PLL/SDRAM Frequency configuration register Bits */
+#define PLL_VALID BIT(31)
+#define FRAC_N GENMASK(23, 16)
+#define RST_TIME GENMASK(3, 2)
+#define SDRAM_DIV GENMASK(1, 0)
+
+/* CPU/CAMERA/DC Frequency configuration register Bits */
+#define DIV_DC_EN BIT(31)
+#define DIV_DC GENMASK(30, 24)
+#define DIV_CAM_EN BIT(23)
+#define DIV_CAM GENMASK(22, 16)
+#define DIV_CPU_EN BIT(15)
+#define DIV_CPU GENMASK(14, 8)
+#define DIV_DC_SEL_EN BIT(5)
+#define DIV_DC_SEL BIT(4)
+#define DIV_CAM_SEL_EN BIT(3)
+#define DIV_CAM_SEL BIT(2)
+#define DIV_CPU_SEL_EN BIT(1)
+#define DIV_CPU_SEL BIT(0)
+
+#define DIV_DC_SHIFT 24
+#define DIV_CAM_SHIFT 16
+#define DIV_CPU_SHIFT 8
+#define DIV_DDR_SHIFT 0
+
+#define DIV_DC_WIDTH 7
+#define DIV_CAM_WIDTH 7
+#define DIV_CPU_WIDTH 7
+#define DIV_DDR_WIDTH 2
+
+#endif
+
+#endif /* __ASM_MACH_LOONGSON32_REGS_CLK_H */
diff --git a/arch/mips/mach-loongson/include/mach/regs-mux.h b/arch/mips/mach-loongson/include/mach/regs-mux.h
new file mode 100644
index 0000000000..95788a4f03
--- /dev/null
+++ b/arch/mips/mach-loongson/include/mach/regs-mux.h
@@ -0,0 +1,124 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ * Copyright (c) 2014 Zhang, Keguang <keguang.zhang@gmail.com>
+ *
+ * Loongson 1 MUX Register Definitions.
+ */
+
+#ifndef __ASM_MACH_LOONGSON32_REGS_MUX_H
+#define __ASM_MACH_LOONGSON32_REGS_MUX_H
+
+#define LS1X_MUX_REG(x) \
+ ((void __iomem *)KSEG1ADDR(LS1X_MUX_BASE + (x)))
+
+#define LS1X_MUX_CTRL0 LS1X_MUX_REG(0x0)
+#define LS1X_MUX_CTRL1 LS1X_MUX_REG(0x4)
+
+#if defined(CONFIG_LOONGSON1_LS1B)
+/* MUX CTRL0 Register Bits */
+#define UART0_USE_PWM23 BIT(28)
+#define UART0_USE_PWM01 BIT(27)
+#define UART1_USE_LCD0_5_6_11 BIT(26)
+#define I2C2_USE_CAN1 BIT(25)
+#define I2C1_USE_CAN0 BIT(24)
+#define NAND3_USE_UART5 BIT(23)
+#define NAND3_USE_UART4 BIT(22)
+#define NAND3_USE_UART1_DAT BIT(21)
+#define NAND3_USE_UART1_CTS BIT(20)
+#define NAND3_USE_PWM23 BIT(19)
+#define NAND3_USE_PWM01 BIT(18)
+#define NAND2_USE_UART5 BIT(17)
+#define NAND2_USE_UART4 BIT(16)
+#define NAND2_USE_UART1_DAT BIT(15)
+#define NAND2_USE_UART1_CTS BIT(14)
+#define NAND2_USE_PWM23 BIT(13)
+#define NAND2_USE_PWM01 BIT(12)
+#define NAND1_USE_UART5 BIT(11)
+#define NAND1_USE_UART4 BIT(10)
+#define NAND1_USE_UART1_DAT BIT(9)
+#define NAND1_USE_UART1_CTS BIT(8)
+#define NAND1_USE_PWM23 BIT(7)
+#define NAND1_USE_PWM01 BIT(6)
+#define GMAC1_USE_UART1 BIT(4)
+#define GMAC1_USE_UART0 BIT(3)
+#define LCD_USE_UART0_DAT BIT(2)
+#define LCD_USE_UART15 BIT(1)
+#define LCD_USE_UART0 BIT(0)
+
+/* MUX CTRL1 Register Bits */
+#define USB_RESET BIT(31)
+#define SPI1_CS_USE_PWM01 BIT(24)
+#define SPI1_USE_CAN BIT(23)
+#define DISABLE_DDR_CONFSPACE BIT(20)
+#define DDR32TO16EN BIT(16)
+#define GMAC1_SHUT BIT(13)
+#define GMAC0_SHUT BIT(12)
+#define USB_SHUT BIT(11)
+#define UART1_3_USE_CAN1 BIT(5)
+#define UART1_2_USE_CAN0 BIT(4)
+#define GMAC1_USE_TXCLK BIT(3)
+#define GMAC0_USE_TXCLK BIT(2)
+#define GMAC1_USE_PWM23 BIT(1)
+#define GMAC0_USE_PWM01 BIT(0)
+
+#elif defined(CONFIG_LOONGSON1_LS1C)
+
+/* SHUT_CTRL Register Bits */
+#define UART_SPLIT GENMASK(31, 30)
+#define OUTPUT_CLK GENMASK(29, 26)
+#define ADC_SHUT BIT(25)
+#define SDIO_SHUT BIT(24)
+#define DMA2_SHUT BIT(23)
+#define DMA1_SHUT BIT(22)
+#define DMA0_SHUT BIT(21)
+#define SPI1_SHUT BIT(20)
+#define SPI0_SHUT BIT(19)
+#define I2C2_SHUT BIT(18)
+#define I2C1_SHUT BIT(17)
+#define I2C0_SHUT BIT(16)
+#define AC97_SHUT BIT(15)
+#define I2S_SHUT BIT(14)
+#define UART3_SHUT BIT(13)
+#define UART2_SHUT BIT(12)
+#define UART1_SHUT BIT(11)
+#define UART0_SHUT BIT(10)
+#define CAN1_SHUT BIT(9)
+#define CAN0_SHUT BIT(8)
+#define ECC_SHUT BIT(7)
+#define GMAC_SHUT BIT(6)
+#define USBHOST_SHUT BIT(5)
+#define USBOTG_SHUT BIT(4)
+#define SDRAM_SHUT BIT(3)
+#define SRAM_SHUT BIT(2)
+#define CAM_SHUT BIT(1)
+#define LCD_SHUT BIT(0)
+
+#define UART_SPLIT_SHIFT 30
+#define OUTPUT_CLK_SHIFT 26
+
+/* MISC_CTRL Register Bits */
+#define USBHOST_RSTN BIT(31)
+#define PHY_INTF_SELI GENMASK(30, 28)
+#define AC97_EN BIT(25)
+#define SDIO_DMA_EN GENMASK(24, 23)
+#define ADC_DMA_EN BIT(22)
+#define SDIO_USE_SPI1 BIT(17)
+#define SDIO_USE_SPI0 BIT(16)
+#define SRAM_CTRL GENMASK(15, 0)
+
+#define PHY_INTF_SELI_SHIFT 28
+#define SDIO_DMA_EN_SHIFT 23
+#define SRAM_CTRL_SHIFT 0
+
+#define LS1X_CBUS_REG(n, x) \
+ ((void __iomem *)KSEG1ADDR(LS1X_CBUS_BASE + (n * 0x04) + (x)))
+
+#define LS1X_CBUS_FIRST(n) LS1X_CBUS_REG(n, 0x00)
+#define LS1X_CBUS_SECOND(n) LS1X_CBUS_REG(n, 0x10)
+#define LS1X_CBUS_THIRD(n) LS1X_CBUS_REG(n, 0x20)
+#define LS1X_CBUS_FOURTHT(n) LS1X_CBUS_REG(n, 0x30)
+#define LS1X_CBUS_FIFTHT(n) LS1X_CBUS_REG(n, 0x40)
+
+#endif
+
+#endif /* __ASM_MACH_LOONGSON32_REGS_MUX_H */
diff --git a/arch/mips/mach-loongson/include/mach/regs-pwm.h b/arch/mips/mach-loongson/include/mach/regs-pwm.h
new file mode 100644
index 0000000000..ec870c82d4
--- /dev/null
+++ b/arch/mips/mach-loongson/include/mach/regs-pwm.h
@@ -0,0 +1,25 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ * Copyright (c) 2014 Zhang, Keguang <keguang.zhang@gmail.com>
+ *
+ * Loongson 1 PWM Register Definitions.
+ */
+
+#ifndef __ASM_MACH_LOONGSON32_REGS_PWM_H
+#define __ASM_MACH_LOONGSON32_REGS_PWM_H
+
+/* Loongson 1 PWM Timer Register Definitions */
+#define PWM_CNT 0x0
+#define PWM_HRC 0x4
+#define PWM_LRC 0x8
+#define PWM_CTRL 0xc
+
+/* PWM Control Register Bits */
+#define CNT_RST BIT(7)
+#define INT_SR BIT(6)
+#define INT_EN BIT(5)
+#define PWM_SINGLE BIT(4)
+#define PWM_OE BIT(3)
+#define CNT_EN BIT(0)
+
+#endif /* __ASM_MACH_LOONGSON32_REGS_PWM_H */
diff --git a/arch/mips/mach-loongson/include/mach/regs-rtc.h b/arch/mips/mach-loongson/include/mach/regs-rtc.h
new file mode 100644
index 0000000000..a3d096be16
--- /dev/null
+++ b/arch/mips/mach-loongson/include/mach/regs-rtc.h
@@ -0,0 +1,19 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ * Copyright (c) 2016 Yang Ling <gnaygnil@gmail.com>
+ *
+ * Loongson 1 RTC timer Register Definitions.
+ */
+
+#ifndef __ASM_MACH_LOONGSON32_REGS_RTC_H
+#define __ASM_MACH_LOONGSON32_REGS_RTC_H
+
+#define LS1X_RTC_REG(x) \
+ ((void __iomem *)KSEG1ADDR(LS1X_RTC_BASE + (x)))
+
+#define LS1X_RTC_CTRL LS1X_RTC_REG(0x40)
+
+#define RTC_EXTCLK_OK (BIT(5) | BIT(8))
+#define RTC_EXTCLK_EN BIT(8)
+
+#endif /* __ASM_MACH_LOONGSON32_REGS_RTC_H */
diff --git a/arch/mips/mach-loongson/include/mach/regs-wdt.h b/arch/mips/mach-loongson/include/mach/regs-wdt.h
new file mode 100644
index 0000000000..c6d345fe13
--- /dev/null
+++ b/arch/mips/mach-loongson/include/mach/regs-wdt.h
@@ -0,0 +1,15 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ * Copyright (c) 2011 Zhang, Keguang <keguang.zhang@gmail.com>
+ *
+ * Loongson 1 Watchdog Register Definitions.
+ */
+
+#ifndef __ASM_MACH_LOONGSON32_REGS_WDT_H
+#define __ASM_MACH_LOONGSON32_REGS_WDT_H
+
+#define WDT_EN 0x0
+#define WDT_TIMER 0x4
+#define WDT_SET 0x8
+
+#endif /* __ASM_MACH_LOONGSON32_REGS_WDT_H */
diff --git a/arch/mips/mach-loongson/loongson1_reset.c b/arch/mips/mach-loongson/loongson1_reset.c
index 3763a109ea..a6c05905de 100644
--- a/arch/mips/mach-loongson/loongson1_reset.c
+++ b/arch/mips/mach-loongson/loongson1_reset.c
@@ -11,9 +11,9 @@
static void __noreturn longhorn_restart_soc(struct restart_handler *rst)
{
- __raw_writel(0x1, LS1X_WDT_EN);
- __raw_writel(0x1, LS1X_WDT_SET);
- __raw_writel(0x1, LS1X_WDT_TIMER);
+ __raw_writel(0x1, WDT_EN);
+ __raw_writel(0x1, WDT_SET);
+ __raw_writel(0x1, WDT_TIMER);
hang();
}
diff --git a/arch/sandbox/board/dev-random.c b/arch/sandbox/board/dev-random.c
index f65e5ef6e5..60295e9fce 100644
--- a/arch/sandbox/board/dev-random.c
+++ b/arch/sandbox/board/dev-random.c
@@ -4,10 +4,6 @@
devrandom_t *devrandom_init(void) {
devrandom_t *fds = xzalloc(sizeof(*fds));
- fds->randomfd = linux_open("/dev/random", false);
- if (fds->randomfd < 0)
- return ERR_PTR(-EPERM);
-
fds->urandomfd = linux_open("/dev/urandom", false);
if (fds->urandomfd < 0)
return ERR_PTR(-EPERM);
@@ -17,8 +13,7 @@ devrandom_t *devrandom_init(void) {
int devrandom_read(devrandom_t *devrandom, void *buf, size_t len, int wait)
{
- if (wait)
- return linux_read(devrandom->randomfd, buf, len);
+ (void)wait; /* /dev/urandom won't block */
return linux_read(devrandom->urandomfd, buf, len);
}
diff --git a/arch/sandbox/mach-sandbox/include/mach/linux.h b/arch/sandbox/mach-sandbox/include/mach/linux.h
index 1e64d41c6a..9759a376ec 100644
--- a/arch/sandbox/mach-sandbox/include/mach/linux.h
+++ b/arch/sandbox/mach-sandbox/include/mach/linux.h
@@ -52,7 +52,6 @@ int barebox_libftdi1_update(struct ft2232_bitbang *ftbb);
void barebox_libftdi1_close(void);
typedef struct {
- int randomfd;
int urandomfd;
} devrandom_t;
devrandom_t *devrandom_init(void);
diff --git a/arch/sandbox/os/common.c b/arch/sandbox/os/common.c
index 86118822a1..3ad12b4a30 100644
--- a/arch/sandbox/os/common.c
+++ b/arch/sandbox/os/common.c
@@ -39,6 +39,8 @@
#include <signal.h>
#include <sys/select.h>
#include <sys/wait.h>
+#include <sys/ioctl.h>
+#include <linux/fs.h>
/*
* ...except the ones needed to connect with barebox
*/
@@ -260,11 +262,17 @@ static int add_image(char *str, char *devname_template, int *devname_number)
hf->size = s.st_size;
hf->devname = strdup(devname);
+ if (S_ISBLK(s.st_mode)) {
+ if (ioctl(fd, BLKGETSIZE64, &hf->size) == -1) {
+ perror("ioctl");
+ goto err_out;
+ }
+ }
hf->base = (unsigned long)mmap(NULL, hf->size,
PROT_READ | (readonly ? 0 : PROT_WRITE),
MAP_SHARED, fd, 0);
if ((void *)hf->base == MAP_FAILED)
- printf("warning: mmapping %s failed\n", filename);
+ printf("warning: mmapping %s failed: %s\n", filename, strerror(errno));
ret = barebox_register_filedev(hf);
if (ret)
diff --git a/arch/x86/include/asm/linkage.h b/arch/x86/include/asm/linkage.h
new file mode 100644
index 0000000000..a8d1bdb7de
--- /dev/null
+++ b/arch/x86/include/asm/linkage.h
@@ -0,0 +1,6 @@
+#ifndef __ASM_LINKAGE_H
+#define __ASM_LINKAGE_H
+
+/* referenced by <linux/linkage.h> */
+
+#endif
diff --git a/arch/x86/mach-efi/reloc_x86_64.c b/arch/x86/mach-efi/reloc_x86_64.c
index 1db72f5dbc..e83bacb302 100644
--- a/arch/x86/mach-efi/reloc_x86_64.c
+++ b/arch/x86/mach-efi/reloc_x86_64.c
@@ -35,11 +35,14 @@
SUCH DAMAGE.
*/
+#include <linux/linkage.h>
#include <common.h>
#include <efi.h>
#include <elf.h>
+asmlinkage efi_status_t _relocate (long, Elf64_Dyn *, efi_handle_t, efi_system_table_t *);
+
efi_status_t _relocate (long ldbase, Elf64_Dyn *dyn, efi_handle_t image, efi_system_table_t *systab)
{
long relsz = 0, relent = 0;
diff --git a/commands/Kconfig b/commands/Kconfig
index 0189b4715b..a6db52ae54 100644
--- a/commands/Kconfig
+++ b/commands/Kconfig
@@ -1389,8 +1389,10 @@ config CMD_PASSWD
help
Set password
- 'Interactively asks for a password. The digest of this password will be
- stored in /env/etc//passwd. This is then used by the 'login' command.
+ Interactively asks for a password. The digest of this password will be
+ stored in /env/etc/passwd. This is then used by the 'login' command.
+
+ Passwords can be generated on the host machine using barebox sandbox.
Entering an empty string will disable the password function.
diff --git a/commands/cp.c b/commands/cp.c
index 54934dd64f..845dae6b15 100644
--- a/commands/cp.c
+++ b/commands/cp.c
@@ -100,13 +100,14 @@ BAREBOX_CMD_HELP_START(cp)
BAREBOX_CMD_HELP_TEXT("Copy file from SRC to DEST.")
BAREBOX_CMD_HELP_TEXT("")
BAREBOX_CMD_HELP_TEXT("Options:")
+BAREBOX_CMD_HELP_OPT ("-r", "recursive")
BAREBOX_CMD_HELP_OPT ("-v", "verbose")
BAREBOX_CMD_HELP_END
BAREBOX_CMD_START(cp)
.cmd = do_cp,
BAREBOX_CMD_DESC("copy files")
- BAREBOX_CMD_OPTS("[-v] SRC DEST")
+ BAREBOX_CMD_OPTS("[-rv] SRC DEST")
BAREBOX_CMD_GROUP(CMD_GRP_FILE)
BAREBOX_CMD_HELP(cmd_cp_help)
BAREBOX_CMD_END
diff --git a/commands/edit.c b/commands/edit.c
index ba6a8c7cdd..4e661df14f 100644
--- a/commands/edit.c
+++ b/commands/edit.c
@@ -55,7 +55,7 @@ static int scrcol = 0; /* the first column on screen */
static void pos(int x, int y)
{
- printf("%c[%d;%dH", 27, y + 2, x + 1);
+ printf("\x1b[%d;%dH", y + 2, x + 1);
}
static char *screenline(char *line, int *pos)
@@ -110,7 +110,7 @@ static void refresh_line(struct line *line, int ypos)
char *str = screenline(line->data, NULL) + scrcol;
pos(0, ypos);
str[screenwidth] = 0;
- printf("%s%c[K", str, 27);
+ printf("%s\x1b[K", str);
pos(cursx, cursy);
}
@@ -130,7 +130,7 @@ static void refresh(int full)
if (!full) {
if (smartscroll) {
if (scrline->next == lastscrline) {
- printf("%c[1T", 27);
+ printf("\x1b[1T");
refresh_line(scrline, 0);
pos(0, screenheight);
printf("%*s", screenwidth, "");
@@ -138,7 +138,7 @@ static void refresh(int full)
}
if (scrline->prev == lastscrline) {
- printf("%c[1S", 27);
+ printf("\x1b[1S");
for (i = 0; i < screenheight - 1; i++) {
l = l->next;
if (!l)
@@ -378,8 +378,128 @@ static void getwinsize(void)
pos(0, 0);
}
+static void statusbar(const char *str)
+{
+ pos(0, screenheight+1);
+ printf("%*c\r%s", screenwidth, ' ', str);
+ pos(cursx, cursy);
+}
+
+static int read_modal_key(bool is_modal)
+{
+ static enum { MODE_INSERT, MODE_NORMAL } mode = MODE_NORMAL;
+ static int backlog[2] = { -1, -1 };
+ int c;
+
+ if (backlog[0] >= 0) {
+ /* pop a character */
+ c = backlog[0];
+ backlog[0] = backlog[1];
+ backlog[1] = -1;
+ } else {
+ c = read_key();
+ }
+
+ if (is_modal && mode == MODE_INSERT && (c == -1 || c == CTL_CH('c'))) {
+ mode = MODE_NORMAL;
+ statusbar("");
+ return -EAGAIN;
+ }
+
+ if (!is_modal || mode == MODE_INSERT)
+ return c;
+
+ switch (c) {
+ case -1: /* invalid escape, e.g. two escapes in a row */
+ break;
+ case 'i':
+ statusbar("-- INSERT --");
+ mode = MODE_INSERT;
+ break;
+ case 'h':
+ return BB_KEY_LEFT;
+ case 'j':
+ return BB_KEY_DOWN;
+ case 'k':
+ return BB_KEY_UP;
+ case 'a':
+ statusbar("-- INSERT --");
+ mode = MODE_INSERT;
+ /* fall through */
+ case 'l':
+ return BB_KEY_RIGHT;
+ case 'O':
+ backlog[0] = '\n';
+ backlog[1] = BB_KEY_UP;
+ /* fall through */
+ case 'I':
+ statusbar("-- INSERT --");
+ mode = MODE_INSERT;
+ /* fall through */
+ case '^':
+ case '0':
+ return BB_KEY_HOME;
+ case 'g':
+ c = read_key();
+ if (c != 'g')
+ break;
+ backlog[0] = CTL_CH('u');
+ backlog[1] = CTL_CH('u');
+ /* fall through */
+ case CTL_CH('u'):
+ return BB_KEY_PAGEUP;
+ case 'G':
+ backlog[0] = CTL_CH('d');
+ backlog[1] = CTL_CH('d');
+ /* fall through */
+ case CTL_CH('d'):
+ return BB_KEY_PAGEDOWN;
+ case 'o':
+ backlog[0] = '\n';
+ /* fall through */
+ case 'A':
+ statusbar("-- INSERT --");
+ mode = MODE_INSERT;
+ /* fall through */
+ case '$':
+ return BB_KEY_END;
+ case CTL_CH('c'):
+ statusbar("Type ZQ to abandon all changes and exit vi."
+ "Type ZZ to exit while saving them.");
+ break;
+ case 'x':
+ return BB_KEY_DEL;
+ case 'X':
+ return '\b';
+ case BB_KEY_PAGEUP:
+ case BB_KEY_PAGEDOWN:
+ case BB_KEY_HOME:
+ case BB_KEY_END:
+ case BB_KEY_UP:
+ case BB_KEY_DOWN:
+ case BB_KEY_RIGHT:
+ case BB_KEY_LEFT:
+ return c;
+ case ':':
+ statusbar("ERROR: command mode not supported");
+ break;
+ case 'Z':
+ c = read_key();
+ if (c == 'Z')
+ return CTL_CH('d');
+ if (c == 'Q')
+ return CTL_CH('c');
+ default:
+ statusbar("ERROR: not implemented");
+ break;
+ }
+
+ return -EAGAIN;
+}
+
static int do_edit(int argc, char *argv[])
{
+ bool is_vi = false;
int lastscrcol;
int i;
int linepos;
@@ -401,10 +521,14 @@ static int do_edit(int argc, char *argv[])
else
screenheight = 25;
- /* check if we are called as "sedit" instead of "edit" */
- if (*argv[0] == 's') {
+ /* check if we are not called as "edit" */
+ if (*argv[0] != 'e') {
smartscroll = 1;
getwinsize();
+
+ /* check if we are called as "vi" */
+ if (*argv[0] == 'v')
+ is_vi = true;
}
buffer = NULL;
@@ -420,18 +544,26 @@ static int do_edit(int argc, char *argv[])
lastscrline = scrline;
lastscrcol = 0;
- printf("%c[2J", 27);
+ printf("\x1b[2J");
pos(0, -1);
- printf("%c[7m %-25s <ctrl-d>: Save and quit <ctrl-c>: quit %c[0m",
- 27, argv[1], 27);
- printf("%c[2;%dr", 27, screenheight);
-
- screenheight--; /* status line */
+ if (is_vi) {
+ screenheight -= 2;
+ printf("\x1b[7m%*c\x1b[0m", screenwidth , ' ');
+ pos(0, screenheight-1);
+ printf("\x1b[7m%*c\x1b[0m", screenwidth , ' ');
+ printf("\r\x1b[7m%-25s\x1b[0m", argv[1]);
+ } else {
+ printf("\x1b[7m %-25s <ctrl-d>: Save and quit <ctrl-c>: quit \x1b[0m",
+ argv[1]);
+ }
+ printf("\x1b[2;%dr", screenheight);
pos(0, 0);
+ screenheight--; /* status line */
+
refresh(1);
while (1) {
@@ -469,7 +601,11 @@ static int do_edit(int argc, char *argv[])
lastscrline = scrline;
pos(cursx, cursy);
- c = read_key();
+again:
+ c = read_modal_key(is_vi);
+ if (c == -EAGAIN)
+ goto again;
+
switch (c) {
case BB_KEY_UP:
if (!curline->prev)
@@ -554,12 +690,12 @@ static int do_edit(int argc, char *argv[])
}
out:
free_buffer();
- printf("%c[2J%c[r", 27, 27);
+ printf("\x1b[2J\x1b[r");
printf("\n");
return ret;
}
-static const char * const edit_aliases[] = { "sedit", NULL};
+static const char * const edit_aliases[] = { "sedit", "vi", NULL};
BAREBOX_CMD_HELP_START(edit)
BAREBOX_CMD_HELP_TEXT("Use cursor keys, Ctrl-C to exit and Ctrl-D to exit-with-save.")
diff --git a/common/Kconfig b/common/Kconfig
index b840242ac9..d397d8bc4d 100644
--- a/common/Kconfig
+++ b/common/Kconfig
@@ -959,11 +959,11 @@ config STATE_CRYPTO
for more information.
config STATE_BACKWARD_COMPATIBLE
- bool "backward compatible 'direct storage backend'"
+ bool "backward compatible 'direct' storage backend"
depends on STATE
help
- With this option enabled the 'direct' storage backend keeps backward
- compatibility with older revisions of the state framework. Newer
+ With this option enabled, the 'direct' storage backend keeps backward
+ compatibility with the state framework of barebox <= v2016.08.0. Newer
revisions expect an additional 'meta header' and fail otherwise.
config BOOTCHOOSER
diff --git a/common/efi-devicepath.c b/common/efi-devicepath.c
index 24722284b4..3db2cea061 100644
--- a/common/efi-devicepath.c
+++ b/common/efi-devicepath.c
@@ -572,7 +572,7 @@ dev_path_vendor(struct string *str, void *dev_path)
}
cprintf(str, "Ven%s(%pU", type, &Vendor->Guid);
- if (efi_compare_guid(&Vendor->Guid, &efi_unknown_device_guid) == 0) {
+ if (efi_guidcmp(Vendor->Guid, efi_unknown_device_guid) == 0) {
/* GUID used by EFI to enumerate an EDD 1.1 device */
unknown_dev_path =
(struct unknown_device_vendor_device_path *) Vendor;
diff --git a/common/efi-guid.c b/common/efi-guid.c
index 1e45ccf4d2..2bf2395e85 100644
--- a/common/efi-guid.c
+++ b/common/efi-guid.c
@@ -52,7 +52,7 @@ const char *efi_guid_string(efi_guid_t *g)
EFI_GUID_STRING(EFI_ISA_IO_PROTOCOL_GUID, "ISA IO Protocol", "ISA IO Protocol");
EFI_GUID_STRING(EFI_STANDARD_ERROR_DEVICE_GUID, "Standard Error Device Guid", "EFI Standard Error Device Guid");
EFI_GUID_STRING(EFI_CONSOLE_OUT_DEVICE_GUID, "Console Out Device Guid", "EFI Console Out Device Guid");
- EFI_GUID_STRING(EFI_CONSOLE_IN_DEVICE_GUID, "Console In Device Guid", "EFI Conosle In Device Guid");
+ EFI_GUID_STRING(EFI_CONSOLE_IN_DEVICE_GUID, "Console In Device Guid", "EFI Console In Device Guid");
EFI_GUID_STRING(EFI_SIMPLE_TEXT_OUT_PROTOCOL_GUID, "Simple Text Out Protocol", "EFI 1.0 Simple Text Out Protocol");
EFI_GUID_STRING(EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL_GUID, "Simple Text Input Ex Protocol", "UEFI 2.1 Simple Text Input Ex Protocol");
EFI_GUID_STRING(EFI_SIMPLE_TEXT_IN_PROTOCOL_GUID, "Simple Text In Protocol", "EFI 1.0 Simple Text In Protocol");
diff --git a/common/efi/efi.c b/common/efi/efi.c
index a7b25cbbe2..73cea37036 100644
--- a/common/efi/efi.c
+++ b/common/efi/efi.c
@@ -17,6 +17,7 @@
*
*/
+#include <linux/linkage.h>
#include <common.h>
#include <linux/sizes.h>
#include <memory.h>
@@ -318,6 +319,8 @@ static int efi_init(void)
}
device_initcall(efi_init);
+asmlinkage efi_status_t efi_main(efi_handle_t, efi_system_table_t *);
+
/**
* efi-main - Entry point for EFI images
*/
diff --git a/common/partitions.c b/common/partitions.c
index 574b31fbbe..4162e86804 100644
--- a/common/partitions.c
+++ b/common/partitions.c
@@ -54,8 +54,8 @@ static int register_one_partition(struct block_device *blk,
partition_name = basprintf("%s.%d", blk->cdev.name, no);
if (!partition_name)
return -ENOMEM;
- dev_dbg(blk->dev, "Registering partition %s on drive %s\n",
- partition_name, blk->cdev.name);
+ dev_dbg(blk->dev, "Registering partition %s on drive %s (partuuid=%s)\n",
+ partition_name, blk->cdev.name, part->partuuid);
cdev = devfs_add_partition(blk->cdev.name,
start, size, 0, partition_name);
if (IS_ERR(cdev)) {
diff --git a/drivers/block/efi-block-io.c b/drivers/block/efi-block-io.c
index d167d814c2..39dbfb0f7a 100644
--- a/drivers/block/efi-block-io.c
+++ b/drivers/block/efi-block-io.c
@@ -14,6 +14,7 @@
#include <disks.h>
#include <efi/efi.h>
#include <efi/efi-device.h>
+#include <bootsource.h>
#define EFI_BLOCK_IO_PROTOCOL_REVISION2 0x00020001
#define EFI_BLOCK_IO_PROTOCOL_REVISION3 ((2<<16) | (31))
@@ -145,6 +146,7 @@ static int is_bio_usbdev(struct efi_device *efidev)
static int efi_bio_probe(struct efi_device *efidev)
{
int ret;
+ int instance;
struct efi_bio_priv *priv;
struct efi_block_io_media *media;
@@ -159,10 +161,14 @@ static int efi_bio_probe(struct efi_device *efidev)
efi_bio_print_info(priv);
priv->dev = &efidev->dev;
- if (is_bio_usbdev(efidev))
- priv->blk.cdev.name = xasprintf("usbdisk%d", cdev_find_free_index("usbdisk"));
- else
- priv->blk.cdev.name = xasprintf("disk%d", cdev_find_free_index("disk"));
+ if (is_bio_usbdev(efidev)) {
+ instance = cdev_find_free_index("usbdisk");
+ priv->blk.cdev.name = xasprintf("usbdisk%d", instance);
+ } else {
+ instance = cdev_find_free_index("disk");
+ priv->blk.cdev.name = xasprintf("disk%d", instance);
+ }
+
priv->blk.blockbits = ffs(media->block_size) - 1;
priv->blk.num_blocks = media->last_block + 1;
priv->blk.ops = &efi_bio_ops;
@@ -174,6 +180,9 @@ static int efi_bio_probe(struct efi_device *efidev)
if (ret)
return ret;
+ if (efi_get_bootsource() == efidev)
+ bootsource_set_instance(instance);
+
parse_partition_table(&priv->blk);
return 0;
diff --git a/drivers/efi/efi-device.c b/drivers/efi/efi-device.c
index 305d337aab..a1aac2dd31 100644
--- a/drivers/efi/efi-device.c
+++ b/drivers/efi/efi-device.c
@@ -311,7 +311,7 @@ static int efi_bus_match(struct device_d *dev, struct driver_d *drv)
int i;
for (i = 0; i < efidev->num_guids; i++) {
- if (!memcmp(&efidrv->guid, &efidev->guids[i], sizeof(efi_guid_t))) {
+ if (!efi_guidcmp(efidrv->guid, efidev->guids[i])) {
BS->handle_protocol(efidev->handle, &efidev->guids[i],
&efidev->protocol);
return 0;
@@ -398,13 +398,19 @@ static int is_bio_usbdev(struct efi_device *efidev)
return 0;
}
+static struct efi_device *bootdev;
+
+struct efi_device *efi_get_bootsource(void)
+{
+ return bootdev;
+}
+
static void efi_set_bootsource(void)
{
enum bootsource src = BOOTSOURCE_UNKNOWN;
int instance = BOOTSOURCE_INSTANCE_UNKNOWN;
efi_handle_t *efi_parent;
- struct efi_device *bootdev;
if (!efi_loaded_image->parent_handle)
goto out;
diff --git a/drivers/hw_random/Kconfig b/drivers/hw_random/Kconfig
index c57928204d..242a7ef278 100644
--- a/drivers/hw_random/Kconfig
+++ b/drivers/hw_random/Kconfig
@@ -15,11 +15,11 @@ config HWRNG_MXC_RNGC
Generator hardware found on some Freescale i.MX processors.
config HWRNG_DEV_RANDOM
- tristate "Linux /dev/random and /dev/urandom RNG"
+ tristate "Linux /dev/urandom RNG"
depends on SANDBOX
default y
help
- This driver allows use of the host provided /dev/random
- and /dev/urandom as barebox HWRNGs.
+ This driver allows use of the host provided /dev/urandom
+ as barebox HWRNGs.
endif
diff --git a/drivers/mci/Kconfig b/drivers/mci/Kconfig
index 08c8c84e8c..4a71a46097 100644
--- a/drivers/mci/Kconfig
+++ b/drivers/mci/Kconfig
@@ -153,4 +153,13 @@ config MMC_SPI_CRC_ON
help
Enable CRC protection for transfers
+config MCI_STM32_SDMMC2
+ bool "STMicroelectronics STM32H7 SD/MMC Host Controller support"
+ depends on ARM_AMBA
+ depends on RESET_CONTROLLER
+ help
+ This selects support for the SD/MMC controller on STM32H7 SoCs.
+ If you have a board based on such a SoC and with a SD/MMC slot,
+ say Y or M here.
+
endif
diff --git a/drivers/mci/Makefile b/drivers/mci/Makefile
index 25a1d073dc..04c1287fee 100644
--- a/drivers/mci/Makefile
+++ b/drivers/mci/Makefile
@@ -14,3 +14,4 @@ obj-$(CONFIG_MCI_TEGRA) += tegra-sdmmc.o
obj-$(CONFIG_MCI_SPI) += mci_spi.o
obj-$(CONFIG_MCI_DW) += dw_mmc.o
obj-$(CONFIG_MCI_MMCI) += mmci.o
+obj-$(CONFIG_MCI_STM32_SDMMC2) += stm32_sdmmc2.o
diff --git a/drivers/mci/stm32_sdmmc2.c b/drivers/mci/stm32_sdmmc2.c
new file mode 100644
index 0000000000..1a41c34d24
--- /dev/null
+++ b/drivers/mci/stm32_sdmmc2.c
@@ -0,0 +1,672 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Copyright (C) 2017, STMicroelectronics - All Rights Reserved
+ * Author(s): Patrice Chotard, <patrice.chotard@st.com> for STMicroelectronics.
+ */
+
+#include <common.h>
+#include <dma.h>
+#include <init.h>
+#include <linux/amba/bus.h>
+#include <linux/iopoll.h>
+#include <linux/log2.h>
+#include <linux/reset.h>
+#include <mci.h>
+
+#define DRIVER_NAME "stm32_sdmmc"
+
+/* SDMMC REGISTERS OFFSET */
+#define SDMMC_POWER 0x00 /* SDMMC power control */
+#define SDMMC_CLKCR 0x04 /* SDMMC clock control */
+#define SDMMC_ARG 0x08 /* SDMMC argument */
+#define SDMMC_CMD 0x0C /* SDMMC command */
+#define SDMMC_RESP1 0x14 /* SDMMC response 1 */
+#define SDMMC_RESP2 0x18 /* SDMMC response 2 */
+#define SDMMC_RESP3 0x1C /* SDMMC response 3 */
+#define SDMMC_RESP4 0x20 /* SDMMC response 4 */
+#define SDMMC_DTIMER 0x24 /* SDMMC data timer */
+#define SDMMC_DLEN 0x28 /* SDMMC data length */
+#define SDMMC_DCTRL 0x2C /* SDMMC data control */
+#define SDMMC_DCOUNT 0x30 /* SDMMC data counter */
+#define SDMMC_STA 0x34 /* SDMMC status */
+#define SDMMC_ICR 0x38 /* SDMMC interrupt clear */
+#define SDMMC_MASK 0x3C /* SDMMC mask */
+#define SDMMC_IDMACTRL 0x50 /* SDMMC DMA control */
+#define SDMMC_IDMABASE0 0x58 /* SDMMC DMA buffer 0 base address */
+
+/* SDMMC_POWER register */
+#define SDMMC_POWER_PWRCTRL_MASK GENMASK(1, 0)
+#define SDMMC_POWER_PWRCTRL_OFF 0
+#define SDMMC_POWER_PWRCTRL_CYCLE 2
+#define SDMMC_POWER_PWRCTRL_ON 3
+#define SDMMC_POWER_VSWITCH BIT(2)
+#define SDMMC_POWER_VSWITCHEN BIT(3)
+#define SDMMC_POWER_DIRPOL BIT(4)
+
+/* SDMMC_CLKCR register */
+#define SDMMC_CLKCR_CLKDIV GENMASK(9, 0)
+#define SDMMC_CLKCR_CLKDIV_MAX SDMMC_CLKCR_CLKDIV
+#define SDMMC_CLKCR_PWRSAV BIT(12)
+#define SDMMC_CLKCR_WIDBUS_4 BIT(14)
+#define SDMMC_CLKCR_WIDBUS_8 BIT(15)
+#define SDMMC_CLKCR_NEGEDGE BIT(16)
+#define SDMMC_CLKCR_HWFC_EN BIT(17)
+#define SDMMC_CLKCR_DDR BIT(18)
+#define SDMMC_CLKCR_BUSSPEED BIT(19)
+#define SDMMC_CLKCR_SELCLKRX_MASK GENMASK(21, 20)
+#define SDMMC_CLKCR_SELCLKRX_CK 0
+#define SDMMC_CLKCR_SELCLKRX_CKIN BIT(20)
+#define SDMMC_CLKCR_SELCLKRX_FBCK BIT(21)
+
+/* SDMMC_CMD register */
+#define SDMMC_CMD_CMDINDEX GENMASK(5, 0)
+#define SDMMC_CMD_CMDTRANS BIT(6)
+#define SDMMC_CMD_CMDSTOP BIT(7)
+#define SDMMC_CMD_WAITRESP GENMASK(9, 8)
+#define SDMMC_CMD_WAITRESP_0 BIT(8)
+#define SDMMC_CMD_WAITRESP_1 BIT(9)
+#define SDMMC_CMD_WAITINT BIT(10)
+#define SDMMC_CMD_WAITPEND BIT(11)
+#define SDMMC_CMD_CPSMEN BIT(12)
+#define SDMMC_CMD_DTHOLD BIT(13)
+#define SDMMC_CMD_BOOTMODE BIT(14)
+#define SDMMC_CMD_BOOTEN BIT(15)
+#define SDMMC_CMD_CMDSUSPEND BIT(16)
+
+/* SDMMC_DCTRL register */
+#define SDMMC_DCTRL_DTEN BIT(0)
+#define SDMMC_DCTRL_DTDIR BIT(1)
+#define SDMMC_DCTRL_DTMODE GENMASK(3, 2)
+#define SDMMC_DCTRL_DBLOCKSIZE GENMASK(7, 4)
+#define SDMMC_DCTRL_DBLOCKSIZE_SHIFT 4
+#define SDMMC_DCTRL_RWSTART BIT(8)
+#define SDMMC_DCTRL_RWSTOP BIT(9)
+#define SDMMC_DCTRL_RWMOD BIT(10)
+#define SDMMC_DCTRL_SDMMCEN BIT(11)
+#define SDMMC_DCTRL_BOOTACKEN BIT(12)
+#define SDMMC_DCTRL_FIFORST BIT(13)
+
+/* SDMMC_STA register */
+#define SDMMC_STA_CCRCFAIL BIT(0)
+#define SDMMC_STA_DCRCFAIL BIT(1)
+#define SDMMC_STA_CTIMEOUT BIT(2)
+#define SDMMC_STA_DTIMEOUT BIT(3)
+#define SDMMC_STA_TXUNDERR BIT(4)
+#define SDMMC_STA_RXOVERR BIT(5)
+#define SDMMC_STA_CMDREND BIT(6)
+#define SDMMC_STA_CMDSENT BIT(7)
+#define SDMMC_STA_DATAEND BIT(8)
+#define SDMMC_STA_DHOLD BIT(9)
+#define SDMMC_STA_DBCKEND BIT(10)
+#define SDMMC_STA_DABORT BIT(11)
+#define SDMMC_STA_DPSMACT BIT(12)
+#define SDMMC_STA_CPSMACT BIT(13)
+#define SDMMC_STA_TXFIFOHE BIT(14)
+#define SDMMC_STA_RXFIFOHF BIT(15)
+#define SDMMC_STA_TXFIFOF BIT(16)
+#define SDMMC_STA_RXFIFOF BIT(17)
+#define SDMMC_STA_TXFIFOE BIT(18)
+#define SDMMC_STA_RXFIFOE BIT(19)
+#define SDMMC_STA_BUSYD0 BIT(20)
+#define SDMMC_STA_BUSYD0END BIT(21)
+#define SDMMC_STA_SDMMCIT BIT(22)
+#define SDMMC_STA_ACKFAIL BIT(23)
+#define SDMMC_STA_ACKTIMEOUT BIT(24)
+#define SDMMC_STA_VSWEND BIT(25)
+#define SDMMC_STA_CKSTOP BIT(26)
+#define SDMMC_STA_IDMATE BIT(27)
+#define SDMMC_STA_IDMABTC BIT(28)
+
+/* SDMMC_ICR register */
+#define SDMMC_ICR_CCRCFAILC BIT(0)
+#define SDMMC_ICR_DCRCFAILC BIT(1)
+#define SDMMC_ICR_CTIMEOUTC BIT(2)
+#define SDMMC_ICR_DTIMEOUTC BIT(3)
+#define SDMMC_ICR_TXUNDERRC BIT(4)
+#define SDMMC_ICR_RXOVERRC BIT(5)
+#define SDMMC_ICR_CMDRENDC BIT(6)
+#define SDMMC_ICR_CMDSENTC BIT(7)
+#define SDMMC_ICR_DATAENDC BIT(8)
+#define SDMMC_ICR_DHOLDC BIT(9)
+#define SDMMC_ICR_DBCKENDC BIT(10)
+#define SDMMC_ICR_DABORTC BIT(11)
+#define SDMMC_ICR_BUSYD0ENDC BIT(21)
+#define SDMMC_ICR_SDMMCITC BIT(22)
+#define SDMMC_ICR_ACKFAILC BIT(23)
+#define SDMMC_ICR_ACKTIMEOUTC BIT(24)
+#define SDMMC_ICR_VSWENDC BIT(25)
+#define SDMMC_ICR_CKSTOPC BIT(26)
+#define SDMMC_ICR_IDMATEC BIT(27)
+#define SDMMC_ICR_IDMABTCC BIT(28)
+#define SDMMC_ICR_STATIC_FLAGS ((GENMASK(28, 21)) | (GENMASK(11, 0)))
+
+/* SDMMC_MASK register */
+#define SDMMC_MASK_CCRCFAILIE BIT(0)
+#define SDMMC_MASK_DCRCFAILIE BIT(1)
+#define SDMMC_MASK_CTIMEOUTIE BIT(2)
+#define SDMMC_MASK_DTIMEOUTIE BIT(3)
+#define SDMMC_MASK_TXUNDERRIE BIT(4)
+#define SDMMC_MASK_RXOVERRIE BIT(5)
+#define SDMMC_MASK_CMDRENDIE BIT(6)
+#define SDMMC_MASK_CMDSENTIE BIT(7)
+#define SDMMC_MASK_DATAENDIE BIT(8)
+#define SDMMC_MASK_DHOLDIE BIT(9)
+#define SDMMC_MASK_DBCKENDIE BIT(10)
+#define SDMMC_MASK_DABORTIE BIT(11)
+#define SDMMC_MASK_TXFIFOHEIE BIT(14)
+#define SDMMC_MASK_RXFIFOHFIE BIT(15)
+#define SDMMC_MASK_RXFIFOFIE BIT(17)
+#define SDMMC_MASK_TXFIFOEIE BIT(18)
+#define SDMMC_MASK_BUSYD0ENDIE BIT(21)
+#define SDMMC_MASK_SDMMCITIE BIT(22)
+#define SDMMC_MASK_ACKFAILIE BIT(23)
+#define SDMMC_MASK_ACKTIMEOUTIE BIT(24)
+#define SDMMC_MASK_VSWENDIE BIT(25)
+#define SDMMC_MASK_CKSTOPIE BIT(26)
+#define SDMMC_MASK_IDMABTCIE BIT(28)
+
+/* SDMMC_IDMACTRL register */
+#define SDMMC_IDMACTRL_IDMAEN BIT(0)
+
+#define SDMMC_CMD_TIMEOUT 0xFFFFFFFF
+#define SDMMC_BUSYD0END_TIMEOUT_US 2000000
+
+#define IS_RISING_EDGE(reg) ((reg) & SDMMC_CLKCR_NEGEDGE ? 0 : 1)
+
+struct stm32_sdmmc2_priv {
+ void __iomem *base;
+ struct mci_host mci;
+ struct device_d *dev;
+ struct clk *clk;
+ struct reset_control *reset_ctl;
+ u32 clk_reg_msk;
+ u32 pwr_reg_msk;
+};
+
+#define to_mci_host(mci) container_of(mci, struct stm32_sdmmc2_priv, mci)
+
+/*
+ * Reset the SDMMC with the RCC.SDMMCxRST register bit.
+ * This will reset the SDMMC to the reset state and the CPSM and DPSM
+ * to the Idle state. SDMMC is disabled, Signals Hiz.
+ */
+static int stm32_sdmmc2_reset(struct mci_host *mci, struct device_d *mci_dev)
+{
+ struct stm32_sdmmc2_priv *priv = to_mci_host(mci);
+
+ reset_control_assert(priv->reset_ctl);
+ udelay(2);
+ reset_control_deassert(priv->reset_ctl);
+
+ /* init the needed SDMMC register after reset */
+ writel(priv->pwr_reg_msk, priv->base + SDMMC_POWER);
+
+ return 0;
+}
+
+/*
+ * Set the SDMMC in power-cycle state.
+ * This will make that the SDMMC_D[7:0],
+ * SDMMC_CMD and SDMMC_CK are driven low, to prevent the card from being
+ * supplied through the signal lines.
+ */
+static void stm32_sdmmc2_pwrcycle(struct stm32_sdmmc2_priv *priv)
+{
+ if ((readl(priv->base + SDMMC_POWER) & SDMMC_POWER_PWRCTRL_MASK) ==
+ SDMMC_POWER_PWRCTRL_CYCLE)
+ return;
+
+ stm32_sdmmc2_reset(&priv->mci, priv->dev);
+ writel(SDMMC_POWER_PWRCTRL_CYCLE | priv->pwr_reg_msk,
+ priv->base + SDMMC_POWER);
+}
+
+/*
+ * set the SDMMC state Power-on: the card is clocked
+ * manage the SDMMC state control:
+ * Reset => Power-Cycle => Power-Off => Power
+ * PWRCTRL=10 PWCTRL=00 PWCTRL=11
+ */
+static void stm32_sdmmc2_pwron(struct stm32_sdmmc2_priv *priv)
+{
+ u32 pwrctrl =
+ readl(priv->base + SDMMC_POWER) & SDMMC_POWER_PWRCTRL_MASK;
+
+ if (pwrctrl == SDMMC_POWER_PWRCTRL_ON)
+ return;
+
+ /* warning: same PWRCTRL value after reset and for power-off state
+ * it is the reset state here = the only managed by the driver
+ */
+ if (pwrctrl == SDMMC_POWER_PWRCTRL_OFF) {
+ writel(SDMMC_POWER_PWRCTRL_CYCLE | priv->pwr_reg_msk,
+ priv->base + SDMMC_POWER);
+ }
+
+ /*
+ * the remaining case is SDMMC_POWER_PWRCTRL_CYCLE
+ * switch to Power-Off state: SDMCC disable, signals drive 1
+ */
+ writel(SDMMC_POWER_PWRCTRL_OFF | priv->pwr_reg_msk,
+ priv->base + SDMMC_POWER);
+
+ /* After the 1ms delay set the SDMMC to power-on */
+ mdelay(1);
+ writel(SDMMC_POWER_PWRCTRL_ON | priv->pwr_reg_msk,
+ priv->base + SDMMC_POWER);
+
+ /* during the first 74 SDMMC_CK cycles the SDMMC is still disabled. */
+}
+
+static void stm32_sdmmc2_start_data(struct stm32_sdmmc2_priv *priv,
+ struct mci_data *data, u32 data_length)
+{
+ unsigned int num_bytes = data->blocks * data->blocksize;
+ u32 data_ctrl, idmabase0;
+
+ /* Configure the SDMMC DPSM (Data Path State Machine) */
+ data_ctrl = (__ilog2_u32(data->blocksize) <<
+ SDMMC_DCTRL_DBLOCKSIZE_SHIFT) &
+ SDMMC_DCTRL_DBLOCKSIZE;
+
+ if (data->flags & MMC_DATA_READ) {
+ data_ctrl |= SDMMC_DCTRL_DTDIR;
+ idmabase0 = (u32)data->dest;
+ } else {
+ idmabase0 = (u32)data->src;
+ }
+
+ /* Set the SDMMC DataLength value */
+ writel(data_length, priv->base + SDMMC_DLEN);
+
+ /* Write to SDMMC DCTRL */
+ writel(data_ctrl, priv->base + SDMMC_DCTRL);
+
+ if (data->flags & MMC_DATA_WRITE)
+ dma_sync_single_for_device((unsigned long)idmabase0,
+ num_bytes, DMA_TO_DEVICE);
+ else
+ dma_sync_single_for_device((unsigned long)idmabase0,
+ num_bytes, DMA_FROM_DEVICE);
+
+ /* Enable internal DMA */
+ writel(idmabase0, priv->base + SDMMC_IDMABASE0);
+ writel(SDMMC_IDMACTRL_IDMAEN, priv->base + SDMMC_IDMACTRL);
+}
+
+static void stm32_sdmmc2_start_cmd(struct stm32_sdmmc2_priv *priv,
+ struct mci_cmd *cmd, u32 cmd_param,
+ u32 data_length)
+{
+ u32 timeout = 0;
+
+ if (readl(priv->base + SDMMC_CMD) & SDMMC_CMD_CPSMEN)
+ writel(0, priv->base + SDMMC_CMD);
+
+ cmd_param |= cmd->cmdidx | SDMMC_CMD_CPSMEN;
+ if (cmd->resp_type & MMC_RSP_PRESENT) {
+ if (cmd->resp_type & MMC_RSP_136)
+ cmd_param |= SDMMC_CMD_WAITRESP;
+ else if (cmd->resp_type & MMC_RSP_CRC)
+ cmd_param |= SDMMC_CMD_WAITRESP_0;
+ else
+ cmd_param |= SDMMC_CMD_WAITRESP_1;
+ }
+
+ /*
+ * SDMMC_DTIME must be set in two case:
+ * - on data transfert.
+ * - on busy request.
+ * If not done or too short, the dtimeout flag occurs and DPSM stays
+ * enabled/busy and waits for abort (stop transmission cmd).
+ * Next data command is not possible whereas DPSM is activated.
+ */
+ if (data_length) {
+ timeout = SDMMC_CMD_TIMEOUT;
+ } else {
+ writel(0, priv->base + SDMMC_DCTRL);
+
+ if (cmd->resp_type & MMC_RSP_BUSY)
+ timeout = SDMMC_CMD_TIMEOUT;
+ }
+
+ /* Set the SDMMC Data TimeOut value */
+ writel(timeout, priv->base + SDMMC_DTIMER);
+
+ /* Clear flags */
+ writel(SDMMC_ICR_STATIC_FLAGS, priv->base + SDMMC_ICR);
+
+ /* Set SDMMC argument value */
+ writel(cmd->cmdarg, priv->base + SDMMC_ARG);
+
+ /* Set SDMMC command parameters */
+ writel(cmd_param, priv->base + SDMMC_CMD);
+}
+
+static int stm32_sdmmc2_end_cmd(struct stm32_sdmmc2_priv *priv,
+ struct mci_cmd *cmd)
+{
+ u32 mask = SDMMC_STA_CTIMEOUT;
+ u32 status;
+ int ret;
+
+ if (cmd->resp_type & MMC_RSP_PRESENT) {
+ mask |= SDMMC_STA_CMDREND;
+ if (cmd->resp_type & MMC_RSP_CRC)
+ mask |= SDMMC_STA_CCRCFAIL;
+ } else {
+ mask |= SDMMC_STA_CMDSENT;
+ }
+
+ /* Polling status register */
+ ret = readl_poll_timeout(priv->base + SDMMC_STA, status, status & mask,
+ SDMMC_BUSYD0END_TIMEOUT_US);
+ if (ret < 0) {
+ dev_err(priv->dev, "timeout reading SDMMC_STA register\n");
+ return ret;
+ }
+
+ /* Check status */
+ if (status & SDMMC_STA_CTIMEOUT) {
+ dev_err(priv->dev, "%s: error SDMMC_STA_CTIMEOUT (0x%x) for cmd %d\n",
+ __func__, status, cmd->cmdidx);
+ return -ETIMEDOUT;
+ }
+
+ if (status & SDMMC_STA_CCRCFAIL && cmd->resp_type & MMC_RSP_CRC) {
+ dev_err(priv->dev, "%s: error SDMMC_STA_CCRCFAIL (0x%x) for cmd %d\n",
+ __func__, status, cmd->cmdidx);
+ return -EILSEQ;
+ }
+
+ if (status & SDMMC_STA_CMDREND && cmd->resp_type & MMC_RSP_PRESENT) {
+ cmd->response[0] = readl(priv->base + SDMMC_RESP1);
+ if (cmd->resp_type & MMC_RSP_136) {
+ cmd->response[1] = readl(priv->base + SDMMC_RESP2);
+ cmd->response[2] = readl(priv->base + SDMMC_RESP3);
+ cmd->response[3] = readl(priv->base + SDMMC_RESP4);
+ }
+
+ /* Wait for BUSYD0END flag if busy status is detected */
+ if (cmd->resp_type & MMC_RSP_BUSY &&
+ status & SDMMC_STA_BUSYD0) {
+ mask = SDMMC_STA_DTIMEOUT | SDMMC_STA_BUSYD0END;
+
+ /* Polling status register */
+ ret = readl_poll_timeout(priv->base + SDMMC_STA,
+ status, status & mask,
+ SDMMC_BUSYD0END_TIMEOUT_US);
+
+ if (ret < 0) {
+ dev_err(priv->dev, "%s: timeout reading SDMMC_STA\n",
+ __func__);
+ return ret;
+ }
+
+ if (status & SDMMC_STA_DTIMEOUT) {
+ dev_err(priv->dev, "%s: error SDMMC_STA_DTIMEOUT (0x%x)\n",
+ __func__, status);
+ return -ETIMEDOUT;
+ }
+ }
+ }
+
+ return 0;
+}
+
+static int stm32_sdmmc2_end_data(struct stm32_sdmmc2_priv *priv,
+ struct mci_cmd *cmd,
+ struct mci_data *data)
+{
+ u32 mask = SDMMC_STA_DCRCFAIL | SDMMC_STA_DTIMEOUT |
+ SDMMC_STA_IDMATE | SDMMC_STA_DATAEND;
+ unsigned int num_bytes = data->blocks * data->blocksize;
+ u32 status;
+ int ret;
+
+ if (data->flags & MMC_DATA_READ)
+ mask |= SDMMC_STA_RXOVERR;
+ else
+ mask |= SDMMC_STA_TXUNDERR;
+
+ ret = readl_poll_timeout(priv->base + SDMMC_STA, status, status & mask,
+ SDMMC_BUSYD0END_TIMEOUT_US);
+ if (ret < 0) {
+ dev_err(priv->dev, "Time out on waiting for SDMMC_STA. cmd %d\n",
+ cmd->cmdidx);
+ return ret;
+ }
+
+ if (data->flags & MMC_DATA_WRITE)
+ dma_sync_single_for_cpu((unsigned long)data->src,
+ num_bytes, DMA_TO_DEVICE);
+ else
+ dma_sync_single_for_cpu((unsigned long)data->dest,
+ num_bytes, DMA_FROM_DEVICE);
+
+ if (status & SDMMC_STA_DCRCFAIL) {
+ dev_err(priv->dev, "error SDMMC_STA_DCRCFAIL (0x%x) for cmd %d\n",
+ status, cmd->cmdidx);
+ return -EILSEQ;
+ }
+
+ if (status & SDMMC_STA_DTIMEOUT) {
+ dev_err(priv->dev, "error SDMMC_STA_DTIMEOUT (0x%x) for cmd %d\n",
+ status, cmd->cmdidx);
+ return -ETIMEDOUT;
+ }
+
+ if (status & SDMMC_STA_TXUNDERR) {
+ dev_err(priv->dev, "error SDMMC_STA_TXUNDERR (0x%x) for cmd %d\n",
+ status, cmd->cmdidx);
+ return -EIO;
+ }
+
+ if (status & SDMMC_STA_RXOVERR) {
+ dev_err(priv->dev, "error SDMMC_STA_RXOVERR (0x%x) for cmd %d\n",
+ status, cmd->cmdidx);
+ return -EIO;
+ }
+
+ if (status & SDMMC_STA_IDMATE) {
+ dev_err(priv->dev, "%s: error SDMMC_STA_IDMATE (0x%x) for cmd %d\n",
+ __func__, status, cmd->cmdidx);
+ return -EIO;
+ }
+
+ return 0;
+}
+
+static int stm32_sdmmc2_send_cmd(struct mci_host *mci, struct mci_cmd *cmd,
+ struct mci_data *data)
+{
+ struct stm32_sdmmc2_priv *priv = to_mci_host(mci);
+ u32 cmdat = data ? SDMMC_CMD_CMDTRANS : 0;
+ u32 data_length;
+ int ret, retry = 3;
+
+retry_cmd:
+ data_length = 0;
+
+ if (data) {
+ data_length = data->blocks * data->blocksize;
+ stm32_sdmmc2_start_data(priv, data, data_length);
+ }
+
+ stm32_sdmmc2_start_cmd(priv, cmd, cmdat, data_length);
+
+ dev_dbg(priv->dev, "%s: send cmd %d data: 0x%x @ 0x%x\n", __func__,
+ cmd->cmdidx, data ? data_length : 0, (unsigned int)data);
+
+ ret = stm32_sdmmc2_end_cmd(priv, cmd);
+
+ if (data && !ret)
+ ret = stm32_sdmmc2_end_data(priv, cmd, data);
+
+ /* Clear flags */
+ writel(SDMMC_ICR_STATIC_FLAGS, priv->base + SDMMC_ICR);
+ if (data)
+ writel(0x0, priv->base + SDMMC_IDMACTRL);
+
+ /*
+ * To stop Data Path State Machine, a stop_transmission command
+ * shall be send on cmd or data errors.
+ */
+ if (ret && cmd->cmdidx != MMC_CMD_STOP_TRANSMISSION) {
+ struct mci_cmd stop_cmd;
+
+ stop_cmd.cmdidx = MMC_CMD_STOP_TRANSMISSION;
+ stop_cmd.cmdarg = 0;
+ stop_cmd.resp_type = MMC_RSP_R1b;
+
+ dev_dbg(priv->dev, "%s: send STOP command to abort dpsm treatments\n",
+ __func__);
+
+ data_length = 0;
+
+ stm32_sdmmc2_start_cmd(priv, &stop_cmd,
+ SDMMC_CMD_CMDSTOP, data_length);
+ ret = stm32_sdmmc2_end_cmd(priv, &stop_cmd);
+
+ writel(SDMMC_ICR_STATIC_FLAGS, priv->base + SDMMC_ICR);
+ }
+
+ if (ret && retry) {
+ dev_warn(priv->dev, "%s: cmd %d failed, retrying ...\n",
+ __func__, cmd->cmdidx);
+
+ stm32_sdmmc2_pwrcycle(priv);
+ stm32_sdmmc2_pwron(priv);
+ retry--;
+
+ goto retry_cmd;
+ }
+
+ dev_dbg(priv->dev, "%s: end for CMD %d, ret = %d\n", __func__,
+ cmd->cmdidx, ret);
+
+ return ret;
+}
+
+static void stm32_sdmmc2_set_ios(struct mci_host *mci, struct mci_ios *ios)
+{
+ struct stm32_sdmmc2_priv *priv = to_mci_host(mci);
+ u32 desired = mci->clock;
+ u32 sys_clock = clk_get_rate(priv->clk);
+ u32 clk = 0;
+
+ dev_dbg(priv->dev, "%s: bus_with = %d, clock = %d\n", __func__,
+ mci->bus_width, mci->clock);
+
+ if (mci->clock)
+ stm32_sdmmc2_pwron(priv);
+ else
+ stm32_sdmmc2_pwrcycle(priv);
+
+ /*
+ * clk_div = 0 => command and data generated on SDMMCCLK falling edge
+ * clk_div > 0 and NEGEDGE = 0 => command and data generated on
+ * SDMMCCLK rising edge
+ * clk_div > 0 and NEGEDGE = 1 => command and data generated on
+ * SDMMCCLK falling edge
+ */
+ if (desired && (sys_clock > desired ||
+ IS_RISING_EDGE(priv->clk_reg_msk))) {
+ clk = DIV_ROUND_UP(sys_clock, 2 * desired);
+ if (clk > SDMMC_CLKCR_CLKDIV_MAX)
+ clk = SDMMC_CLKCR_CLKDIV_MAX;
+ }
+
+ if (mci->bus_width == 4)
+ clk |= SDMMC_CLKCR_WIDBUS_4;
+ if (mci->bus_width == 8)
+ clk |= SDMMC_CLKCR_WIDBUS_8;
+
+ writel(clk | priv->clk_reg_msk | SDMMC_CLKCR_HWFC_EN,
+ priv->base + SDMMC_CLKCR);
+}
+
+static int stm32_sdmmc2_probe(struct amba_device *adev,
+ const struct amba_id *id)
+{
+ struct device_d *dev = &adev->dev;
+ struct device_node *np = dev->device_node;
+ struct stm32_sdmmc2_priv *priv;
+ struct mci_host *mci;
+ int ret;
+
+ priv = xzalloc(sizeof(*priv));
+
+ priv->base = amba_get_mem_region(adev);
+ priv->dev = dev;
+
+ mci = &priv->mci;
+ mci->send_cmd = stm32_sdmmc2_send_cmd,
+ mci->set_ios = stm32_sdmmc2_set_ios,
+ mci->init = stm32_sdmmc2_reset;
+ mci->hw_dev = dev;
+
+ priv->clk = clk_get(dev, NULL);
+ if (IS_ERR(priv->clk)) {
+ ret = PTR_ERR(priv->clk);
+ goto priv_free;
+ }
+
+ ret = clk_enable(priv->clk);
+ if (ret)
+ goto priv_free;
+
+ if (of_get_property(np, "st,neg-edge", NULL))
+ priv->clk_reg_msk |= SDMMC_CLKCR_NEGEDGE;
+ if (of_get_property(np, "st,sig-dir", NULL))
+ priv->pwr_reg_msk |= SDMMC_POWER_DIRPOL;
+ if (of_get_property(np, "st,use-ckin", NULL))
+ priv->clk_reg_msk |= SDMMC_CLKCR_SELCLKRX_CKIN;
+
+ priv->reset_ctl = reset_control_get(dev, NULL);
+ if (IS_ERR(priv->reset_ctl))
+ priv->reset_ctl = NULL;
+
+ mci->f_min = 400000;
+ /* f_max is taken from kernel v5.3 variant_stm32_sdmmc */
+ mci->f_max = 208000000;
+ mci->voltages = MMC_VDD_32_33 | MMC_VDD_33_34 | MMC_VDD_165_195;
+
+ mci_of_parse(&priv->mci);
+
+ if (mci->host_caps & (MMC_CAP_4_BIT_DATA | MMC_CAP_8_BIT_DATA)) {
+ dev_notice(dev, "Fixing bus-width to 1 due to driver limitation\n");
+ mci->host_caps &= ~(MMC_CAP_4_BIT_DATA | MMC_CAP_8_BIT_DATA);
+ }
+
+ return mci_register(&priv->mci);
+
+priv_free:
+ free(priv);
+
+ return ret;
+}
+
+static struct amba_id stm32_sdmmc2_ids[] = {
+ /* ST Micro STM32MP157C */
+ {
+ .id = 0x10153180,
+ .mask = 0xf0ffffff,
+ },
+ { 0, 0 },
+};
+
+static struct amba_driver stm32_sdmmc2_driver = {
+ .drv = {
+ .name = DRIVER_NAME,
+ },
+ .probe = stm32_sdmmc2_probe,
+ .id_table = stm32_sdmmc2_ids,
+};
+
+static int stm32_sdmmc2_init(void)
+{
+ amba_driver_register(&stm32_sdmmc2_driver);
+ return 0;
+}
+device_initcall(stm32_sdmmc2_init);
diff --git a/drivers/mfd/stpmic1.c b/drivers/mfd/stpmic1.c
index 88c7921990..eae6fe3a4e 100644
--- a/drivers/mfd/stpmic1.c
+++ b/drivers/mfd/stpmic1.c
@@ -69,7 +69,6 @@ static int __init stpmic1_probe(struct device_d *dev)
stpmic1->client = to_i2c_client(dev);
regmap = regmap_init(dev, &regmap_stpmic1_i2c_bus,
stpmic1, &stpmic1_regmap_i2c_config);
- dev->priv = regmap;
ret = regmap_register_cdev(regmap, NULL);
if (ret)
diff --git a/drivers/mfd/superio.c b/drivers/mfd/superio.c
index 0f08d56cb3..12d74b40f6 100644
--- a/drivers/mfd/superio.c
+++ b/drivers/mfd/superio.c
@@ -88,7 +88,7 @@ void superio_chip_add(struct superio_chip *siochip)
&superio_regmap_config);
if (IS_ERR(regmap))
pr_warn("creating %s regmap failed: %s\n",
- chipname, strerror(-PTR_ERR(regmap)));
+ chipname, strerrorp(regmap));
ret = regmap_register_cdev(regmap, chipname);
if (ret)
diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig
index 57f0b57d64..62e522a302 100644
--- a/drivers/net/Kconfig
+++ b/drivers/net/Kconfig
@@ -61,7 +61,7 @@ config DRIVER_NET_DAVINCI_EMAC
select PHYLIB
config DRIVER_NET_DESIGNWARE
- bool "Designware Universal MAC ethernet platform support"
+ bool "Designware Universal MAC1000 ethernet platform support"
depends on HAS_DMA
select PHYLIB
help
@@ -87,6 +87,31 @@ config DRIVER_NET_DESIGNWARE_SOCFPGA
endif
+config DRIVER_NET_DESIGNWARE_EQOS
+ bool "Designware Designware Ethernet QoS support"
+ depends on HAS_DMA
+ select PHYLIB
+ select OFTREE
+ help
+ This option enables support for the Synopsys
+ Designware Ethernet Quality-of-Service (GMAC4).
+
+if DRIVER_NET_DESIGNWARE_EQOS
+
+config DRIVER_NET_DESIGNWARE_STM32
+ bool "Designware EQOS STM32 driver"
+ select MFD_SYSCON
+ help
+ This option enables support for the ethernet MAC on the STM32MP platforms.
+
+config DRIVER_NET_DESIGNWARE_TEGRA186
+ bool "Designware Universal MAC ethernet driver for Tegra 186 platforms"
+ select RESET_CONTROLLER
+ help
+ This option enables support for the ethernet MAC on the Tegra186 & 194.
+
+endif
+
config DRIVER_NET_DM9K
bool "Davicom dm9k[E|A|B] ethernet driver"
depends on HAS_DM9000
diff --git a/drivers/net/Makefile b/drivers/net/Makefile
index f6a8213613..656d45a868 100644
--- a/drivers/net/Makefile
+++ b/drivers/net/Makefile
@@ -11,6 +11,9 @@ obj-$(CONFIG_DRIVER_NET_DAVINCI_EMAC) += davinci_emac.o
obj-$(CONFIG_DRIVER_NET_DESIGNWARE) += designware.o
obj-$(CONFIG_DRIVER_NET_DESIGNWARE_GENERIC) += designware_generic.o
obj-$(CONFIG_DRIVER_NET_DESIGNWARE_SOCFPGA) += designware_socfpga.o
+obj-$(CONFIG_DRIVER_NET_DESIGNWARE_EQOS) += designware_eqos.o
+obj-$(CONFIG_DRIVER_NET_DESIGNWARE_STM32) += designware_stm32.o
+obj-$(CONFIG_DRIVER_NET_DESIGNWARE_TEGRA186) += designware_tegra186.o
obj-$(CONFIG_DRIVER_NET_DM9K) += dm9k.o
obj-$(CONFIG_DRIVER_NET_E1000) += e1000/regio.o e1000/main.o e1000/eeprom.o
obj-$(CONFIG_DRIVER_NET_ENC28J60) += enc28j60.o
diff --git a/drivers/net/designware.h b/drivers/net/designware.h
index 305f674bf0..0a6a6bf1a4 100644
--- a/drivers/net/designware.h
+++ b/drivers/net/designware.h
@@ -35,6 +35,7 @@ struct dw_eth_dev {
struct dw_eth_drvdata {
bool enh_desc;
+ void *priv;
};
struct dw_eth_dev *dwc_drv_probe(struct device_d *dev);
diff --git a/drivers/net/designware_eqos.c b/drivers/net/designware_eqos.c
new file mode 100644
index 0000000000..a49239e057
--- /dev/null
+++ b/drivers/net/designware_eqos.c
@@ -0,0 +1,876 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (c) 2016, NVIDIA CORPORATION.
+ * Copyright (c) 2019, Ahmad Fatoum, Pengutronix
+ *
+ * Portions based on U-Boot's rtl8169.c and dwc_eth_qos.
+ */
+
+#include <common.h>
+#include <init.h>
+#include <dma.h>
+#include <net.h>
+#include <of_net.h>
+#include <linux/iopoll.h>
+#include <linux/time.h>
+#include <linux/sizes.h>
+
+#include "designware_eqos.h"
+
+/* Core registers */
+
+#define EQOS_MAC_REGS_BASE 0x000
+struct eqos_mac_regs {
+ u32 config; /* 0x000 */
+ u32 ext_config; /* 0x004 */
+ u32 unused_004[(0x070 - 0x008) / 4]; /* 0x008 */
+ u32 q0_tx_flow_ctrl; /* 0x070 */
+ u32 unused_070[(0x090 - 0x074) / 4]; /* 0x074 */
+ u32 rx_flow_ctrl; /* 0x090 */
+ u32 unused_094; /* 0x094 */
+ u32 txq_prty_map0; /* 0x098 */
+ u32 unused_09c; /* 0x09c */
+ u32 rxq_ctrl0; /* 0x0a0 */
+ u32 unused_0a4; /* 0x0a4 */
+ u32 rxq_ctrl2; /* 0x0a8 */
+ u32 unused_0ac[(0x0dc - 0x0ac) / 4]; /* 0x0ac */
+ u32 us_tic_counter; /* 0x0dc */
+ u32 unused_0e0[(0x11c - 0x0e0) / 4]; /* 0x0e0 */
+ u32 hw_feature0; /* 0x11c */
+ u32 hw_feature1; /* 0x120 */
+ u32 hw_feature2; /* 0x124 */
+ u32 unused_128[(0x200 - 0x128) / 4]; /* 0x128 */
+ u32 mdio_address; /* 0x200 */
+ u32 mdio_data; /* 0x204 */
+ u32 unused_208[(0x300 - 0x208) / 4]; /* 0x208 */
+ u32 macaddr0hi; /* 0x300 */
+ u32 macaddr0lo; /* 0x304 */
+};
+
+#define EQOS_MAC_CONFIGURATION_GPSLCE BIT(23)
+#define EQOS_MAC_CONFIGURATION_CST BIT(21)
+#define EQOS_MAC_CONFIGURATION_ACS BIT(20)
+#define EQOS_MAC_CONFIGURATION_WD BIT(19)
+#define EQOS_MAC_CONFIGURATION_JD BIT(17)
+#define EQOS_MAC_CONFIGURATION_JE BIT(16)
+#define EQOS_MAC_CONFIGURATION_PS BIT(15)
+#define EQOS_MAC_CONFIGURATION_FES BIT(14)
+#define EQOS_MAC_CONFIGURATION_DM BIT(13)
+#define EQOS_MAC_CONFIGURATION_TE BIT(1)
+#define EQOS_MAC_CONFIGURATION_RE BIT(0)
+
+#define EQOS_MAC_Q0_TX_FLOW_CTRL_PT_SHIFT 16
+#define EQOS_MAC_Q0_TX_FLOW_CTRL_PT_MASK 0xffff
+#define EQOS_MAC_Q0_TX_FLOW_CTRL_TFE BIT(1)
+
+#define EQOS_MAC_RX_FLOW_CTRL_RFE BIT(0)
+
+#define EQOS_MAC_TXQ_PRTY_MAP0_PSTQ0_SHIFT 0
+#define EQOS_MAC_TXQ_PRTY_MAP0_PSTQ0_MASK 0xff
+
+#define EQOS_MAC_RXQ_CTRL2_PSRQ0_SHIFT 0
+#define EQOS_MAC_RXQ_CTRL2_PSRQ0_MASK 0xff
+
+#define EQOS_MAC_HW_FEATURE1_TXFIFOSIZE_SHIFT 6
+#define EQOS_MAC_HW_FEATURE1_TXFIFOSIZE_MASK 0x1f
+#define EQOS_MAC_HW_FEATURE1_RXFIFOSIZE_SHIFT 0
+#define EQOS_MAC_HW_FEATURE1_RXFIFOSIZE_MASK 0x1f
+
+#define EQOS_MTL_REGS_BASE 0xd00
+struct eqos_mtl_regs {
+ u32 txq0_operation_mode; /* 0xd00 */
+ u32 unused_d04; /* 0xd04 */
+ u32 txq0_debug; /* 0xd08 */
+ u32 unused_d0c[(0xd18 - 0xd0c) / 4]; /* 0xd0c */
+ u32 txq0_quantum_weight; /* 0xd18 */
+ u32 unused_d1c[(0xd30 - 0xd1c) / 4]; /* 0xd1c */
+ u32 rxq0_operation_mode; /* 0xd30 */
+ u32 unused_d34; /* 0xd34 */
+ u32 rxq0_debug; /* 0xd38 */
+};
+
+#define EQOS_MTL_TXQ0_OPERATION_MODE_TQS_SHIFT 16
+#define EQOS_MTL_TXQ0_OPERATION_MODE_TQS_MASK 0x1ff
+#define EQOS_MTL_TXQ0_OPERATION_MODE_TXQEN_SHIFT 2
+#define EQOS_MTL_TXQ0_OPERATION_MODE_TXQEN_MASK 3
+#define EQOS_MTL_TXQ0_OPERATION_MODE_TXQEN_ENABLED 2
+#define EQOS_MTL_TXQ0_OPERATION_MODE_TSF BIT(1)
+#define EQOS_MTL_TXQ0_OPERATION_MODE_FTQ BIT(0)
+
+#define EQOS_MTL_TXQ0_DEBUG_TXQSTS BIT(4)
+#define EQOS_MTL_TXQ0_DEBUG_TRCSTS_SHIFT 1
+#define EQOS_MTL_TXQ0_DEBUG_TRCSTS_MASK 3
+
+#define EQOS_MTL_RXQ0_OPERATION_MODE_RQS_SHIFT 20
+#define EQOS_MTL_RXQ0_OPERATION_MODE_RQS_MASK 0x3ff
+#define EQOS_MTL_RXQ0_OPERATION_MODE_RFD_SHIFT 14
+#define EQOS_MTL_RXQ0_OPERATION_MODE_RFD_MASK 0x3f
+#define EQOS_MTL_RXQ0_OPERATION_MODE_RFA_SHIFT 8
+#define EQOS_MTL_RXQ0_OPERATION_MODE_RFA_MASK 0x3f
+#define EQOS_MTL_RXQ0_OPERATION_MODE_EHFC BIT(7)
+#define EQOS_MTL_RXQ0_OPERATION_MODE_RSF BIT(5)
+
+#define EQOS_MTL_RXQ0_DEBUG_PRXQ_SHIFT 16
+#define EQOS_MTL_RXQ0_DEBUG_PRXQ_MASK 0x7fff
+#define EQOS_MTL_RXQ0_DEBUG_RXQSTS_SHIFT 4
+#define EQOS_MTL_RXQ0_DEBUG_RXQSTS_MASK 3
+
+#define EQOS_DMA_REGS_BASE 0x1000
+struct eqos_dma_regs {
+ u32 mode; /* 0x1000 */
+ u32 sysbus_mode; /* 0x1004 */
+ u32 unused_1008[(0x1100 - 0x1008) / 4]; /* 0x1008 */
+ u32 ch0_control; /* 0x1100 */
+ u32 ch0_tx_control; /* 0x1104 */
+ u32 ch0_rx_control; /* 0x1108 */
+ u32 unused_110c; /* 0x110c */
+ u32 ch0_txdesc_list_haddress; /* 0x1110 */
+ u32 ch0_txdesc_list_address; /* 0x1114 */
+ u32 ch0_rxdesc_list_haddress; /* 0x1118 */
+ u32 ch0_rxdesc_list_address; /* 0x111c */
+ u32 ch0_txdesc_tail_pointer; /* 0x1120 */
+ u32 unused_1124; /* 0x1124 */
+ u32 ch0_rxdesc_tail_pointer; /* 0x1128 */
+ u32 ch0_txdesc_ring_length; /* 0x112c */
+ u32 ch0_rxdesc_ring_length; /* 0x1130 */
+};
+
+#define EQOS_DMA_MODE_SWR BIT(0)
+
+#define EQOS_DMA_SYSBUS_MODE_RD_OSR_LMT_SHIFT 16
+#define EQOS_DMA_SYSBUS_MODE_RD_OSR_LMT_MASK 0xf
+#define EQOS_DMA_SYSBUS_MODE_EAME BIT(11)
+#define EQOS_DMA_SYSBUS_MODE_BLEN16 BIT(3)
+#define EQOS_DMA_SYSBUS_MODE_BLEN8 BIT(2)
+#define EQOS_DMA_SYSBUS_MODE_BLEN4 BIT(1)
+
+#define EQOS_DMA_CH0_CONTROL_PBLX8 BIT(16)
+
+#define EQOS_DMA_CH0_TX_CONTROL_TXPBL_SHIFT 16
+#define EQOS_DMA_CH0_TX_CONTROL_TXPBL_MASK 0x3f
+#define EQOS_DMA_CH0_TX_CONTROL_OSP BIT(4)
+#define EQOS_DMA_CH0_TX_CONTROL_ST BIT(0)
+
+#define EQOS_DMA_CH0_RX_CONTROL_RXPBL_SHIFT 16
+#define EQOS_DMA_CH0_RX_CONTROL_RXPBL_MASK 0x3f
+#define EQOS_DMA_CH0_RX_CONTROL_RBSZ_SHIFT 1
+#define EQOS_DMA_CH0_RX_CONTROL_RBSZ_MASK 0x3fff
+#define EQOS_DMA_CH0_RX_CONTROL_SR BIT(0)
+
+/* Descriptors */
+
+#define EQOS_DESCRIPTOR_WORDS 4
+#define EQOS_DESCRIPTOR_SIZE (EQOS_DESCRIPTOR_WORDS * 4)
+/* We assume ARCH_DMA_MINALIGN >= 16; 16 is the EQOS HW minimum */
+#define EQOS_DESCRIPTOR_ALIGN 64
+#define EQOS_DESCRIPTORS_TX 4
+#define EQOS_DESCRIPTORS_RX 4
+#define EQOS_DESCRIPTORS_NUM (EQOS_DESCRIPTORS_TX + EQOS_DESCRIPTORS_RX)
+#define EQOS_DESCRIPTORS_SIZE ALIGN(EQOS_DESCRIPTORS_NUM * \
+ EQOS_DESCRIPTOR_SIZE, EQOS_DESCRIPTOR_ALIGN)
+#define EQOS_BUFFER_ALIGN EQOS_DESCRIPTOR_ALIGN
+#define EQOS_MAX_PACKET_SIZE ALIGN(1568, EQOS_DESCRIPTOR_ALIGN)
+
+struct eqos_desc {
+ u32 des0; /* PA of buffer 1 or TSO header */
+ u32 des1; /* PA of buffer 2 with descriptor rings */
+ u32 des2; /* Length, VLAN, Timestamps, Interrupts */
+ u32 des3; /* All other flags */
+};
+
+#define EQOS_DESC3_OWN BIT(31)
+#define EQOS_DESC3_FD BIT(29)
+#define EQOS_DESC3_LD BIT(28)
+#define EQOS_DESC3_BUF1V BIT(24)
+
+#define EQOS_MDIO_ADDR(reg) ((addr << 21) & GENMASK(25, 21))
+#define EQOS_MDIO_REG(reg) ((reg << 16) & GENMASK(20, 16))
+#define EQOS_MDIO_CLK_CSR(clk_csr) ((clk_csr << 8) & GENMASK(11, 8))
+
+#define MII_BUSY (1 << 0)
+
+static int eqos_mdio_wait_idle(struct eqos *eqos)
+{
+ u32 idle;
+ return readl_poll_timeout(&eqos->mac_regs->mdio_address, idle,
+ !(idle & MII_BUSY), 10 * USEC_PER_MSEC);
+}
+
+static int eqos_mdio_read(struct mii_bus *bus, int addr, int reg)
+{
+ struct eqos *eqos = bus->priv;
+ u32 miiaddr;
+ int ret;
+
+ ret = eqos_mdio_wait_idle(eqos);
+ if (ret) {
+ eqos_err(eqos, "MDIO not idle at entry\n");
+ return ret;
+ }
+
+ miiaddr = readl(&eqos->mac_regs->mdio_address);
+ miiaddr &= EQOS_MDIO_ADDR_SKAP | EQOS_MDIO_ADDR_C45E;
+ miiaddr |= EQOS_MDIO_ADDR_GOC_READ << EQOS_MDIO_ADDR_GOC_SHIFT;
+
+ miiaddr |= EQOS_MDIO_CLK_CSR(eqos->ops->clk_csr);
+ miiaddr |= EQOS_MDIO_ADDR(addr) | EQOS_MDIO_REG(reg);
+ miiaddr |= MII_BUSY;
+
+ writel(miiaddr, &eqos->mac_regs->mdio_address);
+
+ udelay(eqos->ops->mdio_wait_us);
+
+ ret = eqos_mdio_wait_idle(eqos);
+ if (ret) {
+ eqos_err(eqos, "MDIO read didn't complete\n");
+ return ret;
+ }
+
+ return readl(&eqos->mac_regs->mdio_data) & 0xffff;
+}
+
+static int eqos_mdio_write(struct mii_bus *bus, int addr, int reg, u16 val)
+{
+ struct eqos *eqos = bus->priv;
+ u32 miiaddr = 0;
+ int ret;
+
+ ret = eqos_mdio_wait_idle(eqos);
+ if (ret) {
+ eqos_err(eqos, "MDIO not idle at entry\n");
+ return ret;
+ }
+
+ miiaddr = readl(&eqos->mac_regs->mdio_address);
+ miiaddr &= EQOS_MDIO_ADDR_SKAP | EQOS_MDIO_ADDR_C45E;
+ miiaddr |= EQOS_MDIO_ADDR_GOC_WRITE << EQOS_MDIO_ADDR_GOC_SHIFT;
+
+ miiaddr |= EQOS_MDIO_CLK_CSR(eqos->ops->clk_csr);
+ miiaddr |= EQOS_MDIO_ADDR(addr) | EQOS_MDIO_REG(reg);
+ miiaddr |= MII_BUSY;
+
+ writel(val, &eqos->mac_regs->mdio_data);
+ writel(addr, &eqos->mac_regs->mdio_address);
+
+ udelay(eqos->ops->mdio_wait_us);
+
+ ret = eqos_mdio_wait_idle(eqos);
+ if (ret) {
+ eqos_err(eqos, "MDIO read didn't complete\n");
+ return ret;
+ }
+
+ /* Needed as a fix for ST-Phy */
+ eqos_mdio_read(bus, addr, reg);
+ return 0;
+}
+
+
+static inline void eqos_set_full_duplex(struct eqos *eqos)
+{
+ setbits_le32(&eqos->mac_regs->config, EQOS_MAC_CONFIGURATION_DM);
+}
+
+static inline void eqos_set_half_duplex(struct eqos *eqos)
+{
+ clrbits_le32(&eqos->mac_regs->config, EQOS_MAC_CONFIGURATION_DM);
+
+ /* WAR: Flush TX queue when switching to half-duplex */
+ setbits_le32(&eqos->mtl_regs->txq0_operation_mode,
+ EQOS_MTL_TXQ0_OPERATION_MODE_FTQ);
+}
+
+static inline void eqos_set_gmii_speed(struct eqos *eqos)
+{
+ clrbits_le32(&eqos->mac_regs->config,
+ EQOS_MAC_CONFIGURATION_PS | EQOS_MAC_CONFIGURATION_FES);
+}
+
+static inline void eqos_set_mii_speed_100(struct eqos *eqos)
+{
+ setbits_le32(&eqos->mac_regs->config,
+ EQOS_MAC_CONFIGURATION_PS | EQOS_MAC_CONFIGURATION_FES);
+}
+
+static inline void eqos_set_mii_speed_10(struct eqos *eqos)
+{
+ clrsetbits_le32(&eqos->mac_regs->config,
+ EQOS_MAC_CONFIGURATION_FES, EQOS_MAC_CONFIGURATION_PS);
+}
+
+void eqos_adjust_link(struct eth_device *edev)
+{
+ struct eqos *eqos = edev->priv;
+ unsigned speed = edev->phydev->speed;
+
+ if (edev->phydev->duplex)
+ eqos_set_full_duplex(eqos);
+ else
+ eqos_set_half_duplex(eqos);
+
+ switch (speed) {
+ case SPEED_1000:
+ eqos_set_gmii_speed(eqos);
+ break;
+ case SPEED_100:
+ eqos_set_mii_speed_100(eqos);
+ break;
+ case SPEED_10:
+ eqos_set_mii_speed_10(eqos);
+ break;
+ default:
+ eqos_warn(eqos, "invalid speed %d\n", speed);
+ return;
+ }
+}
+
+int eqos_get_ethaddr(struct eth_device *edev, unsigned char *mac)
+{
+ return -EOPNOTSUPP;
+}
+
+int eqos_set_ethaddr(struct eth_device *edev, const unsigned char *mac)
+{
+ struct eqos *eqos = edev->priv;
+ __le32 mac_hi, mac_lo;
+
+ memcpy(eqos->macaddr, mac, ETH_ALEN);
+
+ /* Update the MAC address */
+ memcpy(&mac_hi, &mac[4], 2);
+ memcpy(&mac_lo, &mac[0], 4);
+
+ __raw_writel(mac_hi, &eqos->mac_regs->macaddr0hi);
+ __raw_writel(mac_lo, &eqos->mac_regs->macaddr0lo);
+
+ return 0;
+}
+
+/* Get PHY out of power saving mode. If this is needed elsewhere then
+ * consider making it part of phy-core and adding a resume method to
+ * the phy device ops. */
+static int phy_resume(struct phy_device *phydev)
+{
+ int bmcr;
+
+ bmcr = phy_read(phydev, MII_BMCR);
+ if (bmcr < 0)
+ return bmcr;
+
+ if (bmcr & BMCR_PDOWN) {
+ bmcr &= ~BMCR_PDOWN;
+ return phy_write(phydev, MII_BMCR, bmcr);
+ }
+
+ return 0;
+}
+
+int eqos_start(struct eth_device *edev)
+{
+ struct eqos *eqos = edev->priv;
+ u32 val, tx_fifo_sz, rx_fifo_sz, tqs, rqs, pbl;
+ unsigned long last_rx_desc;
+ unsigned long rate;
+ u32 mode_set;
+ int ret;
+ int i;
+
+ setbits_le32(&eqos->dma_regs->mode, EQOS_DMA_MODE_SWR);
+
+ ret = readl_poll_timeout(&eqos->dma_regs->mode, mode_set,
+ !(mode_set & EQOS_DMA_MODE_SWR),
+ 100 * USEC_PER_MSEC);
+ if (ret) {
+ eqos_err(eqos, "EQOS_DMA_MODE_SWR stuck: 0x%08x\n", mode_set);
+ return ret;
+ }
+
+ /* Reset above clears MAC address */
+ eqos_set_ethaddr(edev, eqos->macaddr);
+
+ /* Required for accurate time keeping with EEE counters */
+ rate = eqos->ops->get_csr_clk_rate(eqos);
+
+ val = (rate / USEC_PER_SEC) - 1; /* -1 because the data sheet says so */
+ writel(val, &eqos->mac_regs->us_tic_counter);
+
+ ret = phy_device_connect(edev, &eqos->miibus, eqos->phy_addr,
+ eqos->ops->adjust_link, 0, eqos->interface);
+ if (ret)
+ return ret;
+
+ /* Before we reset the mac, we must insure the PHY is not powered down
+ * as the dw controller needs all clock domains to be running, including
+ * the PHY clock, to come out of a mac reset. */
+ ret = phy_resume(edev->phydev);
+ if (ret)
+ return ret;
+
+ /* Configure MTL */
+
+ /* Enable Store and Forward mode for TX */
+ /* Program Tx operating mode */
+ setbits_le32(&eqos->mtl_regs->txq0_operation_mode,
+ EQOS_MTL_TXQ0_OPERATION_MODE_TSF |
+ (EQOS_MTL_TXQ0_OPERATION_MODE_TXQEN_ENABLED <<
+ EQOS_MTL_TXQ0_OPERATION_MODE_TXQEN_SHIFT));
+
+ /* Transmit Queue weight */
+ writel(0x10, &eqos->mtl_regs->txq0_quantum_weight);
+
+ /* Enable Store and Forward mode for RX, since no jumbo frame */
+ setbits_le32(&eqos->mtl_regs->rxq0_operation_mode,
+ EQOS_MTL_RXQ0_OPERATION_MODE_RSF);
+
+ /* Transmit/Receive queue fifo size; use all RAM for 1 queue */
+ val = readl(&eqos->mac_regs->hw_feature1);
+ tx_fifo_sz = (val >> EQOS_MAC_HW_FEATURE1_TXFIFOSIZE_SHIFT) &
+ EQOS_MAC_HW_FEATURE1_TXFIFOSIZE_MASK;
+ rx_fifo_sz = (val >> EQOS_MAC_HW_FEATURE1_RXFIFOSIZE_SHIFT) &
+ EQOS_MAC_HW_FEATURE1_RXFIFOSIZE_MASK;
+
+ /*
+ * r/tx_fifo_sz is encoded as log2(n / 128). Undo that by shifting.
+ * r/tqs is encoded as (n / 256) - 1.
+ */
+ tqs = (128 << tx_fifo_sz) / 256 - 1;
+ rqs = (128 << rx_fifo_sz) / 256 - 1;
+
+ clrsetbits_le32(&eqos->mtl_regs->txq0_operation_mode,
+ EQOS_MTL_TXQ0_OPERATION_MODE_TQS_MASK <<
+ EQOS_MTL_TXQ0_OPERATION_MODE_TQS_SHIFT,
+ tqs << EQOS_MTL_TXQ0_OPERATION_MODE_TQS_SHIFT);
+
+ clrsetbits_le32(&eqos->mtl_regs->rxq0_operation_mode,
+ EQOS_MTL_RXQ0_OPERATION_MODE_RQS_MASK <<
+ EQOS_MTL_RXQ0_OPERATION_MODE_RQS_SHIFT,
+ rqs << EQOS_MTL_RXQ0_OPERATION_MODE_RQS_SHIFT);
+
+ /* Flow control used only if each channel gets 4KB or more FIFO */
+ if (rqs >= ((SZ_4K / 256) - 1)) {
+ u32 rfd, rfa;
+
+ setbits_le32(&eqos->mtl_regs->rxq0_operation_mode,
+ EQOS_MTL_RXQ0_OPERATION_MODE_EHFC);
+
+ /*
+ * Set Threshold for Activating Flow Contol space for min 2
+ * frames ie, (1500 * 1) = 1500 bytes.
+ *
+ * Set Threshold for Deactivating Flow Contol for space of
+ * min 1 frame (frame size 1500bytes) in receive fifo
+ */
+ if (rqs == ((SZ_4K / 256) - 1)) {
+ /*
+ * This violates the above formula because of FIFO size
+ * limit therefore overflow may occur inspite of this.
+ */
+ rfd = 0x3; /* Full-3K */
+ rfa = 0x1; /* Full-1.5K */
+ } else if (rqs == ((SZ_8K / 256) - 1)) {
+ rfd = 0x6; /* Full-4K */
+ rfa = 0xa; /* Full-6K */
+ } else if (rqs == ((16384 / 256) - 1)) {
+ rfd = 0x6; /* Full-4K */
+ rfa = 0x12; /* Full-10K */
+ } else {
+ rfd = 0x6; /* Full-4K */
+ rfa = 0x1E; /* Full-16K */
+ }
+
+ clrsetbits_le32(&eqos->mtl_regs->rxq0_operation_mode,
+ (EQOS_MTL_RXQ0_OPERATION_MODE_RFD_MASK <<
+ EQOS_MTL_RXQ0_OPERATION_MODE_RFD_SHIFT) |
+ (EQOS_MTL_RXQ0_OPERATION_MODE_RFA_MASK <<
+ EQOS_MTL_RXQ0_OPERATION_MODE_RFA_SHIFT),
+ (rfd <<
+ EQOS_MTL_RXQ0_OPERATION_MODE_RFD_SHIFT) |
+ (rfa <<
+ EQOS_MTL_RXQ0_OPERATION_MODE_RFA_SHIFT));
+ }
+
+ /* Configure MAC */
+
+ clrsetbits_le32(&eqos->mac_regs->rxq_ctrl0,
+ EQOS_MAC_RXQ_CTRL0_RXQ0EN_MASK <<
+ EQOS_MAC_RXQ_CTRL0_RXQ0EN_SHIFT,
+ eqos->ops->config_mac <<
+ EQOS_MAC_RXQ_CTRL0_RXQ0EN_SHIFT);
+
+ /* Set TX flow control parameters */
+ /* Set Pause Time */
+ setbits_le32(&eqos->mac_regs->q0_tx_flow_ctrl,
+ 0xffff << EQOS_MAC_Q0_TX_FLOW_CTRL_PT_SHIFT);
+ /* Assign priority for TX flow control */
+ clrbits_le32(&eqos->mac_regs->txq_prty_map0,
+ EQOS_MAC_TXQ_PRTY_MAP0_PSTQ0_MASK <<
+ EQOS_MAC_TXQ_PRTY_MAP0_PSTQ0_SHIFT);
+ /* Assign priority for RX flow control */
+ clrbits_le32(&eqos->mac_regs->rxq_ctrl2,
+ EQOS_MAC_RXQ_CTRL2_PSRQ0_MASK <<
+ EQOS_MAC_RXQ_CTRL2_PSRQ0_SHIFT);
+ /* Enable flow control */
+ setbits_le32(&eqos->mac_regs->q0_tx_flow_ctrl,
+ EQOS_MAC_Q0_TX_FLOW_CTRL_TFE);
+ setbits_le32(&eqos->mac_regs->rx_flow_ctrl,
+ EQOS_MAC_RX_FLOW_CTRL_RFE);
+
+ clrsetbits_le32(&eqos->mac_regs->config,
+ EQOS_MAC_CONFIGURATION_GPSLCE |
+ EQOS_MAC_CONFIGURATION_WD |
+ EQOS_MAC_CONFIGURATION_JD |
+ EQOS_MAC_CONFIGURATION_JE,
+ EQOS_MAC_CONFIGURATION_CST |
+ EQOS_MAC_CONFIGURATION_ACS);
+
+ /* Configure DMA */
+
+ /* Enable OSP mode */
+ setbits_le32(&eqos->dma_regs->ch0_tx_control,
+ EQOS_DMA_CH0_TX_CONTROL_OSP);
+
+ /* RX buffer size. Must be a multiple of bus width */
+ clrsetbits_le32(&eqos->dma_regs->ch0_rx_control,
+ EQOS_DMA_CH0_RX_CONTROL_RBSZ_MASK <<
+ EQOS_DMA_CH0_RX_CONTROL_RBSZ_SHIFT,
+ EQOS_MAX_PACKET_SIZE <<
+ EQOS_DMA_CH0_RX_CONTROL_RBSZ_SHIFT);
+
+ setbits_le32(&eqos->dma_regs->ch0_control,
+ EQOS_DMA_CH0_CONTROL_PBLX8);
+
+ /*
+ * Burst length must be < 1/2 FIFO size.
+ * FIFO size in tqs is encoded as (n / 256) - 1.
+ * Each burst is n * 8 (PBLX8) * 16 (AXI width) == 128 bytes.
+ * Half of n * 256 is n * 128, so pbl == tqs, modulo the -1.
+ */
+ pbl = tqs + 1;
+ if (pbl > 32)
+ pbl = 32;
+ clrsetbits_le32(&eqos->dma_regs->ch0_tx_control,
+ EQOS_DMA_CH0_TX_CONTROL_TXPBL_MASK <<
+ EQOS_DMA_CH0_TX_CONTROL_TXPBL_SHIFT,
+ pbl << EQOS_DMA_CH0_TX_CONTROL_TXPBL_SHIFT);
+
+ clrsetbits_le32(&eqos->dma_regs->ch0_rx_control,
+ EQOS_DMA_CH0_RX_CONTROL_RXPBL_MASK <<
+ EQOS_DMA_CH0_RX_CONTROL_RXPBL_SHIFT,
+ 8 << EQOS_DMA_CH0_RX_CONTROL_RXPBL_SHIFT);
+
+ /* DMA performance configuration */
+ val = (2 << EQOS_DMA_SYSBUS_MODE_RD_OSR_LMT_SHIFT) |
+ EQOS_DMA_SYSBUS_MODE_EAME | EQOS_DMA_SYSBUS_MODE_BLEN16 |
+ EQOS_DMA_SYSBUS_MODE_BLEN8 | EQOS_DMA_SYSBUS_MODE_BLEN4;
+ writel(val, &eqos->dma_regs->sysbus_mode);
+
+ /* Set up descriptors */
+
+ eqos->tx_currdescnum = eqos->rx_currdescnum = 0;
+
+ for (i = 0; i < EQOS_DESCRIPTORS_RX; i++) {
+ struct eqos_desc *rx_desc = &eqos->rx_descs[i];
+
+ writel(EQOS_DESC3_BUF1V | EQOS_DESC3_OWN, &rx_desc->des3);
+ }
+
+ writel(0, &eqos->dma_regs->ch0_txdesc_list_haddress);
+ writel((ulong)eqos->tx_descs, &eqos->dma_regs->ch0_txdesc_list_address);
+ writel(EQOS_DESCRIPTORS_TX - 1,
+ &eqos->dma_regs->ch0_txdesc_ring_length);
+
+ writel(0, &eqos->dma_regs->ch0_rxdesc_list_haddress);
+ writel((ulong)eqos->rx_descs, &eqos->dma_regs->ch0_rxdesc_list_address);
+ writel(EQOS_DESCRIPTORS_RX - 1,
+ &eqos->dma_regs->ch0_rxdesc_ring_length);
+
+ /* Enable everything */
+
+ setbits_le32(&eqos->mac_regs->config,
+ EQOS_MAC_CONFIGURATION_TE | EQOS_MAC_CONFIGURATION_RE);
+
+ setbits_le32(&eqos->dma_regs->ch0_tx_control,
+ EQOS_DMA_CH0_TX_CONTROL_ST);
+ setbits_le32(&eqos->dma_regs->ch0_rx_control,
+ EQOS_DMA_CH0_RX_CONTROL_SR);
+
+ /* TX tail pointer not written until we need to TX a packet */
+ /*
+ * Point RX tail pointer at last descriptor. Ideally, we'd point at the
+ * first descriptor, implying all descriptors were available. However,
+ * that's not distinguishable from none of the descriptors being
+ * available.
+ */
+ last_rx_desc = (ulong)&eqos->rx_descs[(EQOS_DESCRIPTORS_RX - 1)];
+ writel(last_rx_desc, &eqos->dma_regs->ch0_rxdesc_tail_pointer);
+
+ barrier();
+
+ eqos->started = true;
+
+ return 0;
+}
+
+void eqos_stop(struct eth_device *edev)
+{
+ struct eqos *eqos = edev->priv;
+ int i;
+
+ if (!eqos->started)
+ return;
+
+ eqos->started = false;
+
+ barrier();
+
+ /* Disable TX DMA */
+ clrbits_le32(&eqos->dma_regs->ch0_tx_control,
+ EQOS_DMA_CH0_TX_CONTROL_ST);
+
+ /* Wait for TX all packets to drain out of MTL */
+ for (i = 0; i < 1000000; i++) {
+ u32 val = readl(&eqos->mtl_regs->txq0_debug);
+ u32 trcsts = (val >> EQOS_MTL_TXQ0_DEBUG_TRCSTS_SHIFT) &
+ EQOS_MTL_TXQ0_DEBUG_TRCSTS_MASK;
+ u32 txqsts = val & EQOS_MTL_TXQ0_DEBUG_TXQSTS;
+ if ((trcsts != 1) && (!txqsts))
+ break;
+ }
+
+ /* Turn off MAC TX and RX */
+ clrbits_le32(&eqos->mac_regs->config,
+ EQOS_MAC_CONFIGURATION_TE | EQOS_MAC_CONFIGURATION_RE);
+
+ /* Wait for all RX packets to drain out of MTL */
+ for (i = 0; i < 1000000; i++) {
+ u32 val = readl(&eqos->mtl_regs->rxq0_debug);
+ u32 prxq = (val >> EQOS_MTL_RXQ0_DEBUG_PRXQ_SHIFT) &
+ EQOS_MTL_RXQ0_DEBUG_PRXQ_MASK;
+ u32 rxqsts = (val >> EQOS_MTL_RXQ0_DEBUG_RXQSTS_SHIFT) &
+ EQOS_MTL_RXQ0_DEBUG_RXQSTS_MASK;
+ if ((!prxq) && (!rxqsts))
+ break;
+ }
+
+ /* Turn off RX DMA */
+ clrbits_le32(&eqos->dma_regs->ch0_rx_control,
+ EQOS_DMA_CH0_RX_CONTROL_SR);
+}
+
+static int eqos_send(struct eth_device *edev, void *packet, int length)
+{
+ struct eqos *eqos = edev->priv;
+ struct device_d *dev = &eqos->netdev.dev;
+ struct eqos_desc *tx_desc;
+ dma_addr_t dma;
+ u32 des3;
+ int ret;
+
+ tx_desc = &eqos->tx_descs[eqos->tx_currdescnum];
+ eqos->tx_currdescnum++;
+ eqos->tx_currdescnum %= EQOS_DESCRIPTORS_TX;
+
+ dma = dma_map_single(dev, packet, length, DMA_TO_DEVICE);
+ if (dma_mapping_error(dev, dma))
+ return -EFAULT;
+
+ tx_desc->des0 = (unsigned long)dma;
+ tx_desc->des1 = 0;
+ tx_desc->des2 = length;
+ /*
+ * Make sure the compiler doesn't reorder the _OWN write below, before
+ * the writes to the rest of the descriptor.
+ */
+ barrier();
+
+ writel(EQOS_DESC3_OWN | EQOS_DESC3_FD | EQOS_DESC3_LD | length, &tx_desc->des3);
+ writel((ulong)(tx_desc + 1), &eqos->dma_regs->ch0_txdesc_tail_pointer);
+
+ ret = readl_poll_timeout(&tx_desc->des3, des3,
+ !(des3 & EQOS_DESC3_OWN),
+ 100 * USEC_PER_MSEC);
+
+ dma_unmap_single(dev, dma, length, DMA_TO_DEVICE);
+
+ if (ret == -ETIMEDOUT)
+ eqos_dbg(eqos, "TX timeout\n");
+
+ return ret;
+}
+
+static int eqos_recv(struct eth_device *edev)
+{
+ struct eqos *eqos = edev->priv;
+ struct eqos_desc *rx_desc;
+ void *frame;
+ int length;
+
+ rx_desc = &eqos->rx_descs[eqos->rx_currdescnum];
+ if (readl(&rx_desc->des3) & EQOS_DESC3_OWN)
+ return 0;
+
+ frame = phys_to_virt(rx_desc->des0);
+ length = rx_desc->des3 & 0x7fff;
+
+ dma_sync_single_for_cpu((unsigned long)frame, length, DMA_FROM_DEVICE);
+ net_receive(edev, frame, length);
+ dma_sync_single_for_device((unsigned long)frame, length, DMA_FROM_DEVICE);
+
+ rx_desc->des0 = (unsigned long)frame;
+ rx_desc->des1 = 0;
+ rx_desc->des2 = 0;
+ /*
+ * Make sure that if HW sees the _OWN write below, it will see all the
+ * writes to the rest of the descriptor too.
+ */
+ rx_desc->des3 |= EQOS_DESC3_BUF1V;
+ rx_desc->des3 |= EQOS_DESC3_OWN;
+ barrier();
+
+ writel((ulong)rx_desc, &eqos->dma_regs->ch0_rxdesc_tail_pointer);
+
+ eqos->rx_currdescnum++;
+ eqos->rx_currdescnum %= EQOS_DESCRIPTORS_RX;
+
+ return 0;
+}
+
+static int eqos_init_resources(struct eqos *eqos)
+{
+ struct device_d *dev = eqos->netdev.parent;
+ int ret = -ENOMEM;
+ void *descs;
+ void *p;
+ int i;
+
+ descs = dma_alloc_coherent(EQOS_DESCRIPTORS_SIZE, DMA_ADDRESS_BROKEN);
+ if (!descs)
+ goto err;
+
+ eqos->tx_descs = (struct eqos_desc *)descs;
+ eqos->rx_descs = (eqos->tx_descs + EQOS_DESCRIPTORS_TX);
+
+ p = dma_alloc(EQOS_DESCRIPTORS_RX * EQOS_MAX_PACKET_SIZE);
+ if (!p)
+ goto err_free_desc;
+
+ for (i = 0; i < EQOS_DESCRIPTORS_RX; i++) {
+ struct eqos_desc *rx_desc = &eqos->rx_descs[i];
+ dma_addr_t dma;
+
+ dma = dma_map_single(dev, p, EQOS_MAX_PACKET_SIZE, DMA_FROM_DEVICE);
+ if (dma_mapping_error(dev, dma)) {
+ ret = -EFAULT;
+ goto err_free_rx_bufs;
+ }
+
+ rx_desc->des0 = dma;
+
+ p += EQOS_MAX_PACKET_SIZE;
+ }
+
+ return 0;
+
+err_free_rx_bufs:
+ dma_free(phys_to_virt(eqos->rx_descs[0].des0));
+err_free_desc:
+ dma_free_coherent(descs, 0, EQOS_DESCRIPTORS_SIZE);
+err:
+
+ return ret;
+}
+
+static int eqos_init(struct device_d *dev, struct eqos *eqos)
+{
+ int ret;
+
+ ret = eqos_init_resources(eqos);
+ if (ret) {
+ dev_err(dev, "eqos_init_resources() failed: %s\n", strerror(-ret));
+ return ret;
+ }
+
+ if (eqos->ops->init)
+ ret = eqos->ops->init(dev, eqos);
+
+ return ret;
+}
+
+static void eqos_probe_dt(struct device_d *dev, struct eqos *eqos)
+{
+ struct device_node *child;
+
+ eqos->interface = of_get_phy_mode(dev->device_node);
+ eqos->phy_addr = -1;
+
+ /* Set MDIO bus device node, if present. */
+ for_each_child_of_node(dev->device_node, child) {
+ if (of_device_is_compatible(child, "snps,dwmac-mdio") ||
+ (child->name && !of_node_cmp(child->name, "mdio"))) {
+ eqos->miibus.dev.device_node = child;
+ break;
+ }
+ }
+}
+
+int eqos_probe(struct device_d *dev, const struct eqos_ops *ops, void *priv)
+{
+ struct mii_bus *miibus;
+ struct resource *iores;
+ struct eqos *eqos;
+ struct eth_device *edev;
+ int ret;
+
+ eqos = xzalloc(sizeof(*eqos));
+
+ iores = dev_request_mem_resource(dev, 0);
+ if (IS_ERR(iores))
+ return PTR_ERR(iores);
+ eqos->regs = IOMEM(iores->start);
+
+ eqos->mac_regs = eqos->regs + EQOS_MAC_REGS_BASE;
+ eqos->mtl_regs = eqos->regs + EQOS_MTL_REGS_BASE;
+ eqos->dma_regs = eqos->regs + EQOS_DMA_REGS_BASE;
+ eqos->ops = ops;
+ eqos->priv = priv;
+
+ eqos_probe_dt(dev, eqos);
+
+ edev = &eqos->netdev;
+
+ dev->priv = edev->priv = eqos;
+
+ edev->parent = dev;
+ edev->open = ops->start;
+ edev->send = eqos_send;
+ edev->recv = eqos_recv;
+ edev->halt = ops->stop;
+ edev->get_ethaddr = ops->get_ethaddr;
+ edev->set_ethaddr = ops->set_ethaddr;
+
+ miibus = &eqos->miibus;
+ miibus->parent = edev->parent;
+ miibus->read = eqos_mdio_read;
+ miibus->write = eqos_mdio_write;
+ miibus->priv = eqos;
+
+ ret = eqos_init(dev, eqos);
+ if (ret)
+ return ret;
+
+ ret = mdiobus_register(miibus);
+ if (ret)
+ return ret;
+
+ return eth_register(edev);
+}
+
+void eqos_remove(struct device_d *dev)
+{
+ struct eqos *eqos = dev->priv;
+
+ mdiobus_unregister(&eqos->miibus);
+
+ dma_free(phys_to_virt(eqos->rx_descs[0].des0));
+ dma_free_coherent(eqos->tx_descs, 0, EQOS_DESCRIPTORS_SIZE);
+}
diff --git a/drivers/net/designware_eqos.h b/drivers/net/designware_eqos.h
new file mode 100644
index 0000000000..969a524c0a
--- /dev/null
+++ b/drivers/net/designware_eqos.h
@@ -0,0 +1,84 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (c) 2019 Ahmad Fatoum, Pengutronix
+ */
+
+#ifndef __EQOS_H_
+#define __EQOS_H_
+
+struct eqos;
+struct eth_device;
+
+struct eqos_ops {
+ int (*init)(struct device_d *dev, struct eqos *priv);
+ int (*start)(struct eth_device *edev);
+ void (*stop)(struct eth_device *edev);
+ int (*get_ethaddr)(struct eth_device *dev, unsigned char *mac);
+ int (*set_ethaddr)(struct eth_device *edev, const unsigned char *mac);
+ void (*adjust_link)(struct eth_device *edev);
+ unsigned long (*get_csr_clk_rate)(struct eqos *);
+
+ bool enh_desc;
+ int mdio_wait_us;
+
+#define EQOS_MAC_RXQ_CTRL0_RXQ0EN_SHIFT 0
+#define EQOS_MAC_RXQ_CTRL0_RXQ0EN_MASK 3
+#define EQOS_MAC_RXQ_CTRL0_RXQ0EN_NOT_ENABLED 0
+#define EQOS_MAC_RXQ_CTRL0_RXQ0EN_ENABLED_DCB 2
+#define EQOS_MAC_RXQ_CTRL0_RXQ0EN_ENABLED_AV 1
+ unsigned clk_csr;
+
+#define EQOS_MDIO_ADDR_CR_20_35 2
+#define EQOS_MDIO_ADDR_CR_250_300 5
+#define EQOS_MDIO_ADDR_SKAP BIT(4)
+#define EQOS_MDIO_ADDR_GOC_SHIFT 2
+#define EQOS_MDIO_ADDR_GOC_READ 3
+#define EQOS_MDIO_ADDR_GOC_WRITE 1
+#define EQOS_MDIO_ADDR_C45E BIT(1)
+ unsigned config_mac;
+};
+
+struct eqos_desc;
+struct eqos_dma_regs;
+struct eqos_mac_regs;
+struct eqos_mtl_regs;
+
+struct eqos {
+ struct eth_device netdev;
+ struct mii_bus miibus;
+
+ u8 macaddr[6];
+
+ u32 tx_currdescnum, rx_currdescnum;
+
+ struct eqos_desc *tx_descs, *rx_descs;
+
+ void __iomem *regs;
+ struct eqos_mac_regs __iomem *mac_regs;
+ struct eqos_dma_regs __iomem *dma_regs;
+ struct eqos_mtl_regs __iomem *mtl_regs;
+
+ int phy_addr;
+ phy_interface_t interface;
+
+ const struct eqos_ops *ops;
+ void *priv;
+ bool started;
+};
+
+struct device_d;
+int eqos_probe(struct device_d *dev, const struct eqos_ops *ops, void *priv);
+void eqos_remove(struct device_d *dev);
+int eqos_reset(struct eqos *priv);
+
+int eqos_get_ethaddr(struct eth_device *edev, unsigned char *mac);
+int eqos_set_ethaddr(struct eth_device *edev, const unsigned char *mac);
+int eqos_start(struct eth_device *edev);
+void eqos_stop(struct eth_device *edev);
+void eqos_adjust_link(struct eth_device *edev);
+
+#define eqos_dbg(eqos, ...) dev_dbg(&eqos->netdev.dev, __VA_ARGS__)
+#define eqos_warn(eqos, ...) dev_warn(&eqos->netdev.dev, __VA_ARGS__)
+#define eqos_err(eqos, ...) dev_err(&eqos->netdev.dev, __VA_ARGS__)
+
+#endif
diff --git a/drivers/net/designware_socfpga.c b/drivers/net/designware_socfpga.c
index 77157c2b51..ce3ac38ebe 100644
--- a/drivers/net/designware_socfpga.c
+++ b/drivers/net/designware_socfpga.c
@@ -14,11 +14,27 @@
#include <net.h>
#include <of_net.h>
#include <linux/reset.h>
-#include <mach/cyclone5-system-manager.h>
#include <mfd/syscon.h>
#include "designware.h"
-#define SYSMGR_EMACGRP_CTRL_PTP_REF_CLK_MASK 0x00000010
+#define SYSMGR_EMACGRP_CTRL_PHYSEL_ENUM_GMII_MII 0x0
+#define SYSMGR_EMACGRP_CTRL_PHYSEL_ENUM_RGMII 0x1
+#define SYSMGR_EMACGRP_CTRL_PHYSEL_ENUM_RMII 0x2
+#define SYSMGR_EMACGRP_CTRL_PHYSEL0_LSB 0
+#define SYSMGR_EMACGRP_CTRL_PHYSEL1_LSB 2
+#define SYSMGR_EMACGRP_CTRL_PHYSEL_MASK 0x00000003
+#define SYSMGR_EMACGRP_CTRL_PTP_REF_CLK_MASK 0x00000010
+#define SYSMGR_GEN10_EMACGRP_CTRL_PTP_REF_CLK_MASK 0x00000100
+
+#define SYSMGR_FPGAGRP_MODULE 0x00000028
+#define SYSMGR_FPGAGRP_MODULE_EMAC 0x00000004
+#define SYSMGR_FPGAINTF_EMAC_REG 0x00000070
+#define SYSMGR_FPGAINTF_EMAC_BIT 0x1
+
+struct socfpga_dwc_dev;
+struct socfpga_dwmac_ops {
+ int (*set_phy_mode)(struct socfpga_dwc_dev *dwmac_priv);
+};
struct socfpga_dwc_dev {
struct dw_eth_dev *priv;
@@ -26,27 +42,36 @@ struct socfpga_dwc_dev {
u32 reg_shift;
void __iomem *sys_mgr_base;
bool f2h_ptp_ref_clk;
+ const struct socfpga_dwmac_ops *ops;
};
-static int socfpga_dwc_set_phy_mode(struct socfpga_dwc_dev *dwc_dev)
+static int socfpga_set_phy_mode_common(int phymode, u32 *val)
{
- struct dw_eth_dev *eth_dev = dwc_dev->priv;
- int phymode = eth_dev->interface;
- u32 reg_offset = dwc_dev->reg_offset;
- u32 reg_shift = dwc_dev->reg_shift;
- u32 ctrl, val;
-
switch (phymode) {
case PHY_INTERFACE_MODE_RGMII:
case PHY_INTERFACE_MODE_RGMII_ID:
- val = SYSMGR_EMACGRP_CTRL_PHYSEL_ENUM_RGMII;
+ *val = SYSMGR_EMACGRP_CTRL_PHYSEL_ENUM_RGMII;
break;
case PHY_INTERFACE_MODE_MII:
case PHY_INTERFACE_MODE_GMII:
case PHY_INTERFACE_MODE_SGMII:
- val = SYSMGR_EMACGRP_CTRL_PHYSEL_ENUM_GMII_MII;
+ *val = SYSMGR_EMACGRP_CTRL_PHYSEL_ENUM_GMII_MII;
break;
default:
+ return -EINVAL;
+ }
+ return 0;
+};
+
+static int socfpga_gen5_set_phy_mode(struct socfpga_dwc_dev *dwc_dev)
+{
+ struct dw_eth_dev *eth_dev = dwc_dev->priv;
+ int phymode = eth_dev->interface;
+ u32 reg_offset = dwc_dev->reg_offset;
+ u32 reg_shift = dwc_dev->reg_shift;
+ u32 ctrl, val;
+
+ if (socfpga_set_phy_mode_common(phymode, &val)) {
dev_err(&eth_dev->netdev.dev, "bad phy mode %d\n", phymode);
return -EINVAL;
}
@@ -85,6 +110,54 @@ static int socfpga_dwc_set_phy_mode(struct socfpga_dwc_dev *dwc_dev)
return 0;
}
+static int socfpga_gen10_set_phy_mode(struct socfpga_dwc_dev *dwc_dev)
+{
+ struct dw_eth_dev *eth_dev = dwc_dev->priv;
+ int phymode = eth_dev->interface;
+ u32 reg_offset = dwc_dev->reg_offset;
+ u32 reg_shift = dwc_dev->reg_shift;
+ u32 ctrl, val;
+
+ if (socfpga_set_phy_mode_common(phymode, &val)) {
+ dev_err(&eth_dev->netdev.dev, "bad phy mode %d\n", phymode);
+ return -EINVAL;
+ }
+
+ /* Assert reset to the enet controller before changing the phy mode */
+ if (eth_dev->rst)
+ reset_control_assert(eth_dev->rst);
+
+ ctrl = readl(dwc_dev->sys_mgr_base + reg_offset);
+ ctrl &= ~(SYSMGR_EMACGRP_CTRL_PHYSEL_MASK << reg_shift);
+ ctrl |= val << reg_shift;
+
+ if (dwc_dev->f2h_ptp_ref_clk ||
+ phymode == PHY_INTERFACE_MODE_MII ||
+ phymode == PHY_INTERFACE_MODE_GMII ||
+ phymode == PHY_INTERFACE_MODE_SGMII) {
+ u32 module;
+
+ ctrl |= SYSMGR_GEN10_EMACGRP_CTRL_PTP_REF_CLK_MASK;
+ module = readl(dwc_dev->sys_mgr_base + SYSMGR_FPGAINTF_EMAC_REG);
+ module |= (SYSMGR_FPGAINTF_EMAC_BIT << reg_shift);
+
+ writel(module, dwc_dev->sys_mgr_base + SYSMGR_FPGAINTF_EMAC_REG);
+ } else {
+ ctrl &= ~SYSMGR_GEN10_EMACGRP_CTRL_PTP_REF_CLK_MASK;
+ }
+
+ writel(ctrl, dwc_dev->sys_mgr_base + reg_offset);
+
+ /* Deassert reset for the phy configuration to be sampled by
+ * the enet controller, and operation to start in requested mode
+ */
+ if (eth_dev->rst)
+ reset_control_deassert(eth_dev->rst);
+
+ return 0;
+}
+
+
static int socfpga_dwc_probe_dt(struct device_d *dev, struct socfpga_dwc_dev *priv)
{
u32 reg_offset, reg_shift;
@@ -120,11 +193,21 @@ static int socfpga_dwc_ether_probe(struct device_d *dev)
{
struct socfpga_dwc_dev *dwc_dev;
struct dw_eth_dev *priv;
+ struct dw_eth_drvdata *drvdata;
int ret;
dwc_dev = xzalloc(sizeof(*dwc_dev));
- priv = dwc_drv_probe(dev);
+ ret = dev_get_drvdata(dev, (const void **)&drvdata);
+ if (ret)
+ return ret;
+
+ if (drvdata && drvdata->priv)
+ dwc_dev->ops = (struct socfpga_dwmac_ops *)drvdata->priv;
+ else
+ return -EINVAL;
+
+ priv = dwc_drv_probe(dev);
if (IS_ERR(priv))
return PTR_ERR(priv);
@@ -145,18 +228,36 @@ static int socfpga_dwc_ether_probe(struct device_d *dev)
if (ret)
return ret;
- return socfpga_dwc_set_phy_mode(dwc_dev);
+ return dwc_dev->ops->set_phy_mode(dwc_dev);
}
-static struct dw_eth_drvdata socfpga_stmmac_drvdata = {
+static struct socfpga_dwmac_ops socfpga_gen5_ops = {
+ .set_phy_mode = socfpga_gen5_set_phy_mode,
+};
+
+static const struct dw_eth_drvdata socfpga_gen5_drvdata = {
.enh_desc = 1,
+ .priv = &socfpga_gen5_ops,
+};
+
+static struct socfpga_dwmac_ops socfpga_gen10_ops = {
+ .set_phy_mode = socfpga_gen10_set_phy_mode,
+};
+static const struct dw_eth_drvdata socfpga_gen10_drvdata = {
+ .enh_desc = 1,
+ .priv = &socfpga_gen10_ops,
};
static __maybe_unused struct of_device_id socfpga_dwc_ether_compatible[] = {
{
.compatible = "altr,socfpga-stmmac",
- .data = &socfpga_stmmac_drvdata,
- }, {
+ .data = &socfpga_gen5_drvdata,
+ },
+ {
+ .compatible = "altr,socfpga-stmmac-a10-s10",
+ .data = &socfpga_gen10_drvdata,
+ },
+ {
/* sentinel */
}
};
diff --git a/drivers/net/designware_stm32.c b/drivers/net/designware_stm32.c
new file mode 100644
index 0000000000..5b087ad5a3
--- /dev/null
+++ b/drivers/net/designware_stm32.c
@@ -0,0 +1,245 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (c) 2016, NVIDIA CORPORATION.
+ * Copyright (c) 2019, Ahmad Fatoum, Pengutronix
+ *
+ * Portions based on U-Boot's rtl8169.c and dwc_eth_qos.
+ */
+
+#include <common.h>
+#include <init.h>
+#include <net.h>
+#include <linux/clk.h>
+#include <mfd/syscon.h>
+
+#include "designware_eqos.h"
+
+#define SYSCFG_PMCR_ETH_CLK_SEL BIT(16)
+#define SYSCFG_PMCR_ETH_REF_CLK_SEL BIT(17)
+
+/* Ethernet PHY interface selection in register SYSCFG Configuration
+ *------------------------------------------
+ * src |BIT(23)| BIT(22)| BIT(21)|BIT(20)|
+ *------------------------------------------
+ * MII | 0 | 0 | 0 | 1 |
+ *------------------------------------------
+ * GMII | 0 | 0 | 0 | 0 |
+ *------------------------------------------
+ * RGMII | 0 | 0 | 1 | n/a |
+ *------------------------------------------
+ * RMII | 1 | 0 | 0 | n/a |
+ *------------------------------------------
+ */
+#define SYSCFG_PMCR_ETH_SEL_MII BIT(20)
+#define SYSCFG_PMCR_ETH_SEL_RGMII BIT(21)
+#define SYSCFG_PMCR_ETH_SEL_RMII BIT(23)
+#define SYSCFG_PMCR_ETH_SEL_GMII 0
+#define SYSCFG_MCU_ETH_SEL_MII 0
+#define SYSCFG_MCU_ETH_SEL_RMII 1
+
+/* Descriptors */
+
+#define SYSCFG_MCU_ETH_MASK BIT(23)
+#define SYSCFG_MP1_ETH_MASK GENMASK(23, 16)
+#define SYSCFG_PMCCLRR_OFFSET 0x40
+
+struct eqos_stm32 {
+ struct clk_bulk_data *clks;
+ int num_clks;
+ struct regmap *regmap;
+ u32 mode_reg;
+ int eth_clk_sel_reg;
+ int eth_ref_clk_sel_reg;
+};
+
+static inline struct eqos_stm32 *to_stm32(struct eqos *eqos)
+{
+ return eqos->priv;
+}
+
+enum { CLK_STMMACETH, CLK_MAX_RX, CLK_MAX_TX, CLK_SYSCFG, };
+static const struct clk_bulk_data stm32_clks[] = {
+ [CLK_STMMACETH] = { .id = "stmmaceth" },
+ [CLK_MAX_RX] = { .id = "mac-clk-rx" },
+ [CLK_MAX_TX] = { .id = "mac-clk-tx" },
+ [CLK_SYSCFG] = { .id = "syscfg-clk" },
+};
+
+static unsigned long eqos_get_csr_clk_rate_stm32(struct eqos *eqos)
+{
+ return clk_get_rate(to_stm32(eqos)->clks[CLK_STMMACETH].clk);
+}
+
+static int eqos_set_mode_stm32(struct eqos_stm32 *priv, phy_interface_t interface)
+{
+ u32 val, reg = priv->mode_reg;
+ int ret;
+
+ switch (interface) {
+ case PHY_INTERFACE_MODE_MII:
+ val = SYSCFG_PMCR_ETH_SEL_MII;
+ break;
+ case PHY_INTERFACE_MODE_GMII:
+ val = SYSCFG_PMCR_ETH_SEL_GMII;
+ if (priv->eth_clk_sel_reg)
+ val |= SYSCFG_PMCR_ETH_CLK_SEL;
+ break;
+ case PHY_INTERFACE_MODE_RMII:
+ val = SYSCFG_PMCR_ETH_SEL_RMII;
+ if (priv->eth_ref_clk_sel_reg)
+ val |= SYSCFG_PMCR_ETH_REF_CLK_SEL;
+ break;
+ case PHY_INTERFACE_MODE_RGMII:
+ case PHY_INTERFACE_MODE_RGMII_ID:
+ case PHY_INTERFACE_MODE_RGMII_RXID:
+ case PHY_INTERFACE_MODE_RGMII_TXID:
+ val = SYSCFG_PMCR_ETH_SEL_RGMII;
+ if (priv->eth_clk_sel_reg)
+ val |= SYSCFG_PMCR_ETH_CLK_SEL;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ /* Need to update PMCCLRR (clear register) */
+ ret = regmap_write(priv->regmap, reg + SYSCFG_PMCCLRR_OFFSET,
+ SYSCFG_MP1_ETH_MASK);
+ if (ret)
+ return -EIO;
+
+ /* Update PMCSETR (set register) */
+ regmap_update_bits(priv->regmap, reg, GENMASK(23, 16), val);
+
+ return 0;
+}
+
+static int eqos_init_stm32(struct device_d *dev, struct eqos *eqos)
+{
+ struct device_node *np = dev->device_node;
+ struct eqos_stm32 *priv = to_stm32(eqos);
+ struct clk_bulk_data *eth_ck;
+ int ret;
+
+ /* Gigabit Ethernet 125MHz clock selection. */
+ priv->eth_clk_sel_reg = of_property_read_bool(np, "st,eth-clk-sel");
+
+ /* Ethernet 50Mhz RMII clock selection */
+ priv->eth_ref_clk_sel_reg =
+ of_property_read_bool(np, "st,eth-ref-clk-sel");
+
+ priv->regmap = syscon_regmap_lookup_by_phandle(dev->device_node,
+ "st,syscon");
+ if (IS_ERR(priv->regmap)) {
+ dev_err(dev, "Could not get st,syscon node\n");
+ return PTR_ERR(priv->regmap);
+ }
+
+ ret = of_property_read_u32_index(dev->device_node, "st,syscon",
+ 1, &priv->mode_reg);
+ if (ret) {
+ dev_err(dev, "Can't get sysconfig mode offset (%s)\n",
+ strerror(-ret));
+ return -EINVAL;
+ }
+
+ ret = eqos_set_mode_stm32(priv, eqos->interface);
+ if (ret)
+ dev_warn(dev, "Configuring syscfg failed: %s\n", strerror(-ret));
+
+ priv->num_clks = ARRAY_SIZE(stm32_clks) + 1;
+ priv->clks = xmalloc(priv->num_clks * sizeof(*priv->clks));
+ memcpy(priv->clks, stm32_clks, sizeof stm32_clks);
+
+ ret = clk_bulk_get(dev, ARRAY_SIZE(stm32_clks), priv->clks);
+ if (ret) {
+ dev_err(dev, "Failed to get clks: %s\n", strerror(-ret));
+ return ret;
+ }
+
+ eth_ck = &priv->clks[ARRAY_SIZE(stm32_clks)];
+ eth_ck->id = "eth-ck";
+ eth_ck->clk = clk_get(dev, eth_ck->id);
+ if (IS_ERR(eth_ck->clk)) {
+ priv->num_clks--;
+ dev_dbg(dev, "No phy clock provided. Continuing without.\n");
+ }
+
+ return 0;
+
+}
+
+static int eqos_start_stm32(struct eth_device *edev)
+{
+ struct eqos *eqos = edev->priv;
+ struct eqos_stm32 *priv = to_stm32(eqos);
+ int ret;
+
+ ret = clk_bulk_enable(priv->num_clks, priv->clks);
+ if (ret < 0) {
+ eqos_err(eqos, "clk_bulk_enable() failed: %s\n",
+ strerror(-ret));
+ return ret;
+ }
+
+ udelay(10);
+
+ ret = eqos_start(edev);
+ if (ret)
+ goto err_stop_clks;
+
+ return 0;
+
+err_stop_clks:
+ clk_bulk_disable(priv->num_clks, priv->clks);
+
+ return ret;
+}
+
+static void eqos_stop_stm32(struct eth_device *edev)
+{
+ struct eqos_stm32 *priv = to_stm32(edev->priv);
+
+ clk_bulk_disable(priv->num_clks, priv->clks);
+}
+
+// todo split!
+static struct eqos_ops stm32_ops = {
+ .init = eqos_init_stm32,
+ .get_ethaddr = eqos_get_ethaddr,
+ .set_ethaddr = eqos_set_ethaddr,
+ .start = eqos_start_stm32,
+ .stop = eqos_stop_stm32,
+ .adjust_link = eqos_adjust_link,
+ .get_csr_clk_rate = eqos_get_csr_clk_rate_stm32,
+
+ .mdio_wait_us = 10 * USEC_PER_MSEC,
+ .clk_csr = EQOS_MDIO_ADDR_CR_250_300,
+ .config_mac = EQOS_MAC_RXQ_CTRL0_RXQ0EN_ENABLED_AV,
+};
+
+static int eqos_probe_stm32(struct device_d *dev)
+{
+ return eqos_probe(dev, &stm32_ops, xzalloc(sizeof(struct eqos_stm32)));
+}
+
+static void eqos_remove_stm32(struct device_d *dev)
+{
+ struct eqos_stm32 *priv = to_stm32(dev->priv);
+
+ eqos_remove(dev);
+
+ clk_bulk_put(priv->num_clks, priv->clks);
+}
+
+static const struct of_device_id eqos_stm32_ids[] = {
+ { .compatible = "st,stm32mp1-dwmac" },
+ { /* sentinel */ }
+};
+
+static struct driver_d eqos_stm32_driver = {
+ .name = "eqos-stm32",
+ .probe = eqos_probe_stm32,
+ .remove = eqos_remove_stm32,
+ .of_compatible = DRV_OF_COMPAT(eqos_stm32_ids),
+};
+device_platform_driver(eqos_stm32_driver);
diff --git a/drivers/net/designware_tegra186.c b/drivers/net/designware_tegra186.c
new file mode 100644
index 0000000000..58484d4095
--- /dev/null
+++ b/drivers/net/designware_tegra186.c
@@ -0,0 +1,347 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (c) 2016, NVIDIA CORPORATION.
+ * Copyright (c) 2019, Ahmad Fatoum, Pengutronix
+ *
+ * Portions based on U-Boot's rtl8169.c and dwc_eth_qos.
+ */
+
+#include <common.h>
+#include <init.h>
+#include <gpio.h>
+#include <of_gpio.h>
+#include <linux/clk.h>
+#include <net.h>
+#include <linux/reset.h>
+
+#include "designware_eqos.h"
+
+/* These registers are Tegra186-specific */
+#define EQOS_TEGRA186_REGS_BASE 0x8800
+struct eqos_tegra186_regs {
+ uint32_t sdmemcomppadctrl; /* 0x8800 */
+ uint32_t auto_cal_config; /* 0x8804 */
+ uint32_t unused_8808; /* 0x8808 */
+ uint32_t auto_cal_status; /* 0x880c */
+};
+
+#define EQOS_SDMEMCOMPPADCTRL_PAD_E_INPUT_OR_E_PWRD BIT(31)
+
+#define EQOS_AUTO_CAL_CONFIG_START BIT(31)
+#define EQOS_AUTO_CAL_CONFIG_ENABLE BIT(29)
+
+#define EQOS_AUTO_CAL_STATUS_ACTIVE BIT(31)
+
+struct eqos_tegra186 {
+ struct clk_bulk_data *clks;
+ int num_clks;
+ struct reset_control *rst;
+ struct eqos_tegra186_regs __iomem *tegra186_regs;
+ int phy_reset_gpio;
+};
+
+static inline struct eqos_tegra186 *to_tegra186(struct eqos *eqos)
+{
+ return eqos->priv;
+}
+
+enum { CLK_SLAVE_BUS, CLK_MASTER_BUS, CLK_RX, CLK_PTP_REF, CLK_TX };
+static const struct clk_bulk_data tegra186_clks[] = {
+ [CLK_SLAVE_BUS] = { .id = "slave_bus" },
+ [CLK_MASTER_BUS] = { .id = "master_bus" },
+ [CLK_RX] = { .id = "rx" },
+ [CLK_PTP_REF] = { .id = "ptp_ref" },
+ [CLK_TX] = { .id = "tx" },
+};
+
+static int eqos_clks_set_rate_tegra186(struct eqos_tegra186 *priv)
+{
+ return clk_set_rate(priv->clks[CLK_PTP_REF].clk, 125 * 1000 * 1000);
+}
+
+static int eqos_reset_tegra186(struct eqos_tegra186 *priv, bool reset)
+{
+ int ret;
+
+ if (reset) {
+ reset_control_assert(priv->rst);
+ gpio_set_value(priv->phy_reset_gpio, 1);
+ return 0;
+ }
+
+ gpio_set_value(priv->phy_reset_gpio, 1);
+
+ udelay(2);
+
+ gpio_set_value(priv->phy_reset_gpio, 0);
+
+ ret = reset_control_assert(priv->rst);
+ if (ret < 0)
+ return ret;
+
+ udelay(2);
+
+ return reset_control_deassert(priv->rst);
+}
+
+static int eqos_calibrate_pads_tegra186(struct eqos *eqos)
+{
+ struct eqos_tegra186 *priv = to_tegra186(eqos);
+ u32 active;
+ int ret;
+
+ setbits_le32(&priv->tegra186_regs->sdmemcomppadctrl,
+ EQOS_SDMEMCOMPPADCTRL_PAD_E_INPUT_OR_E_PWRD);
+
+ udelay(1);
+
+ setbits_le32(&priv->tegra186_regs->auto_cal_config,
+ EQOS_AUTO_CAL_CONFIG_START | EQOS_AUTO_CAL_CONFIG_ENABLE);
+
+ ret = readl_poll_timeout(&priv->tegra186_regs->auto_cal_status, active,
+ active & EQOS_AUTO_CAL_STATUS_ACTIVE,
+ 10000);
+ if (ret) {
+ eqos_err(eqos, "calibrate didn't start\n");
+ goto failed;
+ }
+
+ ret = readl_poll_timeout(&priv->tegra186_regs->auto_cal_status, active,
+ !(active & EQOS_AUTO_CAL_STATUS_ACTIVE),
+ 10000);
+ if (ret) {
+ eqos_err(eqos, "calibrate didn't finish\n");
+ goto failed;
+ }
+
+failed:
+ clrbits_le32(&priv->tegra186_regs->sdmemcomppadctrl,
+ EQOS_SDMEMCOMPPADCTRL_PAD_E_INPUT_OR_E_PWRD);
+
+ return ret;
+}
+
+static int eqos_calibrate_link_tegra186(struct eqos *eqos, unsigned speed)
+{
+ struct eqos_tegra186 *priv = to_tegra186(eqos);
+ int ret = 0;
+ unsigned long rate;
+ bool calibrate;
+
+ switch (speed) {
+ case SPEED_1000:
+ rate = 125 * 1000 * 1000;
+ calibrate = true;
+ break;
+ case SPEED_100:
+ rate = 25 * 1000 * 1000;
+ calibrate = true;
+ break;
+ case SPEED_10:
+ rate = 2.5 * 1000 * 1000;
+ calibrate = false;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ if (calibrate) {
+ ret = eqos_calibrate_pads_tegra186(eqos);
+ if (ret)
+ return ret;
+ } else {
+ clrbits_le32(&priv->tegra186_regs->auto_cal_config,
+ EQOS_AUTO_CAL_CONFIG_ENABLE);
+ }
+
+ ret = clk_set_rate(priv->clks[CLK_TX].clk, rate);
+ if (ret < 0) {
+ eqos_err(eqos, "clk_set_rate(tx_clk, %lu) failed: %d\n", rate, ret);
+ return ret;
+ }
+
+ return 0;
+}
+
+static unsigned long eqos_get_csr_clk_rate_tegra186(struct eqos *eqos)
+{
+ return clk_get_rate(to_tegra186(eqos)->clks[CLK_SLAVE_BUS].clk);
+}
+
+static int eqos_set_ethaddr_tegra186(struct eth_device *edev, const unsigned char *mac)
+{
+ struct eqos *eqos = edev->priv;
+
+ /*
+ * This function may be called before start() or after stop(). At that
+ * time, on at least some configurations of the EQoS HW, all clocks to
+ * the EQoS HW block will be stopped, and a reset signal applied. If
+ * any register access is attempted in this state, bus timeouts or CPU
+ * hangs may occur. This check prevents that.
+ *
+ * A simple solution to this problem would be to not implement
+ * write_hwaddr(), since start() always writes the MAC address into HW
+ * anyway. However, it is desirable to implement write_hwaddr() to
+ * support the case of SW that runs subsequent to U-Boot which expects
+ * the MAC address to already be programmed into the EQoS registers,
+ * which must happen irrespective of whether the U-Boot user (or
+ * scripts) actually made use of the EQoS device, and hence
+ * irrespective of whether start() was ever called.
+ *
+ * Note that this requirement by subsequent SW is not valid for
+ * Tegra186, and is likely not valid for any non-PCI instantiation of
+ * the EQoS HW block. This function is implemented solely as
+ * future-proofing with the expectation the driver will eventually be
+ * ported to some system where the expectation above is true.
+ */
+
+ if (!eqos->started) {
+ memcpy(eqos->macaddr, mac, 6);
+ return 0;
+ }
+
+ return eqos_set_ethaddr(edev, mac);
+}
+
+static int eqos_init_tegra186(struct device_d *dev, struct eqos *eqos)
+{
+ struct eqos_tegra186 *priv = to_tegra186(eqos);
+ int phy_reset;
+ int ret;
+
+ priv->tegra186_regs = IOMEM(eqos->regs + EQOS_TEGRA186_REGS_BASE);
+
+ priv->rst = reset_control_get(dev, "eqos");
+ if (IS_ERR(priv->rst)) {
+ ret = PTR_ERR(priv->rst);
+ dev_err(dev, "reset_get_by_name(rst) failed: %s\n", strerror(-ret));
+ return ret;
+ }
+
+ phy_reset = of_get_named_gpio(dev->device_node, "phy-reset-gpios", 0);
+ if (gpio_is_valid(phy_reset)) {
+ ret = gpio_request(phy_reset, "phy-reset");
+ if (ret)
+ goto release_res;
+
+ priv->phy_reset_gpio = phy_reset;
+ }
+
+ priv->clks = xmemdup(tegra186_clks, sizeof(tegra186_clks));
+ priv->num_clks = ARRAY_SIZE(tegra186_clks);
+
+ return 0;
+
+release_res:
+ reset_control_put(priv->rst);
+ return ret;
+}
+
+static int eqos_start_tegra186(struct eth_device *edev)
+{
+ struct eqos *eqos = edev->priv;
+ struct eqos_tegra186 *priv = to_tegra186(eqos);
+ int ret;
+
+ ret = clk_bulk_enable(priv->num_clks, priv->clks);
+ if (ret < 0) {
+ eqos_err(eqos, "clk_bulk_enable() failed: %s\n", strerror(-ret));
+ return ret;
+ }
+
+ ret = eqos_clks_set_rate_tegra186(priv);
+ if (ret < 0) {
+ eqos_err(eqos, "clks_set_rate() failed: %s\n", strerror(-ret));
+ goto err;
+ }
+
+ eqos_reset_tegra186(priv, false);
+ if (ret < 0) {
+ eqos_err(eqos, "reset(0) failed: %s\n", strerror(-ret));
+ goto err_stop_clks;
+ }
+
+ udelay(10);
+
+ ret = eqos_start(edev);
+ if (ret)
+ goto err_stop_resets;
+
+ return 0;
+
+err_stop_resets:
+ eqos_reset_tegra186(priv, true);
+err_stop_clks:
+ clk_bulk_disable(priv->num_clks, priv->clks);
+err:
+ return ret;
+}
+
+
+static void eqos_stop_tegra186(struct eth_device *edev)
+{
+ struct eqos_tegra186 *priv = to_tegra186(edev->priv);
+
+ eqos_reset_tegra186(priv, true);
+
+ clk_bulk_disable(priv->num_clks, priv->clks);
+}
+
+static void eqos_adjust_link_tegra186(struct eth_device *edev)
+{
+ struct eqos *eqos = edev->priv;
+ unsigned speed = edev->phydev->speed;
+ int ret;
+
+ eqos_adjust_link(edev);
+
+ ret = eqos_calibrate_link_tegra186(eqos, speed);
+ if (ret < 0) {
+ eqos_err(eqos, "eqos_calibrate_link_tegra186() failed: %d\n", ret);
+ return;
+ }
+}
+
+static const struct eqos_ops tegra186_ops = {
+ .init = eqos_init_tegra186,
+ .get_ethaddr = eqos_get_ethaddr,
+ .set_ethaddr = eqos_set_ethaddr_tegra186,
+ .start = eqos_start_tegra186,
+ .stop = eqos_stop_tegra186,
+ .adjust_link = eqos_adjust_link_tegra186,
+ .get_csr_clk_rate = eqos_get_csr_clk_rate_tegra186,
+
+ .mdio_wait_us = 10,
+ .clk_csr = EQOS_MDIO_ADDR_CR_20_35,
+ .config_mac = EQOS_MAC_RXQ_CTRL0_RXQ0EN_ENABLED_DCB,
+};
+
+static int eqos_probe_tegra186(struct device_d *dev)
+{
+ return eqos_probe(dev, &tegra186_ops, xzalloc(sizeof(struct eqos_tegra186)));
+}
+
+static void eqos_remove_tegra186(struct device_d *dev)
+{
+ struct eqos_tegra186 *priv = to_tegra186(dev->priv);
+
+ eqos_remove(dev);
+
+ clk_bulk_put(priv->num_clks, priv->clks);
+
+ gpio_free(priv->phy_reset_gpio);
+ reset_control_put(priv->rst);
+}
+
+static const struct of_device_id eqos_tegra186_ids[] = {
+ { .compatible = "nvidia,tegra186-eqos" },
+ { /* sentinel */ }
+};
+
+static struct driver_d eqos_tegra186_driver = {
+ .name = "eqos-tegra186",
+ .probe = eqos_probe_tegra186,
+ .remove = eqos_remove_tegra186,
+ .of_compatible = DRV_OF_COMPAT(eqos_tegra186_ids),
+};
+device_platform_driver(eqos_tegra186_driver);
diff --git a/drivers/nvmem/Kconfig b/drivers/nvmem/Kconfig
index c28a6d4e43..968342b281 100644
--- a/drivers/nvmem/Kconfig
+++ b/drivers/nvmem/Kconfig
@@ -51,4 +51,12 @@ config EEPROM_93XX46
supports both read and write commands and also the command to
erase the whole EEPROM.
+config STM32_BSEC
+ tristate "STM32 Boot and security and OTP control"
+ depends on ARCH_STM32MP
+ depends on OFDEVICE
+ help
+ This adds support for the STM32 OTP controller. Reads and writes
+ to will go to the shadow RAM, not the OTP fuses themselvers.
+
endif
diff --git a/drivers/nvmem/Makefile b/drivers/nvmem/Makefile
index abf9dae429..7101c5aca4 100644
--- a/drivers/nvmem/Makefile
+++ b/drivers/nvmem/Makefile
@@ -16,4 +16,7 @@ obj-$(CONFIG_RAVE_SP_EEPROM) += nvmem-rave-sp-eeprom.o
nvmem-rave-sp-eeprom-y := rave-sp-eeprom.o
obj-$(CONFIG_EEPROM_93XX46) += nvmem_eeprom_93xx46.o
-nvmem_eeprom_93xx46-y := eeprom_93xx46.o \ No newline at end of file
+nvmem_eeprom_93xx46-y := eeprom_93xx46.o
+
+obj-$(CONFIG_STM32_BSEC) += nvmem_bsec.o
+nvmem_bsec-y := bsec.o
diff --git a/drivers/nvmem/bsec.c b/drivers/nvmem/bsec.c
new file mode 100644
index 0000000000..8235d468d1
--- /dev/null
+++ b/drivers/nvmem/bsec.c
@@ -0,0 +1,221 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2018, STMicroelectronics - All Rights Reserved
+ * Copyright (c) 2019 Ahmad Fatoum, Pengutronix
+ */
+
+#include <common.h>
+#include <driver.h>
+#include <malloc.h>
+#include <xfuncs.h>
+#include <errno.h>
+#include <init.h>
+#include <net.h>
+#include <io.h>
+#include <of.h>
+#include <regmap.h>
+#include <mach/bsec.h>
+#include <machine_id.h>
+#include <linux/nvmem-provider.h>
+
+#define BSEC_OTP_SERIAL 13
+
+struct bsec_priv {
+ struct regmap *map;
+ u32 svc_id;
+ struct device_d dev;
+ struct regmap_config map_config;
+ struct nvmem_config config;
+};
+
+struct stm32_bsec_data {
+ unsigned long svc_id;
+ int num_regs;
+};
+
+static int bsec_smc(struct bsec_priv *priv, u8 op, enum bsec_field field,
+ unsigned data2, unsigned *val)
+{
+ enum bsec_smc ret = stm32mp_smc(priv->svc_id, op, field / 4, data2, val);
+ switch(ret)
+ {
+ case BSEC_SMC_OK:
+ return 0;
+ case BSEC_SMC_ERROR:
+ case BSEC_SMC_DISTURBED:
+ case BSEC_SMC_PROG_FAIL:
+ case BSEC_SMC_LOCK_FAIL:
+ case BSEC_SMC_WRITE_FAIL:
+ case BSEC_SMC_SHADOW_FAIL:
+ return -EIO;
+ case BSEC_SMC_INVALID_PARAM:
+ return -EINVAL;
+ case BSEC_SMC_TIMEOUT:
+ return -ETIMEDOUT;
+ }
+
+ return -ENXIO;
+}
+
+static int st32_bsec_read_shadow(void *ctx, unsigned reg, unsigned *val)
+{
+ return bsec_smc(ctx, BSEC_SMC_READ_SHADOW, reg, 0, val);
+}
+
+static int stm32_bsec_reg_write_shadow(void *ctx, unsigned reg, unsigned val)
+{
+ return bsec_smc(ctx, BSEC_SMC_WRITE_SHADOW, reg, val, NULL);
+}
+
+static struct regmap_bus stm32_bsec_regmap_bus = {
+ .reg_write = stm32_bsec_reg_write_shadow,
+ .reg_read = st32_bsec_read_shadow,
+};
+
+static int stm32_bsec_write(struct device_d *dev, int offset,
+ const void *val, int bytes)
+{
+ struct bsec_priv *priv = dev->parent->priv;
+
+ return regmap_bulk_write(priv->map, offset, val, bytes);
+}
+
+static int stm32_bsec_read(struct device_d *dev, int offset,
+ void *val, int bytes)
+{
+ struct bsec_priv *priv = dev->parent->priv;
+
+ return regmap_bulk_read(priv->map, offset, val, bytes);
+}
+
+static const struct nvmem_bus stm32_bsec_nvmem_bus = {
+ .write = stm32_bsec_write,
+ .read = stm32_bsec_read,
+};
+
+static void stm32_bsec_set_unique_machine_id(struct regmap *map)
+{
+ u32 unique_id[3];
+ int ret;
+
+ ret = regmap_bulk_read(map, BSEC_OTP_SERIAL * 4,
+ unique_id, sizeof(unique_id));
+ if (ret)
+ return;
+
+ machine_id_set_hashable(unique_id, sizeof(unique_id));
+}
+
+static int stm32_bsec_read_mac(struct regmap *map, int offset, u8 *mac)
+{
+ u8 res[8];
+ int ret;
+
+ ret = regmap_bulk_read(map, offset * 4, res, 8);
+ if (ret)
+ return ret;
+
+ memcpy(mac, res, ETH_ALEN);
+ return 0;
+}
+
+static void stm32_bsec_init_dt(struct bsec_priv *priv)
+{
+ struct device_node *node = priv->dev.parent->device_node;
+ struct device_node *rnode;
+ u32 phandle, offset;
+ char mac[ETH_ALEN];
+ const __be32 *prop;
+
+ int len;
+ int ret;
+
+ if (!node)
+ return;
+
+ prop = of_get_property(node, "barebox,provide-mac-address", &len);
+ if (!prop)
+ return;
+
+ if (len != 2 * sizeof(__be32))
+ return;
+
+ phandle = be32_to_cpup(prop++);
+
+ rnode = of_find_node_by_phandle(phandle);
+ offset = be32_to_cpup(prop++);
+
+ ret = stm32_bsec_read_mac(priv->map, offset, mac);
+ if (ret) {
+ dev_warn(&priv->dev, "error setting MAC address: %s\n",
+ strerror(-ret));
+ return;
+ }
+
+ of_eth_register_ethaddr(rnode, mac);
+}
+
+static int stm32_bsec_probe(struct device_d *dev)
+{
+ struct bsec_priv *priv;
+ int ret = 0;
+ const struct stm32_bsec_data *data;
+ struct nvmem_device *nvmem;
+
+ ret = dev_get_drvdata(dev, (const void **)&data);
+ if (ret)
+ return ret;
+
+ priv = xzalloc(sizeof(*priv));
+
+ priv->svc_id = data->svc_id;
+
+ dev_set_name(&priv->dev, "bsec");
+ priv->dev.parent = dev;
+ register_device(&priv->dev);
+
+ priv->map_config.reg_bits = 32;
+ priv->map_config.val_bits = 32;
+ priv->map_config.reg_stride = 4;
+ priv->map_config.max_register = data->num_regs;
+
+ priv->map = regmap_init(dev, &stm32_bsec_regmap_bus, priv, &priv->map_config);
+ if (IS_ERR(priv->map))
+ return PTR_ERR(priv->map);
+
+ priv->config.name = "stm32-bsec";
+ priv->config.dev = dev;
+ priv->config.stride = 4;
+ priv->config.word_size = 4;
+ priv->config.size = data->num_regs;
+ priv->config.bus = &stm32_bsec_nvmem_bus;
+ dev->priv = priv;
+
+ nvmem = nvmem_register(&priv->config);
+ if (IS_ERR(nvmem))
+ return PTR_ERR(nvmem);
+
+ if (IS_ENABLED(CONFIG_MACHINE_ID))
+ stm32_bsec_set_unique_machine_id(priv->map);
+
+ stm32_bsec_init_dt(priv);
+
+ return 0;
+}
+
+static struct stm32_bsec_data stm32mp15_bsec_data = {
+ .num_regs = 95 * 4,
+ .svc_id = STM32_SMC_BSEC,
+};
+
+static __maybe_unused struct of_device_id stm32_bsec_dt_ids[] = {
+ { .compatible = "st,stm32mp15-bsec", .data = &stm32mp15_bsec_data },
+ { /* sentinel */ }
+};
+
+static struct driver_d stm32_bsec_driver = {
+ .name = "stm32_bsec",
+ .probe = stm32_bsec_probe,
+ .of_compatible = DRV_OF_COMPAT(stm32_bsec_dt_ids),
+};
+postcore_platform_driver(stm32_bsec_driver);
diff --git a/drivers/of/of_gpio.c b/drivers/of/of_gpio.c
index 9a8331ed18..7cbeeaf69e 100644
--- a/drivers/of/of_gpio.c
+++ b/drivers/of/of_gpio.c
@@ -19,18 +19,20 @@ static void of_gpio_flags_quirks(struct device_node *np,
(!(strcmp(propname, "enable-gpio") &&
strcmp(propname, "enable-gpios")) &&
of_device_is_compatible(np, "regulator-gpio")))) {
+ bool active_low = !of_property_read_bool(np,
+ "enable-active-high");
/*
* The regulator GPIO handles are specified such that the
* presence or absence of "enable-active-high" solely controls
* the polarity of the GPIO line. Any phandle flags must
* be actively ignored.
*/
- if (*flags & OF_GPIO_ACTIVE_LOW) {
+ if ((*flags & OF_GPIO_ACTIVE_LOW) && !active_low) {
pr_warn("%s GPIO handle specifies active low - ignored\n",
np->full_name);
*flags &= ~OF_GPIO_ACTIVE_LOW;
}
- if (!of_property_read_bool(np, "enable-active-high"))
+ if (active_low)
*flags |= OF_GPIO_ACTIVE_LOW;
}
}
diff --git a/drivers/of/of_path.c b/drivers/of/of_path.c
index f8bbf2cba1..5c3a020345 100644
--- a/drivers/of/of_path.c
+++ b/drivers/of/of_path.c
@@ -83,7 +83,7 @@ static int __of_find_path(struct device_node *node, const char *part, char **out
}
if (dev->bus && !dev->driver)
- return -ENODEV;
+ return -EPROBE_DEFER;
device_detect(dev);
diff --git a/drivers/pinctrl/pinctrl-at91-pio4.c b/drivers/pinctrl/pinctrl-at91-pio4.c
index 9bc259f84c..b527114f1b 100644
--- a/drivers/pinctrl/pinctrl-at91-pio4.c
+++ b/drivers/pinctrl/pinctrl-at91-pio4.c
@@ -260,7 +260,7 @@ static int pinctrl_at91_pio4_gpiochip_add(struct device_d *dev,
return ret;
}
- dev_info(dev, "gpio driver registered\n");
+ dev_dbg(dev, "gpio driver registered\n");
return 0;
}
@@ -290,7 +290,7 @@ static int pinctrl_at91_pio4_probe(struct device_d *dev)
if (ret)
return ret;
- dev_info(dev, "pinctrl driver registered\n");
+ dev_dbg(dev, "pinctrl driver registered\n");
if (of_get_property(np, "gpio-controller", NULL))
return pinctrl_at91_pio4_gpiochip_add(dev, pinctrl);
diff --git a/drivers/pinctrl/pinctrl-bcm2835.c b/drivers/pinctrl/pinctrl-bcm2835.c
index 5fd5740e81..b8e9b60372 100644
--- a/drivers/pinctrl/pinctrl-bcm2835.c
+++ b/drivers/pinctrl/pinctrl-bcm2835.c
@@ -171,7 +171,7 @@ static int bcm2835_gpio_probe(struct device_d *dev)
goto err;
}
- dev_info(dev, "probed gpiochip%d with base %d\n", dev->id, bcmgpio->chip.base);
+ dev_dbg(dev, "probed gpiochip%d with base %d\n", dev->id, bcmgpio->chip.base);
if (IS_ENABLED(CONFIG_PINCTRL)) {
ret = pinctrl_register(&bcmgpio->pctl);
diff --git a/drivers/pinctrl/pinctrl-stm32.c b/drivers/pinctrl/pinctrl-stm32.c
index 7f04cea50b..cdaed510c5 100644
--- a/drivers/pinctrl/pinctrl-stm32.c
+++ b/drivers/pinctrl/pinctrl-stm32.c
@@ -87,110 +87,128 @@ static inline u32 stm32_gpio_get_alt(u32 function)
return 0;
}
-static int stm32_pinctrl_set_state(struct pinctrl_device *pdev, struct device_node *group)
+static int __stm32_pinctrl_set_state(struct device_d *dev, struct device_node *pins)
{
- struct stm32_pinctrl *pinctrl = to_stm32_pinctrl(pdev);
- struct device_node *pins;
int ret;
- ret = hwspinlock_lock_timeout(&pinctrl->hws, 10);
- if (ret == -ETIMEDOUT) {
- dev_err(pdev->dev, "hw spinlock timeout\n");
- return ret;
+ int num_pins = 0, i;
+ u32 slew_rate;
+ bool adjust_slew_rate = false;
+ enum stm32_pin_bias bias = -1;
+ enum stm32_pin_out_type out_type = -1;
+ enum { PIN_INPUT, PIN_OUTPUT_LOW, PIN_OUTPUT_HIGH } dir = -1;
+
+ of_get_property(pins, "pinmux", &num_pins);
+ num_pins /= sizeof(__be32);
+ if (!num_pins) {
+ dev_err(dev, "Invalid pinmux property in %s\n",
+ pins->full_name);
+ return -EINVAL;
}
- for_each_child_of_node(group, pins) {
- int num_pins = 0, i;
- u32 slew_rate;
- bool adjust_slew_rate = false;
- enum stm32_pin_bias bias = -1;
- enum stm32_pin_out_type out_type = -1;
- enum { PIN_INPUT, PIN_OUTPUT_LOW, PIN_OUTPUT_HIGH } dir = -1;
-
- of_get_property(pins, "pinmux", &num_pins);
- num_pins /= sizeof(__be32);
- if (!num_pins) {
- dev_err(pdev->dev, "Invalid pinmux property in %s\n",
- pins->full_name);
- return -EINVAL;
- }
-
- ret = of_property_read_u32(pins, "slew-rate", &slew_rate);
- if (!ret)
- adjust_slew_rate = true;
-
- if (of_get_property(pins, "bias-disable", NULL))
- bias = STM32_PIN_NO_BIAS;
- else if (of_get_property(pins, "bias-pull-up", NULL))
- bias = STM32_PIN_PULL_UP;
- else if (of_get_property(pins, "bias-pull-down", NULL))
- bias = STM32_PIN_PULL_DOWN;
+ ret = of_property_read_u32(pins, "slew-rate", &slew_rate);
+ if (!ret)
+ adjust_slew_rate = true;
+
+ if (of_get_property(pins, "bias-disable", NULL))
+ bias = STM32_PIN_NO_BIAS;
+ else if (of_get_property(pins, "bias-pull-up", NULL))
+ bias = STM32_PIN_PULL_UP;
+ else if (of_get_property(pins, "bias-pull-down", NULL))
+ bias = STM32_PIN_PULL_DOWN;
+
+ if (of_get_property(pins, "drive-push-pull", NULL))
+ out_type = STM32_PIN_OUT_PUSHPULL;
+ else if (of_get_property(pins, "drive-open-drain", NULL))
+ out_type = STM32_PIN_OUT_OPENDRAIN;
+
+ if (of_get_property(pins, "input-enable", NULL))
+ dir = PIN_INPUT;
+ else if (of_get_property(pins, "output-low", NULL))
+ dir = PIN_OUTPUT_LOW;
+ else if (of_get_property(pins, "output-high", NULL))
+ dir = PIN_OUTPUT_HIGH;
+
+ dev_dbg(dev, "%s: multiplexing %d pins\n", pins->full_name, num_pins);
+
+ for (i = 0; i < num_pins; i++) {
+ struct stm32_gpio_bank *bank = NULL;
+ u32 pinfunc, mode, alt;
+ unsigned func;
+ int offset;
+
+ ret = of_property_read_u32_index(pins, "pinmux",
+ i, &pinfunc);
+ if (ret)
+ return ret;
- if (of_get_property(pins, "drive-push-pull", NULL))
- out_type = STM32_PIN_OUT_PUSHPULL;
- else if (of_get_property(pins, "drive-open-drain", NULL))
- out_type = STM32_PIN_OUT_OPENDRAIN;
+ func = STM32_GET_PIN_FUNC(pinfunc);
+ offset = stm32_gpio_pin(STM32_GET_PIN_NO(pinfunc), &bank);
+ if (offset < 0)
+ return -ENODEV;
- if (of_get_property(pins, "input-enable", NULL))
- dir = PIN_INPUT;
- else if (of_get_property(pins, "output-low", NULL))
- dir = PIN_OUTPUT_LOW;
- else if (of_get_property(pins, "output-high", NULL))
- dir = PIN_OUTPUT_HIGH;
+ mode = stm32_gpio_get_mode(func);
+ alt = stm32_gpio_get_alt(func);
- dev_dbg(pdev->dev, "%s: multiplexing %d pins\n",
- pins->full_name, num_pins);
+ dev_dbg(dev, "configuring port %s pin %u with:\n\t"
+ "fn %u, mode %u, alt %u\n",
+ bank->name, offset, func, mode, alt);
- for (i = 0; i < num_pins; i++) {
- struct stm32_gpio_bank *bank = NULL;
- u32 pinfunc, mode, alt;
- unsigned func;
- int offset;
+ clk_enable(bank->clk);
- ret = of_property_read_u32_index(pins, "pinmux",
- i, &pinfunc);
- if (ret)
- return ret;
+ __stm32_pmx_set_mode(bank->base, offset, mode, alt);
- func = STM32_GET_PIN_FUNC(pinfunc);
- offset = stm32_gpio_pin(STM32_GET_PIN_NO(pinfunc), &bank);
- if (offset < 0)
- return -ENODEV;
+ if (adjust_slew_rate)
+ __stm32_pmx_set_speed(bank->base, offset, slew_rate);
- dev_dbg(pdev->dev, "configuring port %s pin %u with:\n\t"
- "fn %u, mode %u, alt %u\n",
- bank->name, offset, func, mode, alt);
+ if (bias != -1)
+ __stm32_pmx_set_bias(bank->base, offset, bias);
- mode = stm32_gpio_get_mode(func);
- alt = stm32_gpio_get_alt(func);
+ if (out_type != -1)
+ __stm32_pmx_set_output_type(bank->base, offset, out_type);
- clk_enable(bank->clk);
+ if (dir == PIN_INPUT)
+ __stm32_pmx_gpio_input(bank->base, offset);
+ else if (dir == PIN_OUTPUT_LOW)
+ __stm32_pmx_gpio_output(bank->base, offset, 0);
+ else if (dir == PIN_OUTPUT_HIGH)
+ __stm32_pmx_gpio_output(bank->base, offset, 1);
- __stm32_pmx_set_mode(bank->base, offset, mode, alt);
+ clk_disable(bank->clk);
+ }
- if (adjust_slew_rate)
- __stm32_pmx_set_speed(bank->base, offset, slew_rate);
+ return 0;
+}
- if (bias != -1)
- __stm32_pmx_set_bias(bank->base, offset, bias);
+static int stm32_pinctrl_set_state(struct pinctrl_device *pdev, struct device_node *np)
+{
+ struct stm32_pinctrl *pinctrl = to_stm32_pinctrl(pdev);
+ struct device_d *dev = pdev->dev;
+ struct device_node *pins;
+ void *prop;
+ int ret;
- if (out_type != -1)
- __stm32_pmx_set_output_type(bank->base, offset, out_type);
+ ret = hwspinlock_lock_timeout(&pinctrl->hws, 10);
+ if (ret == -ETIMEDOUT) {
+ dev_err(dev, "hw spinlock timeout\n");
+ return ret;
+ }
- if (dir == PIN_INPUT)
- __stm32_pmx_gpio_input(bank->base, offset);
- else if (dir == PIN_OUTPUT_LOW)
- __stm32_pmx_gpio_output(bank->base, offset, 0);
- else if (dir == PIN_OUTPUT_HIGH)
- __stm32_pmx_gpio_output(bank->base, offset, 1);
+ prop = of_find_property(np, "pinmux", NULL);
+ if (prop) {
+ ret = __stm32_pinctrl_set_state(dev, np);
+ goto out;
+ }
- clk_disable(bank->clk);
- }
+ for_each_child_of_node(np, pins) {
+ ret = __stm32_pinctrl_set_state(dev, pins);
+ if (ret)
+ goto out;
}
+out:
hwspinlock_unlock(&pinctrl->hws);
-
- return 0;
+ return ret;
}
/* GPIO functions */
@@ -401,7 +419,7 @@ static int stm32_pinctrl_probe(struct device_d *dev)
}
}
- dev_info(dev, "pinctrl/gpio driver registered\n");
+ dev_dbg(dev, "pinctrl/gpio driver registered\n");
return 0;
}
diff --git a/drivers/regulator/Kconfig b/drivers/regulator/Kconfig
index c734ef5ef9..28bd69a2a5 100644
--- a/drivers/regulator/Kconfig
+++ b/drivers/regulator/Kconfig
@@ -21,6 +21,15 @@ config REGULATOR_PFUZE
depends on I2C
depends on ARCH_IMX6
+config REGULATOR_STPMIC1
+ tristate "STMicroelectronics STPMIC1 PMIC Regulators"
+ depends on MFD_STPMIC1
+ help
+ This driver supports STMicroelectronics STPMIC1 PMIC voltage
+ regulators and switches. The STPMIC1 regulators supply power to
+ an application processor as well as to external system
+ peripherals such as DDR, Flash memories and system devices.
+
config REGULATOR_ANATOP
tristate "Freescale i.MX on-chip ANATOP LDO regulators"
depends on MFD_SYSCON
diff --git a/drivers/regulator/Makefile b/drivers/regulator/Makefile
index b2fc5b79b6..e27e155cf6 100644
--- a/drivers/regulator/Makefile
+++ b/drivers/regulator/Makefile
@@ -1,5 +1,7 @@
obj-$(CONFIG_REGULATOR) += core.o helpers.o
+obj-$(CONFIG_OFDEVICE) += of_regulator.o
obj-$(CONFIG_REGULATOR_FIXED) += fixed.o
obj-$(CONFIG_REGULATOR_BCM283X) += bcm2835.o
obj-$(CONFIG_REGULATOR_PFUZE) += pfuze.o
-obj-$(CONFIG_REGULATOR_ANATOP) += anatop-regulator.o \ No newline at end of file
+obj-$(CONFIG_REGULATOR_STPMIC1) += stpmic1_regulator.o
+obj-$(CONFIG_REGULATOR_ANATOP) += anatop-regulator.o
diff --git a/drivers/regulator/helpers.c b/drivers/regulator/helpers.c
index f22d21b35d..c4877cecf7 100644
--- a/drivers/regulator/helpers.c
+++ b/drivers/regulator/helpers.c
@@ -184,3 +184,189 @@ int regulator_list_voltage_linear(struct regulator_dev *rdev,
return rdev->desc->min_uV + (rdev->desc->uV_step * selector);
}
EXPORT_SYMBOL_GPL(regulator_list_voltage_linear);
+
+/**
+ * regulator_desc_list_voltage_linear_range - List voltages for linear ranges
+ *
+ * @desc: Regulator desc for regulator which volatges are to be listed
+ * @selector: Selector to convert into a voltage
+ *
+ * Regulators with a series of simple linear mappings between voltages
+ * and selectors who have set linear_ranges in the regulator descriptor
+ * can use this function prior regulator registration to list voltages.
+ * This is useful when voltages need to be listed during device-tree
+ * parsing.
+ */
+int regulator_desc_list_voltage_linear_range(const struct regulator_desc *desc,
+ unsigned int selector)
+{
+ const struct regulator_linear_range *range;
+ int i;
+
+ if (!desc->n_linear_ranges) {
+ BUG_ON(!desc->n_linear_ranges);
+ return -EINVAL;
+ }
+
+ for (i = 0; i < desc->n_linear_ranges; i++) {
+ range = &desc->linear_ranges[i];
+
+ if (!(selector >= range->min_sel &&
+ selector <= range->max_sel))
+ continue;
+
+ selector -= range->min_sel;
+
+ return range->min_uV + (range->uV_step * selector);
+ }
+
+ return -EINVAL;
+}
+EXPORT_SYMBOL_GPL(regulator_desc_list_voltage_linear_range);
+
+/**
+ * regulator_list_voltage_linear_range - List voltages for linear ranges
+ *
+ * @rdev: Regulator device
+ * @selector: Selector to convert into a voltage
+ *
+ * Regulators with a series of simple linear mappings between voltages
+ * and selectors can set linear_ranges in the regulator descriptor and
+ * then use this function as their list_voltage() operation,
+ */
+int regulator_list_voltage_linear_range(struct regulator_dev *rdev,
+ unsigned int selector)
+{
+ return regulator_desc_list_voltage_linear_range(rdev->desc, selector);
+}
+EXPORT_SYMBOL_GPL(regulator_list_voltage_linear_range);
+
+/**
+ * regulator_map_voltage_linear_range - map_voltage() for multiple linear ranges
+ *
+ * @rdev: Regulator to operate on
+ * @min_uV: Lower bound for voltage
+ * @max_uV: Upper bound for voltage
+ *
+ * Drivers providing linear_ranges in their descriptor can use this as
+ * their map_voltage() callback.
+ */
+int regulator_map_voltage_linear_range(struct regulator_dev *rdev,
+ int min_uV, int max_uV)
+{
+ const struct regulator_linear_range *range;
+ int ret = -EINVAL;
+ int voltage, i;
+
+ if (!rdev->desc->n_linear_ranges) {
+ BUG_ON(!rdev->desc->n_linear_ranges);
+ return -EINVAL;
+ }
+
+ for (i = 0; i < rdev->desc->n_linear_ranges; i++) {
+ int linear_max_uV;
+
+ range = &rdev->desc->linear_ranges[i];
+ linear_max_uV = range->min_uV +
+ (range->max_sel - range->min_sel) * range->uV_step;
+
+ if (!(min_uV <= linear_max_uV && max_uV >= range->min_uV))
+ continue;
+
+ if (min_uV <= range->min_uV)
+ min_uV = range->min_uV;
+
+ /* range->uV_step == 0 means fixed voltage range */
+ if (range->uV_step == 0) {
+ ret = 0;
+ } else {
+ ret = DIV_ROUND_UP(min_uV - range->min_uV,
+ range->uV_step);
+ if (ret < 0)
+ return ret;
+ }
+
+ ret += range->min_sel;
+
+ /*
+ * Map back into a voltage to verify we're still in bounds.
+ * If we are not, then continue checking rest of the ranges.
+ */
+ voltage = rdev->desc->ops->list_voltage(rdev, ret);
+ if (voltage >= min_uV && voltage <= max_uV)
+ break;
+ }
+
+ if (i == rdev->desc->n_linear_ranges)
+ return -EINVAL;
+
+ return ret;
+}
+EXPORT_SYMBOL_GPL(regulator_map_voltage_linear_range);
+
+/**
+ * regulator_get_voltage_sel_regmap - standard get_voltage_sel for regmap users
+ *
+ * @rdev: regulator to operate on
+ *
+ * Regulators that use regmap for their register I/O can set the
+ * vsel_reg and vsel_mask fields in their descriptor and then use this
+ * as their get_voltage_vsel operation, saving some code.
+ */
+int regulator_get_voltage_sel_regmap(struct regulator_dev *rdev)
+{
+ unsigned int val;
+ int ret;
+
+ ret = regmap_read(rdev->regmap, rdev->desc->vsel_reg, &val);
+ if (ret != 0)
+ return ret;
+
+ val &= rdev->desc->vsel_mask;
+ val >>= ffs(rdev->desc->vsel_mask) - 1;
+
+ return val;
+}
+EXPORT_SYMBOL_GPL(regulator_get_voltage_sel_regmap);
+
+/**
+ * regulator_map_voltage_iterate - map_voltage() based on list_voltage()
+ *
+ * @rdev: Regulator to operate on
+ * @min_uV: Lower bound for voltage
+ * @max_uV: Upper bound for voltage
+ *
+ * Drivers implementing set_voltage_sel() and list_voltage() can use
+ * this as their map_voltage() operation. It will find a suitable
+ * voltage by calling list_voltage() until it gets something in bounds
+ * for the requested voltages.
+ */
+int regulator_map_voltage_iterate(struct regulator_dev *rdev,
+ int min_uV, int max_uV)
+{
+ int best_val = INT_MAX;
+ int selector = 0;
+ int i, ret;
+
+ /* Find the smallest voltage that falls within the specified
+ * range.
+ */
+ for (i = 0; i < rdev->desc->n_voltages; i++) {
+ ret = rdev->desc->ops->list_voltage(rdev, i);
+ if (ret < 0)
+ continue;
+
+ if (ret < best_val && ret >= min_uV && ret <= max_uV) {
+ best_val = ret;
+ selector = i;
+ }
+ }
+
+ if (best_val != INT_MAX)
+ return selector;
+ else
+ return -EINVAL;
+}
+EXPORT_SYMBOL_GPL(regulator_map_voltage_iterate);
+
+
diff --git a/drivers/regulator/of_regulator.c b/drivers/regulator/of_regulator.c
new file mode 100644
index 0000000000..3e8caa8710
--- /dev/null
+++ b/drivers/regulator/of_regulator.c
@@ -0,0 +1,229 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * OF helpers for regulator framework
+ *
+ * Copyright (C) 2011 Texas Instruments, Inc.
+ * Rajendra Nayak <rnayak@ti.com>
+ */
+
+#include <common.h>
+#include <of.h>
+#include <linux/regulator/of_regulator.h>
+#include <linux/regulator/machine.h>
+
+static int of_get_regulation_constraints(struct device_d *dev,
+ struct device_node *np,
+ struct regulator_init_data **init_data,
+ const struct regulator_desc *desc)
+{
+ struct regulation_constraints *constraints = &(*init_data)->constraints;
+ int ret;
+ u32 pval;
+
+ constraints->name = of_get_property(np, "regulator-name", NULL);
+
+ if (!of_property_read_u32(np, "regulator-min-microvolt", &pval))
+ constraints->min_uV = pval;
+
+ if (!of_property_read_u32(np, "regulator-max-microvolt", &pval))
+ constraints->max_uV = pval;
+
+ /* Voltage change possible? */
+ if (constraints->min_uV != constraints->max_uV)
+ constraints->valid_ops_mask |= REGULATOR_CHANGE_VOLTAGE;
+
+ /* Do we have a voltage range, if so try to apply it? */
+ if (constraints->min_uV && constraints->max_uV)
+ constraints->apply_uV = true;
+
+ if (!of_property_read_u32(np, "regulator-microvolt-offset", &pval))
+ constraints->uV_offset = pval;
+ if (!of_property_read_u32(np, "regulator-min-microamp", &pval))
+ constraints->min_uA = pval;
+ if (!of_property_read_u32(np, "regulator-max-microamp", &pval))
+ constraints->max_uA = pval;
+
+ if (!of_property_read_u32(np, "regulator-input-current-limit-microamp",
+ &pval))
+ constraints->ilim_uA = pval;
+
+ /* Current change possible? */
+ if (constraints->min_uA != constraints->max_uA)
+ constraints->valid_ops_mask |= REGULATOR_CHANGE_CURRENT;
+
+ constraints->boot_on = of_property_read_bool(np, "regulator-boot-on");
+ constraints->always_on = of_property_read_bool(np, "regulator-always-on");
+ if (!constraints->always_on) /* status change should be possible. */
+ constraints->valid_ops_mask |= REGULATOR_CHANGE_STATUS;
+
+ constraints->pull_down = of_property_read_bool(np, "regulator-pull-down");
+
+ if (of_property_read_bool(np, "regulator-allow-bypass"))
+ constraints->valid_ops_mask |= REGULATOR_CHANGE_BYPASS;
+
+ if (of_property_read_bool(np, "regulator-allow-set-load"))
+ constraints->valid_ops_mask |= REGULATOR_CHANGE_DRMS;
+
+ ret = of_property_read_u32(np, "regulator-ramp-delay", &pval);
+ if (!ret) {
+ if (pval)
+ constraints->ramp_delay = pval;
+ else
+ constraints->ramp_disable = true;
+ }
+
+ ret = of_property_read_u32(np, "regulator-settling-time-us", &pval);
+ if (!ret)
+ constraints->settling_time = pval;
+
+ ret = of_property_read_u32(np, "regulator-settling-time-up-us", &pval);
+ if (!ret)
+ constraints->settling_time_up = pval;
+ if (constraints->settling_time_up && constraints->settling_time) {
+ pr_warn("%pOFn: ambiguous configuration for settling time, ignoring 'regulator-settling-time-up-us'\n",
+ np);
+ constraints->settling_time_up = 0;
+ }
+
+ ret = of_property_read_u32(np, "regulator-settling-time-down-us",
+ &pval);
+ if (!ret)
+ constraints->settling_time_down = pval;
+ if (constraints->settling_time_down && constraints->settling_time) {
+ pr_warn("%pOFn: ambiguous configuration for settling time, ignoring 'regulator-settling-time-down-us'\n",
+ np);
+ constraints->settling_time_down = 0;
+ }
+
+ ret = of_property_read_u32(np, "regulator-enable-ramp-delay", &pval);
+ if (!ret)
+ constraints->enable_time = pval;
+
+ constraints->soft_start = of_property_read_bool(np,
+ "regulator-soft-start");
+ ret = of_property_read_u32(np, "regulator-active-discharge", &pval);
+ if (!ret) {
+ constraints->active_discharge =
+ (pval) ? REGULATOR_ACTIVE_DISCHARGE_ENABLE :
+ REGULATOR_ACTIVE_DISCHARGE_DISABLE;
+ }
+
+ if (!of_property_read_u32(np, "regulator-system-load", &pval))
+ constraints->system_load = pval;
+
+ if (!of_property_read_u32(np, "regulator-max-step-microvolt",
+ &pval))
+ constraints->max_uV_step = pval;
+
+ constraints->over_current_protection = of_property_read_bool(np,
+ "regulator-over-current-protection");
+
+ return 0;
+}
+
+/**
+ * of_get_regulator_init_data - extract regulator_init_data structure info
+ * @dev: device requesting for regulator_init_data
+ * @node: regulator device node
+ * @desc: regulator description
+ *
+ * Populates regulator_init_data structure by extracting data from device
+ * tree node, returns a pointer to the populated structure or NULL if memory
+ * alloc fails.
+ */
+struct regulator_init_data *of_get_regulator_init_data(struct device_d *dev,
+ struct device_node *node,
+ const struct regulator_desc *desc)
+{
+ struct regulator_init_data *init_data;
+
+ if (!node)
+ return NULL;
+
+ init_data = xzalloc(sizeof(*init_data));
+
+ if (of_get_regulation_constraints(dev, node, &init_data, desc))
+ return NULL;
+
+ return init_data;
+}
+EXPORT_SYMBOL_GPL(of_get_regulator_init_data);
+
+struct devm_of_regulator_matches {
+ struct of_regulator_match *matches;
+ unsigned int num_matches;
+};
+
+/**
+ * of_regulator_match - extract multiple regulator init data from device tree.
+ * @dev: device requesting the data
+ * @node: parent device node of the regulators
+ * @matches: match table for the regulators
+ * @num_matches: number of entries in match table
+ *
+ * This function uses a match table specified by the regulator driver to
+ * parse regulator init data from the device tree. @node is expected to
+ * contain a set of child nodes, each providing the init data for one
+ * regulator. The data parsed from a child node will be matched to a regulator
+ * based on either the deprecated property regulator-compatible if present,
+ * or otherwise the child node's name. Note that the match table is modified
+ * in place and an additional of_node reference is taken for each matched
+ * regulator.
+ *
+ * Returns the number of matches found or a negative error code on failure.
+ */
+int of_regulator_match(struct device_d *dev, struct device_node *node,
+ struct of_regulator_match *matches,
+ unsigned int num_matches)
+{
+ unsigned int count = 0;
+ unsigned int i;
+ const char *name;
+ struct device_node *child;
+ struct devm_of_regulator_matches *devm_matches;
+
+ if (!dev || !node)
+ return -EINVAL;
+
+ devm_matches = xzalloc(sizeof(struct devm_of_regulator_matches));
+
+ devm_matches->matches = matches;
+ devm_matches->num_matches = num_matches;
+
+ for (i = 0; i < num_matches; i++) {
+ struct of_regulator_match *match = &matches[i];
+ match->init_data = NULL;
+ match->of_node = NULL;
+ }
+
+ for_each_child_of_node(node, child) {
+ name = of_get_property(child,
+ "regulator-compatible", NULL);
+ if (!name)
+ name = child->name;
+
+ for (i = 0; i < num_matches; i++) {
+ struct of_regulator_match *match = &matches[i];
+ if (match->of_node)
+ continue;
+
+ if (strcmp(match->name, name))
+ continue;
+
+ match->init_data = of_get_regulator_init_data(dev, child,
+ match->desc);
+ if (!match->init_data) {
+ dev_err(dev,
+ "failed to parse DT for regulator %pOFn\n",
+ child);
+ return -EINVAL;
+ }
+ match->of_node = child;
+ count++;
+ break;
+ }
+ }
+
+ return count;
+}
+EXPORT_SYMBOL_GPL(of_regulator_match);
diff --git a/drivers/regulator/stpmic1_regulator.c b/drivers/regulator/stpmic1_regulator.c
new file mode 100644
index 0000000000..aaaba092c1
--- /dev/null
+++ b/drivers/regulator/stpmic1_regulator.c
@@ -0,0 +1,436 @@
+// SPDX-License-Identifier: GPL-2.0
+// Copyright (C) STMicroelectronics 2018
+// Author: Pascal Paillet <p.paillet@st.com> for STMicroelectronics.
+
+#include <common.h>
+#include <init.h>
+#include <of_device.h>
+#include <regmap.h>
+#include <linux/regulator/of_regulator.h>
+#include <regulator.h>
+#include <linux/mfd/stpmic1.h>
+
+#include <dt-bindings/mfd/st,stpmic1.h>
+
+/**
+ * stpmic1 regulator description: this structure is used as driver data
+ * @desc: regulator framework description
+ * @mask_reset_reg: mask reset register address
+ * @mask_reset_mask: mask rank and mask reset register mask
+ * @icc_reg: icc register address
+ * @icc_mask: icc register mask
+ */
+struct stpmic1_regulator_cfg {
+ struct device_d *dev;
+ struct regulator_dev rdev;
+ struct regulator_desc desc;
+ u8 mask_reset_reg;
+ u8 mask_reset_mask;
+ u8 icc_reg;
+ u8 icc_mask;
+};
+
+enum {
+ STPMIC1_BUCK1 = 0,
+ STPMIC1_BUCK2 = 1,
+ STPMIC1_BUCK3 = 2,
+ STPMIC1_BUCK4 = 3,
+ STPMIC1_LDO1 = 4,
+ STPMIC1_LDO2 = 5,
+ STPMIC1_LDO3 = 6,
+ STPMIC1_LDO4 = 7,
+ STPMIC1_LDO5 = 8,
+ STPMIC1_LDO6 = 9,
+ STPMIC1_VREF_DDR = 10,
+ STPMIC1_BOOST = 11,
+ STPMIC1_VBUS_OTG = 12,
+ STPMIC1_SW_OUT = 13,
+};
+
+/* Enable time worst case is 5000mV/(2250uV/uS) */
+#define PMIC_ENABLE_TIME_US 2200
+
+static const struct regulator_linear_range buck1_ranges[] = {
+ REGULATOR_LINEAR_RANGE(725000, 0, 4, 0),
+ REGULATOR_LINEAR_RANGE(725000, 5, 36, 25000),
+ REGULATOR_LINEAR_RANGE(1500000, 37, 63, 0),
+};
+
+static const struct regulator_linear_range buck2_ranges[] = {
+ REGULATOR_LINEAR_RANGE(1000000, 0, 17, 0),
+ REGULATOR_LINEAR_RANGE(1050000, 18, 19, 0),
+ REGULATOR_LINEAR_RANGE(1100000, 20, 21, 0),
+ REGULATOR_LINEAR_RANGE(1150000, 22, 23, 0),
+ REGULATOR_LINEAR_RANGE(1200000, 24, 25, 0),
+ REGULATOR_LINEAR_RANGE(1250000, 26, 27, 0),
+ REGULATOR_LINEAR_RANGE(1300000, 28, 29, 0),
+ REGULATOR_LINEAR_RANGE(1350000, 30, 31, 0),
+ REGULATOR_LINEAR_RANGE(1400000, 32, 33, 0),
+ REGULATOR_LINEAR_RANGE(1450000, 34, 35, 0),
+ REGULATOR_LINEAR_RANGE(1500000, 36, 63, 0),
+};
+
+static const struct regulator_linear_range buck3_ranges[] = {
+ REGULATOR_LINEAR_RANGE(1000000, 0, 19, 0),
+ REGULATOR_LINEAR_RANGE(1100000, 20, 23, 0),
+ REGULATOR_LINEAR_RANGE(1200000, 24, 27, 0),
+ REGULATOR_LINEAR_RANGE(1300000, 28, 31, 0),
+ REGULATOR_LINEAR_RANGE(1400000, 32, 35, 0),
+ REGULATOR_LINEAR_RANGE(1500000, 36, 55, 100000),
+ REGULATOR_LINEAR_RANGE(3400000, 56, 63, 0),
+};
+
+static const struct regulator_linear_range buck4_ranges[] = {
+ REGULATOR_LINEAR_RANGE(600000, 0, 27, 25000),
+ REGULATOR_LINEAR_RANGE(1300000, 28, 29, 0),
+ REGULATOR_LINEAR_RANGE(1350000, 30, 31, 0),
+ REGULATOR_LINEAR_RANGE(1400000, 32, 33, 0),
+ REGULATOR_LINEAR_RANGE(1450000, 34, 35, 0),
+ REGULATOR_LINEAR_RANGE(1500000, 36, 60, 100000),
+ REGULATOR_LINEAR_RANGE(3900000, 61, 63, 0),
+};
+
+static const struct regulator_linear_range ldo1_ranges[] = {
+ REGULATOR_LINEAR_RANGE(1700000, 0, 7, 0),
+ REGULATOR_LINEAR_RANGE(1700000, 8, 24, 100000),
+ REGULATOR_LINEAR_RANGE(3300000, 25, 31, 0),
+};
+
+static const struct regulator_linear_range ldo2_ranges[] = {
+ REGULATOR_LINEAR_RANGE(1700000, 0, 7, 0),
+ REGULATOR_LINEAR_RANGE(1700000, 8, 24, 100000),
+ REGULATOR_LINEAR_RANGE(3300000, 25, 30, 0),
+};
+
+static const struct regulator_linear_range ldo3_ranges[] = {
+ REGULATOR_LINEAR_RANGE(1700000, 0, 7, 0),
+ REGULATOR_LINEAR_RANGE(1700000, 8, 24, 100000),
+ REGULATOR_LINEAR_RANGE(3300000, 25, 30, 0),
+ /* with index 31 LDO3 is in DDR mode */
+ REGULATOR_LINEAR_RANGE(500000, 31, 31, 0),
+};
+
+static const struct regulator_linear_range ldo5_ranges[] = {
+ REGULATOR_LINEAR_RANGE(1700000, 0, 7, 0),
+ REGULATOR_LINEAR_RANGE(1700000, 8, 30, 100000),
+ REGULATOR_LINEAR_RANGE(3900000, 31, 31, 0),
+};
+
+static const struct regulator_linear_range ldo6_ranges[] = {
+ REGULATOR_LINEAR_RANGE(900000, 0, 24, 100000),
+ REGULATOR_LINEAR_RANGE(3300000, 25, 31, 0),
+};
+
+static const struct regulator_ops stpmic1_ldo_ops = {
+ .list_voltage = regulator_list_voltage_linear_range,
+ .map_voltage = regulator_map_voltage_linear_range,
+ .is_enabled = regulator_is_enabled_regmap,
+ .enable = regulator_enable_regmap,
+ .disable = regulator_disable_regmap,
+ .set_voltage_sel = regulator_set_voltage_sel_regmap,
+};
+
+static const struct regulator_ops stpmic1_ldo3_ops = {
+ .list_voltage = regulator_list_voltage_linear_range,
+ .map_voltage = regulator_map_voltage_iterate,
+ .is_enabled = regulator_is_enabled_regmap,
+ .enable = regulator_enable_regmap,
+ .disable = regulator_disable_regmap,
+ .set_voltage_sel = regulator_set_voltage_sel_regmap,
+};
+
+static const struct regulator_ops stpmic1_ldo4_fixed_regul_ops = {
+ .is_enabled = regulator_is_enabled_regmap,
+ .enable = regulator_enable_regmap,
+ .disable = regulator_disable_regmap,
+};
+
+static const struct regulator_ops stpmic1_buck_ops = {
+ .list_voltage = regulator_list_voltage_linear_range,
+ .map_voltage = regulator_map_voltage_linear_range,
+ .is_enabled = regulator_is_enabled_regmap,
+ .enable = regulator_enable_regmap,
+ .disable = regulator_disable_regmap,
+ .set_voltage_sel = regulator_set_voltage_sel_regmap,
+};
+
+static const struct regulator_ops stpmic1_vref_ddr_ops = {
+ .is_enabled = regulator_is_enabled_regmap,
+ .enable = regulator_enable_regmap,
+ .disable = regulator_disable_regmap,
+};
+
+static const struct regulator_ops stpmic1_boost_regul_ops = {
+ .is_enabled = regulator_is_enabled_regmap,
+ .enable = regulator_enable_regmap,
+ .disable = regulator_disable_regmap,
+};
+
+static const struct regulator_ops stpmic1_switch_regul_ops = {
+ .is_enabled = regulator_is_enabled_regmap,
+ .enable = regulator_enable_regmap,
+ .disable = regulator_disable_regmap,
+};
+
+#define REG_LDO(ids, base) { \
+ .n_voltages = 32, \
+ .ops = &stpmic1_ldo_ops, \
+ .linear_ranges = base ## _ranges, \
+ .n_linear_ranges = ARRAY_SIZE(base ## _ranges), \
+ .vsel_reg = ids##_ACTIVE_CR, \
+ .vsel_mask = LDO_VOLTAGE_MASK, \
+ .enable_reg = ids##_ACTIVE_CR, \
+ .enable_mask = LDO_ENABLE_MASK, \
+ .enable_val = 1, \
+ .disable_val = 0, \
+}
+
+#define REG_LDO3(ids, base) { \
+ .n_voltages = 32, \
+ .ops = &stpmic1_ldo3_ops, \
+ .linear_ranges = ldo3_ranges, \
+ .n_linear_ranges = ARRAY_SIZE(ldo3_ranges), \
+ .vsel_reg = LDO3_ACTIVE_CR, \
+ .vsel_mask = LDO_VOLTAGE_MASK, \
+ .enable_reg = LDO3_ACTIVE_CR, \
+ .enable_mask = LDO_ENABLE_MASK, \
+ .enable_val = 1, \
+ .disable_val = 0, \
+}
+
+#define REG_LDO4(ids, base) { \
+ .n_voltages = 1, \
+ .ops = &stpmic1_ldo4_fixed_regul_ops, \
+ .min_uV = 3300000, \
+ .enable_reg = LDO4_ACTIVE_CR, \
+ .enable_mask = LDO_ENABLE_MASK, \
+ .enable_val = 1, \
+ .disable_val = 0, \
+}
+
+#define REG_BUCK(ids, base) { \
+ .ops = &stpmic1_buck_ops, \
+ .n_voltages = 64, \
+ .linear_ranges = base ## _ranges, \
+ .n_linear_ranges = ARRAY_SIZE(base ## _ranges), \
+ .vsel_reg = ids##_ACTIVE_CR, \
+ .vsel_mask = BUCK_VOLTAGE_MASK, \
+ .enable_reg = ids##_ACTIVE_CR, \
+ .enable_mask = BUCK_ENABLE_MASK, \
+ .enable_val = 1, \
+ .disable_val = 0, \
+}
+
+#define REG_VREF_DDR(ids, base) { \
+ .n_voltages = 1, \
+ .ops = &stpmic1_vref_ddr_ops, \
+ .min_uV = 500000, \
+ .enable_reg = VREF_DDR_ACTIVE_CR, \
+ .enable_mask = BUCK_ENABLE_MASK, \
+ .enable_val = 1, \
+ .disable_val = 0, \
+}
+
+#define REG_BOOST(ids, base) { \
+ .n_voltages = 1, \
+ .ops = &stpmic1_boost_regul_ops, \
+ .min_uV = 0, \
+ .enable_reg = BST_SW_CR, \
+ .enable_mask = BOOST_ENABLED, \
+ .enable_val = BOOST_ENABLED, \
+ .disable_val = 0, \
+}
+
+#define REG_VBUS_OTG(ids, base) { \
+ .n_voltages = 1, \
+ .ops = &stpmic1_switch_regul_ops, \
+ .min_uV = 0, \
+ .enable_reg = BST_SW_CR, \
+ .enable_mask = USBSW_OTG_SWITCH_ENABLED, \
+ .enable_val = USBSW_OTG_SWITCH_ENABLED, \
+ .disable_val = 0, \
+}
+
+#define REG_SW_OUT(ids, base) { \
+ .n_voltages = 1, \
+ .ops = &stpmic1_switch_regul_ops, \
+ .min_uV = 0, \
+ .enable_reg = BST_SW_CR, \
+ .enable_mask = SWIN_SWOUT_ENABLED, \
+ .enable_val = SWIN_SWOUT_ENABLED, \
+ .disable_val = 0, \
+}
+
+static struct stpmic1_regulator_cfg stpmic1_regulator_cfgs[] = {
+ [STPMIC1_BUCK1] = {
+ .desc = REG_BUCK(BUCK1, buck1),
+ .icc_reg = BUCKS_ICCTO_CR,
+ .icc_mask = BIT(0),
+ .mask_reset_reg = BUCKS_MASK_RESET_CR,
+ .mask_reset_mask = BIT(0),
+ },
+ [STPMIC1_BUCK2] = {
+ .desc = REG_BUCK(BUCK2, buck2),
+ .icc_reg = BUCKS_ICCTO_CR,
+ .icc_mask = BIT(1),
+ .mask_reset_reg = BUCKS_MASK_RESET_CR,
+ .mask_reset_mask = BIT(1),
+ },
+ [STPMIC1_BUCK3] = {
+ .desc = REG_BUCK(BUCK3, buck3),
+ .icc_reg = BUCKS_ICCTO_CR,
+ .icc_mask = BIT(2),
+ .mask_reset_reg = BUCKS_MASK_RESET_CR,
+ .mask_reset_mask = BIT(2),
+ },
+ [STPMIC1_BUCK4] = {
+ .desc = REG_BUCK(BUCK4, buck4),
+ .icc_reg = BUCKS_ICCTO_CR,
+ .icc_mask = BIT(3),
+ .mask_reset_reg = BUCKS_MASK_RESET_CR,
+ .mask_reset_mask = BIT(3),
+ },
+ [STPMIC1_LDO1] = {
+ .desc = REG_LDO(LDO1, ldo1),
+ .icc_reg = LDOS_ICCTO_CR,
+ .icc_mask = BIT(0),
+ .mask_reset_reg = LDOS_MASK_RESET_CR,
+ .mask_reset_mask = BIT(0),
+ },
+ [STPMIC1_LDO2] = {
+ .desc = REG_LDO(LDO2, ldo2),
+ .icc_reg = LDOS_ICCTO_CR,
+ .icc_mask = BIT(1),
+ .mask_reset_reg = LDOS_MASK_RESET_CR,
+ .mask_reset_mask = BIT(1),
+ },
+ [STPMIC1_LDO3] = {
+ .desc = REG_LDO3(LDO3, ldo3),
+ .icc_reg = LDOS_ICCTO_CR,
+ .icc_mask = BIT(2),
+ .mask_reset_reg = LDOS_MASK_RESET_CR,
+ .mask_reset_mask = BIT(2),
+ },
+ [STPMIC1_LDO4] = {
+ .desc = REG_LDO4(LDO4, ldo4),
+ .icc_reg = LDOS_ICCTO_CR,
+ .icc_mask = BIT(3),
+ .mask_reset_reg = LDOS_MASK_RESET_CR,
+ .mask_reset_mask = BIT(3),
+ },
+ [STPMIC1_LDO5] = {
+ .desc = REG_LDO(LDO5, ldo5),
+ .icc_reg = LDOS_ICCTO_CR,
+ .icc_mask = BIT(4),
+ .mask_reset_reg = LDOS_MASK_RESET_CR,
+ .mask_reset_mask = BIT(4),
+ },
+ [STPMIC1_LDO6] = {
+ .desc = REG_LDO(LDO6, ldo6),
+ .icc_reg = LDOS_ICCTO_CR,
+ .icc_mask = BIT(5),
+ .mask_reset_reg = LDOS_MASK_RESET_CR,
+ .mask_reset_mask = BIT(5),
+ },
+ [STPMIC1_VREF_DDR] = {
+ .desc = REG_VREF_DDR(VREF_DDR, vref_ddr),
+ .mask_reset_reg = LDOS_MASK_RESET_CR,
+ .mask_reset_mask = BIT(6),
+ },
+ [STPMIC1_BOOST] = {
+ .desc = REG_BOOST(BOOST, boost),
+ .icc_reg = BUCKS_ICCTO_CR,
+ .icc_mask = BIT(6),
+ },
+ [STPMIC1_VBUS_OTG] = {
+ .desc = REG_VBUS_OTG(VBUS_OTG, pwr_sw1),
+ .icc_reg = BUCKS_ICCTO_CR,
+ .icc_mask = BIT(4),
+ },
+ [STPMIC1_SW_OUT] = {
+ .desc = REG_SW_OUT(SW_OUT, pwr_sw2),
+ .icc_reg = BUCKS_ICCTO_CR,
+ .icc_mask = BIT(5),
+ },
+};
+
+#define MATCH(_name, _id) \
+ [STPMIC1_##_id] = { \
+ .name = #_name, \
+ .desc = &stpmic1_regulator_cfgs[STPMIC1_##_id].desc, \
+ }
+
+static struct of_regulator_match stpmic1_matches[] = {
+ MATCH(buck1, BUCK1),
+ MATCH(buck2, BUCK2),
+ MATCH(buck3, BUCK3),
+ MATCH(buck4, BUCK4),
+ MATCH(ldo1, LDO1),
+ MATCH(ldo2, LDO2),
+ MATCH(ldo3, LDO3),
+ MATCH(ldo4, LDO4),
+ MATCH(ldo5, LDO5),
+ MATCH(ldo6, LDO6),
+ MATCH(vref_ddr, VREF_DDR),
+ MATCH(boost, BOOST),
+ MATCH(pwr_sw1, VBUS_OTG),
+ MATCH(pwr_sw2, SW_OUT),
+};
+
+static int stpmic1_regulator_register(struct device_d *dev, int id,
+ struct of_regulator_match *match,
+ struct stpmic1_regulator_cfg *cfg)
+{
+ int ret;
+
+ cfg->dev = dev;
+ cfg->rdev.desc = &cfg->desc;
+ cfg->rdev.regmap = dev_get_regmap(dev->parent, NULL);
+ if (IS_ERR(cfg->rdev.regmap))
+ return PTR_ERR(cfg->rdev.regmap);
+
+ ret = of_regulator_register(&cfg->rdev, match->of_node);
+ if (ret) {
+ dev_err(dev, "failed to register %s regulator\n", match->name);
+ return ret;
+ }
+
+ dev_dbg(dev, "registered %s\n", match->name);
+
+ return 0;
+}
+
+static int stpmic1_regulator_probe(struct device_d *dev)
+{
+ int i, ret;
+
+ ret = of_regulator_match(dev, dev->device_node, stpmic1_matches,
+ ARRAY_SIZE(stpmic1_matches));
+ if (ret < 0) {
+ dev_err(dev, "Error in PMIC regulator device tree node");
+ return ret;
+ }
+
+ for (i = 0; i < ARRAY_SIZE(stpmic1_regulator_cfgs); i++) {
+ ret = stpmic1_regulator_register(dev, i, &stpmic1_matches[i],
+ &stpmic1_regulator_cfgs[i]);
+ if (ret < 0)
+ return ret;
+ }
+
+ dev_dbg(dev, "probed\n");
+
+ return 0;
+}
+
+static __maybe_unused const struct of_device_id stpmic1_regulator_of_match[] = {
+ { .compatible = "st,stpmic1-regulators" },
+ { /* sentinel */ },
+};
+
+static struct driver_d stpmic1_regulator_driver = {
+ .name = "stpmic1-regulator",
+ .probe = stpmic1_regulator_probe,
+ .of_compatible = DRV_OF_COMPAT(stpmic1_regulator_of_match),
+};
+device_platform_driver(stpmic1_regulator_driver);
diff --git a/drivers/serial/efi-stdio.c b/drivers/serial/efi-stdio.c
index 2ca89fa4f8..9e825181e6 100644
--- a/drivers/serial/efi-stdio.c
+++ b/drivers/serial/efi-stdio.c
@@ -26,6 +26,8 @@
#include <readkey.h>
#include <linux/ctype.h>
#include <efi/efi.h>
+#include <efi/efi-device.h>
+#include "efi-stdio.h"
#define EFI_SHIFT_STATE_VALID 0x80000000
#define EFI_RIGHT_CONTROL_PRESSED 0x00000004
@@ -71,6 +73,7 @@
struct efi_console_priv {
struct efi_simple_text_output_protocol *out;
struct efi_simple_input_interface *in;
+ struct efi_simple_text_input_ex_protocol *inex;
struct console_device cdev;
int lastkey;
u16 efi_console_buffer[CONFIG_CBSIZE];
@@ -105,35 +108,72 @@ static struct efi_ctrlkey ctrlkeys[] = {
{ 0x17, 27 /* escape key */ },
};
+static int xlate_keypress(struct efi_input_key *k)
+{
+ int i;
+
+ /* 32 bit modifier keys + 16 bit scan code + 16 bit unicode */
+ for (i = 0; i < ARRAY_SIZE(ctrlkeys); i++) {
+ if (ctrlkeys[i].scan_code == k->scan_code)
+ return ctrlkeys[i].bb_key;
+
+ }
+
+ return k->unicode_char & 0xff;
+}
+
static int efi_read_key(struct efi_console_priv *priv, bool wait)
{
unsigned long index;
efi_status_t efiret;
- struct efi_input_key k;
- int i;
+ struct efi_key_data kd;
/* wait until key is pressed */
if (wait)
BS->wait_for_event(1, priv->in->wait_for_key, &index);
- efiret = priv->in->read_key_stroke(efi_sys_table->con_in, &k);
- if (EFI_ERROR(efiret))
- return -efi_errno(efiret);
+ if (priv->inex) {
+ efiret = priv->inex->read_key_stroke_ex(priv->inex, &kd);
- /* 32 bit modifier keys + 16 bit scan code + 16 bit unicode */
- for (i = 0; i < ARRAY_SIZE(ctrlkeys); i++) {
- if (ctrlkeys[i].scan_code == k.scan_code)
- return ctrlkeys[i].bb_key;
+ if (efiret == EFI_NOT_READY)
+ return -EAGAIN;
+
+ if (!EFI_ERROR(efiret)) {
+ if ((kd.state.shift_state & EFI_SHIFT_STATE_VALID) &&
+ (kd.state.shift_state & EFI_CONTROL_PRESSED)) {
+ int ch = tolower(kd.key.unicode_char & 0xff);
+
+ if (isalpha(ch))
+ return CHAR_CTRL(ch);
+ if (ch == '\0') /* ctrl is pressed on its own */
+ return -EAGAIN;
+ }
+
+ if (kd.key.unicode_char || kd.key.scan_code)
+ return xlate_keypress(&kd.key);
+ /* Some broken firmwares offer simple_text_input_ex_protocol,
+ * but never handle any key. Treat those as if
+ * read_key_stroke_ex failed and fall through
+ * to the basic simple_text_input_protocol.
+ */
+ dev_dbg(priv->cdev.dev, "Falling back to simple_text_input_protocol\n");
+ }
}
- return k.unicode_char & 0xff;
+ efiret = priv->in->read_key_stroke(priv->in, &kd.key);
+
+ if (EFI_ERROR(efiret))
+ return -efi_errno(efiret);
+
+ return xlate_keypress(&kd.key);
}
static void efi_console_putc(struct console_device *cdev, char c)
{
uint16_t str[2] = {};
- struct efi_simple_text_output_protocol *con_out = efi_sys_table->con_out;
+ struct efi_console_priv *priv = to_efi(cdev);
+ struct efi_simple_text_output_protocol *con_out = priv->out;
str[0] = c;
@@ -331,8 +371,12 @@ static void efi_set_mode(struct efi_console_priv *priv)
static int efi_console_probe(struct device_d *dev)
{
+ efi_guid_t inex_guid = EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL_GUID;
+ struct efi_simple_text_input_ex_protocol *inex;
struct console_device *cdev;
struct efi_console_priv *priv;
+ efi_status_t efiret;
+
int i;
priv = xzalloc(sizeof(*priv));
@@ -340,6 +384,18 @@ static int efi_console_probe(struct device_d *dev)
priv->out = efi_sys_table->con_out;
priv->in = efi_sys_table->con_in;
+ efiret = BS->open_protocol((void *)efi_sys_table->con_in_handle,
+ &inex_guid,
+ (void **)&inex,
+ efi_parent_image,
+ 0,
+ EFI_OPEN_PROTOCOL_GET_PROTOCOL);
+
+ if (!EFI_ERROR(efiret)) {
+ priv->inex = inex;
+ dev_dbg(dev, "Using simple_text_input_ex_protocol\n");
+ }
+
priv->current_color = EFI_WHITE;
efi_set_mode(priv);
diff --git a/drivers/serial/efi-stdio.h b/drivers/serial/efi-stdio.h
new file mode 100644
index 0000000000..1fa417c706
--- /dev/null
+++ b/drivers/serial/efi-stdio.h
@@ -0,0 +1,58 @@
+#ifndef EFI_STDIO_H_
+#define EFI_STDIO_H_
+
+#include <efi.h>
+
+struct efi_simple_text_input_ex_protocol;
+
+typedef efi_status_t (EFIAPI *efi_input_reset_ex)(
+ struct efi_simple_text_input_ex_protocol *this,
+ efi_bool_t extended_verification
+);
+
+struct efi_key_state {
+ u32 shift_state;
+ u8 toggle_state;
+};
+
+struct efi_key_data {
+ struct efi_input_key key;
+ struct efi_key_state state;
+};
+
+typedef efi_status_t (EFIAPI *efi_input_read_key_ex)(
+ struct efi_simple_text_input_ex_protocol *this,
+ struct efi_key_data *keydata
+);
+
+typedef efi_status_t (EFIAPI *efi_set_state)(
+ struct efi_simple_text_input_ex_protocol *this,
+ u8 *key_toggle_state
+);
+
+typedef efi_status_t (EFIAPI *efi_key_notify_function)(
+ struct efi_key_data *keydata
+);
+
+typedef efi_status_t (EFIAPI *efi_register_keystroke_notify)(
+ struct efi_simple_text_input_ex_protocol *this,
+ struct efi_key_data keydata,
+ efi_key_notify_function key_notification_function,
+ void **notify_handle
+);
+
+typedef efi_status_t (EFIAPI *efi_unregister_keystroke_notify)(
+ struct efi_simple_text_input_ex_protocol *this,
+ void *notification_handle
+);
+
+struct efi_simple_text_input_ex_protocol {
+ efi_input_reset_ex reset;
+ efi_input_read_key_ex read_key_stroke_ex;
+ void *wait_for_key_ex;
+ efi_set_state set_state;
+ efi_register_keystroke_notify register_key_notify;
+ efi_unregister_keystroke_notify unregister_key_notify;
+};
+
+#endif
diff --git a/drivers/serial/serial_cadence.c b/drivers/serial/serial_cadence.c
index 0501c400b1..6454888e3c 100644
--- a/drivers/serial/serial_cadence.c
+++ b/drivers/serial/serial_cadence.c
@@ -199,7 +199,7 @@ static void cadence_serial_flush(struct console_device *cdev)
struct cadence_serial_priv, cdev);
while ((readl(priv->regs + CADENCE_UART_CHANNEL_STS) &
- CADENCE_STS_TEMPTY) != 0)
+ CADENCE_STS_TEMPTY) == 0)
;
}
diff --git a/drivers/usb/storage/usb.c b/drivers/usb/storage/usb.c
index 63d624e91b..e0ef4f5ef3 100644
--- a/drivers/usb/storage/usb.c
+++ b/drivers/usb/storage/usb.c
@@ -87,8 +87,7 @@ static int usb_stor_transport(struct us_blk_dev *usb_blkdev,
struct device_d *dev = &us->pusb_dev->dev;
int i, ret;
-
- for (i = 0; i < retries; i++) {
+ for (i = 0; i <= retries; i++) {
dev_dbg(dev, "%s\n", usb_stor_opcode_name(cmd[0]));
ret = us->transport(usb_blkdev, cmd, cmdlen, data, datalen);
dev_dbg(dev, "%s returns %d\n", usb_stor_opcode_name(cmd[0]),
@@ -105,6 +104,8 @@ static int usb_stor_transport(struct us_blk_dev *usb_blkdev,
mdelay(request_sense_delay_ms);
}
+ dev_dbg(dev, "Retried %s %d times, and failed.\n", usb_stor_opcode_name(cmd[0]), retries);
+
return -EIO;
}
@@ -194,7 +195,7 @@ static int usb_stor_io_10(struct us_blk_dev *usb_blkdev, u8 opcode,
put_unaligned_be16(blocks, &cmd[7]);
return usb_stor_transport(usb_blkdev, cmd, sizeof(cmd), data,
- blocks * SECTOR_SIZE, 2, 0);
+ blocks * SECTOR_SIZE, 10, 0);
}
/***********************************************************************
diff --git a/drivers/watchdog/stpmic1_wdt.c b/drivers/watchdog/stpmic1_wdt.c
index f79b7e8c27..9b7a586387 100644
--- a/drivers/watchdog/stpmic1_wdt.c
+++ b/drivers/watchdog/stpmic1_wdt.c
@@ -169,7 +169,10 @@ static int stpmic1_wdt_probe(struct device_d *dev)
int ret;
wdt = xzalloc(sizeof(*wdt));
- wdt->regmap = dev->parent->priv;
+
+ wdt->regmap = dev_get_regmap(dev->parent, NULL);
+ if (IS_ERR(wdt->regmap))
+ return PTR_ERR(wdt->regmap);
wdd = &wdt->wdd;
wdd->hwdev = dev;
diff --git a/dts/Bindings/arm/rockchip.yaml b/dts/Bindings/arm/rockchip.yaml
index c82c5e57d4..9c7e70335a 100644
--- a/dts/Bindings/arm/rockchip.yaml
+++ b/dts/Bindings/arm/rockchip.yaml
@@ -496,12 +496,12 @@ properties:
- description: Theobroma Systems RK3368-uQ7 with Haikou baseboard
items:
- - const: tsd,rk3368-uq7-haikou
+ - const: tsd,rk3368-lion-haikou
- const: rockchip,rk3368
- description: Theobroma Systems RK3399-Q7 with Haikou baseboard
items:
- - const: tsd,rk3399-q7-haikou
+ - const: tsd,rk3399-puma-haikou
- const: rockchip,rk3399
- description: Tronsmart Orion R68 Meta
diff --git a/dts/Bindings/interrupt-controller/atmel,aic.txt b/dts/Bindings/interrupt-controller/atmel,aic.txt
index f4c5d34c41..7079d44bf3 100644
--- a/dts/Bindings/interrupt-controller/atmel,aic.txt
+++ b/dts/Bindings/interrupt-controller/atmel,aic.txt
@@ -1,8 +1,11 @@
* Advanced Interrupt Controller (AIC)
Required properties:
-- compatible: Should be "atmel,<chip>-aic"
- <chip> can be "at91rm9200", "sama5d2", "sama5d3" or "sama5d4"
+- compatible: Should be:
+ - "atmel,<chip>-aic" where <chip> can be "at91rm9200", "sama5d2",
+ "sama5d3" or "sama5d4"
+ - "microchip,<chip>-aic" where <chip> can be "sam9x60"
+
- interrupt-controller: Identifies the node as an interrupt controller.
- #interrupt-cells: The number of cells to define the interrupts. It should be 3.
The first cell is the IRQ number (aka "Peripheral IDentifier" on datasheet).
diff --git a/dts/Bindings/media/allwinner,sun4i-a10-csi.yaml b/dts/Bindings/media/allwinner,sun4i-a10-csi.yaml
index 27f38eed38..d3e423fcb6 100644
--- a/dts/Bindings/media/allwinner,sun4i-a10-csi.yaml
+++ b/dts/Bindings/media/allwinner,sun4i-a10-csi.yaml
@@ -1,7 +1,7 @@
# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
%YAML 1.2
---
-$id: http://devicetree.org/schemas/arm/allwinner,sun4i-a10-csi.yaml#
+$id: http://devicetree.org/schemas/media/allwinner,sun4i-a10-csi.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Allwinner A10 CMOS Sensor Interface (CSI) Device Tree Bindings
@@ -27,14 +27,12 @@ properties:
clocks:
items:
- description: The CSI interface clock
- - description: The CSI module clock
- description: The CSI ISP clock
- description: The CSI DRAM clock
clock-names:
items:
- const: bus
- - const: mod
- const: isp
- const: ram
@@ -89,9 +87,8 @@ examples:
compatible = "allwinner,sun7i-a20-csi0";
reg = <0x01c09000 0x1000>;
interrupts = <GIC_SPI 42 IRQ_TYPE_LEVEL_HIGH>;
- clocks = <&ccu CLK_AHB_CSI0>, <&ccu CLK_CSI0>,
- <&ccu CLK_CSI_SCLK>, <&ccu CLK_DRAM_CSI0>;
- clock-names = "bus", "mod", "isp", "ram";
+ clocks = <&ccu CLK_AHB_CSI0>, <&ccu CLK_CSI_SCLK>, <&ccu CLK_DRAM_CSI0>;
+ clock-names = "bus", "isp", "ram";
resets = <&ccu RST_CSI0>;
port {
diff --git a/dts/Bindings/pinctrl/aspeed,ast2600-pinctrl.yaml b/dts/Bindings/pinctrl/aspeed,ast2600-pinctrl.yaml
index f83d888176..064b7dfc42 100644
--- a/dts/Bindings/pinctrl/aspeed,ast2600-pinctrl.yaml
+++ b/dts/Bindings/pinctrl/aspeed,ast2600-pinctrl.yaml
@@ -33,13 +33,13 @@ patternProperties:
allOf:
- $ref: "/schemas/types.yaml#/definitions/string"
- enum: [ ADC0, ADC1, ADC10, ADC11, ADC12, ADC13, ADC14, ADC15,
- ADC2, ADC3, ADC4, ADC5, ADC6, ADC7, ADC8, ADC9, BMCINT, ESPI,
- ESPIALT, FSI1, FSI2, FWSPIABR, FWSPID, FWSPIWP, GPIT0, GPIT1,
- GPIT2, GPIT3, GPIT4, GPIT5, GPIT6, GPIT7, GPIU0, GPIU1, GPIU2,
- GPIU3, GPIU4, GPIU5, GPIU6, GPIU7, I2C1, I2C10, I2C11, I2C12,
- I2C13, I2C14, I2C15, I2C16, I2C2, I2C3, I2C4, I2C5, I2C6, I2C7,
- I2C8, I2C9, I3C3, I3C4, I3C5, I3C6, JTAGM, LHPD, LHSIRQ, LPC,
- LPCHC, LPCPD, LPCPME, LPCSMI, LSIRQ, MACLINK1, MACLINK2,
+ ADC2, ADC3, ADC4, ADC5, ADC6, ADC7, ADC8, ADC9, BMCINT, EMMC,
+ ESPI, ESPIALT, FSI1, FSI2, FWSPIABR, FWSPID, FWSPIWP, GPIT0,
+ GPIT1, GPIT2, GPIT3, GPIT4, GPIT5, GPIT6, GPIT7, GPIU0, GPIU1,
+ GPIU2, GPIU3, GPIU4, GPIU5, GPIU6, GPIU7, I2C1, I2C10, I2C11,
+ I2C12, I2C13, I2C14, I2C15, I2C16, I2C2, I2C3, I2C4, I2C5, I2C6,
+ I2C7, I2C8, I2C9, I3C3, I3C4, I3C5, I3C6, JTAGM, LHPD, LHSIRQ,
+ LPC, LPCHC, LPCPD, LPCPME, LPCSMI, LSIRQ, MACLINK1, MACLINK2,
MACLINK3, MACLINK4, MDIO1, MDIO2, MDIO3, MDIO4, NCTS1, NCTS2,
NCTS3, NCTS4, NDCD1, NDCD2, NDCD3, NDCD4, NDSR1, NDSR2, NDSR3,
NDSR4, NDTR1, NDTR2, NDTR3, NDTR4, NRI1, NRI2, NRI3, NRI4, NRTS1,
@@ -48,47 +48,45 @@ patternProperties:
PWM8, PWM9, RGMII1, RGMII2, RGMII3, RGMII4, RMII1, RMII2, RMII3,
RMII4, RXD1, RXD2, RXD3, RXD4, SALT1, SALT10, SALT11, SALT12,
SALT13, SALT14, SALT15, SALT16, SALT2, SALT3, SALT4, SALT5,
- SALT6, SALT7, SALT8, SALT9, SD1, SD2, SD3, SD3DAT4, SD3DAT5,
- SD3DAT6, SD3DAT7, SGPM1, SGPS1, SIOONCTRL, SIOPBI, SIOPBO,
- SIOPWREQ, SIOPWRGD, SIOS3, SIOS5, SIOSCI, SPI1, SPI1ABR, SPI1CS1,
- SPI1WP, SPI2, SPI2CS1, SPI2CS2, TACH0, TACH1, TACH10, TACH11,
- TACH12, TACH13, TACH14, TACH15, TACH2, TACH3, TACH4, TACH5,
- TACH6, TACH7, TACH8, TACH9, THRU0, THRU1, THRU2, THRU3, TXD1,
- TXD2, TXD3, TXD4, UART10, UART11, UART12, UART13, UART6, UART7,
- UART8, UART9, VB, VGAHS, VGAVS, WDTRST1, WDTRST2, WDTRST3,
- WDTRST4, ]
+ SALT6, SALT7, SALT8, SALT9, SD1, SD2, SGPM1, SGPS1, SIOONCTRL,
+ SIOPBI, SIOPBO, SIOPWREQ, SIOPWRGD, SIOS3, SIOS5, SIOSCI, SPI1,
+ SPI1ABR, SPI1CS1, SPI1WP, SPI2, SPI2CS1, SPI2CS2, TACH0, TACH1,
+ TACH10, TACH11, TACH12, TACH13, TACH14, TACH15, TACH2, TACH3,
+ TACH4, TACH5, TACH6, TACH7, TACH8, TACH9, THRU0, THRU1, THRU2,
+ THRU3, TXD1, TXD2, TXD3, TXD4, UART10, UART11, UART12, UART13,
+ UART6, UART7, UART8, UART9, VB, VGAHS, VGAVS, WDTRST1, WDTRST2,
+ WDTRST3, WDTRST4, ]
groups:
allOf:
- $ref: "/schemas/types.yaml#/definitions/string"
- enum: [ ADC0, ADC1, ADC10, ADC11, ADC12, ADC13, ADC14, ADC15,
- ADC2, ADC3, ADC4, ADC5, ADC6, ADC7, ADC8, ADC9, BMCINT, ESPI,
- ESPIALT, FSI1, FSI2, FWSPIABR, FWSPID, FWQSPID, FWSPIWP, GPIT0,
- GPIT1, GPIT2, GPIT3, GPIT4, GPIT5, GPIT6, GPIT7, GPIU0, GPIU1,
- GPIU2, GPIU3, GPIU4, GPIU5, GPIU6, GPIU7, HVI3C3, HVI3C4, I2C1,
- I2C10, I2C11, I2C12, I2C13, I2C14, I2C15, I2C16, I2C2, I2C3,
- I2C4, I2C5, I2C6, I2C7, I2C8, I2C9, I3C3, I3C4, I3C5, I3C6,
- JTAGM, LHPD, LHSIRQ, LPC, LPCHC, LPCPD, LPCPME, LPCSMI, LSIRQ,
- MACLINK1, MACLINK2, MACLINK3, MACLINK4, MDIO1, MDIO2, MDIO3,
- MDIO4, NCTS1, NCTS2, NCTS3, NCTS4, NDCD1, NDCD2, NDCD3, NDCD4,
- NDSR1, NDSR2, NDSR3, NDSR4, NDTR1, NDTR2, NDTR3, NDTR4, NRI1,
- NRI2, NRI3, NRI4, NRTS1, NRTS2, NRTS3, NRTS4, OSCCLK, PEWAKE,
- PWM0, PWM1, PWM10G0, PWM10G1, PWM11G0, PWM11G1, PWM12G0, PWM12G1,
- PWM13G0, PWM13G1, PWM14G0, PWM14G1, PWM15G0, PWM15G1, PWM2, PWM3,
- PWM4, PWM5, PWM6, PWM7, PWM8G0, PWM8G1, PWM9G0, PWM9G1, QSPI1,
- QSPI2, RGMII1, RGMII2, RGMII3, RGMII4, RMII1, RMII2, RMII3,
- RMII4, RXD1, RXD2, RXD3, RXD4, SALT1, SALT10G0, SALT10G1,
- SALT11G0, SALT11G1, SALT12G0, SALT12G1, SALT13G0, SALT13G1,
- SALT14G0, SALT14G1, SALT15G0, SALT15G1, SALT16G0, SALT16G1,
- SALT2, SALT3, SALT4, SALT5, SALT6, SALT7, SALT8, SALT9G0,
- SALT9G1, SD1, SD2, SD3, SD3DAT4, SD3DAT5, SD3DAT6, SD3DAT7,
- SGPM1, SGPS1, SIOONCTRL, SIOPBI, SIOPBO, SIOPWREQ, SIOPWRGD,
- SIOS3, SIOS5, SIOSCI, SPI1, SPI1ABR, SPI1CS1, SPI1WP, SPI2,
- SPI2CS1, SPI2CS2, TACH0, TACH1, TACH10, TACH11, TACH12, TACH13,
- TACH14, TACH15, TACH2, TACH3, TACH4, TACH5, TACH6, TACH7, TACH8,
- TACH9, THRU0, THRU1, THRU2, THRU3, TXD1, TXD2, TXD3, TXD4,
- UART10, UART11, UART12G0, UART12G1, UART13G0, UART13G1, UART6,
- UART7, UART8, UART9, VB, VGAHS, VGAVS, WDTRST1, WDTRST2, WDTRST3,
- WDTRST4, ]
+ ADC2, ADC3, ADC4, ADC5, ADC6, ADC7, ADC8, ADC9, BMCINT, EMMCG1,
+ EMMCG4, EMMCG8, ESPI, ESPIALT, FSI1, FSI2, FWSPIABR, FWSPID,
+ FWQSPID, FWSPIWP, GPIT0, GPIT1, GPIT2, GPIT3, GPIT4, GPIT5,
+ GPIT6, GPIT7, GPIU0, GPIU1, GPIU2, GPIU3, GPIU4, GPIU5, GPIU6,
+ GPIU7, HVI3C3, HVI3C4, I2C1, I2C10, I2C11, I2C12, I2C13, I2C14,
+ I2C15, I2C16, I2C2, I2C3, I2C4, I2C5, I2C6, I2C7, I2C8, I2C9,
+ I3C3, I3C4, I3C5, I3C6, JTAGM, LHPD, LHSIRQ, LPC, LPCHC, LPCPD,
+ LPCPME, LPCSMI, LSIRQ, MACLINK1, MACLINK2, MACLINK3, MACLINK4,
+ MDIO1, MDIO2, MDIO3, MDIO4, NCTS1, NCTS2, NCTS3, NCTS4, NDCD1,
+ NDCD2, NDCD3, NDCD4, NDSR1, NDSR2, NDSR3, NDSR4, NDTR1, NDTR2,
+ NDTR3, NDTR4, NRI1, NRI2, NRI3, NRI4, NRTS1, NRTS2, NRTS3, NRTS4,
+ OSCCLK, PEWAKE, PWM0, PWM1, PWM10G0, PWM10G1, PWM11G0, PWM11G1,
+ PWM12G0, PWM12G1, PWM13G0, PWM13G1, PWM14G0, PWM14G1, PWM15G0,
+ PWM15G1, PWM2, PWM3, PWM4, PWM5, PWM6, PWM7, PWM8G0, PWM8G1,
+ PWM9G0, PWM9G1, QSPI1, QSPI2, RGMII1, RGMII2, RGMII3, RGMII4,
+ RMII1, RMII2, RMII3, RMII4, RXD1, RXD2, RXD3, RXD4, SALT1,
+ SALT10G0, SALT10G1, SALT11G0, SALT11G1, SALT12G0, SALT12G1,
+ SALT13G0, SALT13G1, SALT14G0, SALT14G1, SALT15G0, SALT15G1,
+ SALT16G0, SALT16G1, SALT2, SALT3, SALT4, SALT5, SALT6, SALT7,
+ SALT8, SALT9G0, SALT9G1, SD1, SD2, SD3, SGPM1, SGPS1, SIOONCTRL,
+ SIOPBI, SIOPBO, SIOPWREQ, SIOPWRGD, SIOS3, SIOS5, SIOSCI, SPI1,
+ SPI1ABR, SPI1CS1, SPI1WP, SPI2, SPI2CS1, SPI2CS2, TACH0, TACH1,
+ TACH10, TACH11, TACH12, TACH13, TACH14, TACH15, TACH2, TACH3,
+ TACH4, TACH5, TACH6, TACH7, TACH8, TACH9, THRU0, THRU1, THRU2,
+ THRU3, TXD1, TXD2, TXD3, TXD4, UART10, UART11, UART12G0,
+ UART12G1, UART13G0, UART13G1, UART6, UART7, UART8, UART9, VB,
+ VGAHS, VGAVS, WDTRST1, WDTRST2, WDTRST3, WDTRST4, ]
required:
- compatible
diff --git a/dts/Bindings/regulator/fixed-regulator.yaml b/dts/Bindings/regulator/fixed-regulator.yaml
index a78150c47a..f324169681 100644
--- a/dts/Bindings/regulator/fixed-regulator.yaml
+++ b/dts/Bindings/regulator/fixed-regulator.yaml
@@ -30,8 +30,8 @@ if:
properties:
compatible:
enum:
- - const: regulator-fixed
- - const: regulator-fixed-clock
+ - regulator-fixed
+ - regulator-fixed-clock
regulator-name: true
diff --git a/dts/Bindings/riscv/cpus.yaml b/dts/Bindings/riscv/cpus.yaml
index b261a3015f..04819ad379 100644
--- a/dts/Bindings/riscv/cpus.yaml
+++ b/dts/Bindings/riscv/cpus.yaml
@@ -24,15 +24,17 @@ description: |
properties:
compatible:
- items:
- - enum:
- - sifive,rocket0
- - sifive,e5
- - sifive,e51
- - sifive,u54-mc
- - sifive,u54
- - sifive,u5
- - const: riscv
+ oneOf:
+ - items:
+ - enum:
+ - sifive,rocket0
+ - sifive,e5
+ - sifive,e51
+ - sifive,u54-mc
+ - sifive,u54
+ - sifive,u5
+ - const: riscv
+ - const: riscv # Simulator only
description:
Identifies that the hart uses the RISC-V instruction set
and identifies the type of the hart.
@@ -66,12 +68,8 @@ properties:
insensitive, letters in the riscv,isa string must be all
lowercase to simplify parsing.
- timebase-frequency:
- type: integer
- minimum: 1
- description:
- Specifies the clock frequency of the system timer in Hz.
- This value is common to all harts on a single system image.
+ # RISC-V requires 'timebase-frequency' in /cpus, so disallow it here
+ timebase-frequency: false
interrupt-controller:
type: object
@@ -93,7 +91,6 @@ properties:
required:
- riscv,isa
- - timebase-frequency
- interrupt-controller
examples:
diff --git a/dts/src/arc/hsdk.dts b/dts/src/arc/hsdk.dts
index bfc7f5f5d6..9acbeba832 100644
--- a/dts/src/arc/hsdk.dts
+++ b/dts/src/arc/hsdk.dts
@@ -65,6 +65,14 @@
clock-frequency = <33333333>;
};
+ reg_5v0: regulator-5v0 {
+ compatible = "regulator-fixed";
+
+ regulator-name = "5v0-supply";
+ regulator-min-microvolt = <5000000>;
+ regulator-max-microvolt = <5000000>;
+ };
+
cpu_intc: cpu-interrupt-controller {
compatible = "snps,archs-intc";
interrupt-controller;
@@ -264,6 +272,21 @@
clocks = <&input_clk>;
cs-gpios = <&creg_gpio 0 GPIO_ACTIVE_LOW>,
<&creg_gpio 1 GPIO_ACTIVE_LOW>;
+
+ spi-flash@0 {
+ compatible = "sst26wf016b", "jedec,spi-nor";
+ reg = <0>;
+ #address-cells = <1>;
+ #size-cells = <1>;
+ spi-max-frequency = <4000000>;
+ };
+
+ adc@1 {
+ compatible = "ti,adc108s102";
+ reg = <1>;
+ vref-supply = <&reg_5v0>;
+ spi-max-frequency = <1000000>;
+ };
};
creg_gpio: gpio@14b0 {
diff --git a/dts/src/arm/am3874-iceboard.dts b/dts/src/arm/am3874-iceboard.dts
index 883fb85135..1b4b2b0500 100644
--- a/dts/src/arm/am3874-iceboard.dts
+++ b/dts/src/arm/am3874-iceboard.dts
@@ -111,13 +111,13 @@
reg = <0x70>;
#address-cells = <1>;
#size-cells = <0>;
+ i2c-mux-idle-disconnect;
i2c@0 {
/* FMC A */
#address-cells = <1>;
#size-cells = <0>;
reg = <0>;
- i2c-mux-idle-disconnect;
};
i2c@1 {
@@ -125,7 +125,6 @@
#address-cells = <1>;
#size-cells = <0>;
reg = <1>;
- i2c-mux-idle-disconnect;
};
i2c@2 {
@@ -133,7 +132,6 @@
#address-cells = <1>;
#size-cells = <0>;
reg = <2>;
- i2c-mux-idle-disconnect;
};
i2c@3 {
@@ -141,7 +139,6 @@
#address-cells = <1>;
#size-cells = <0>;
reg = <3>;
- i2c-mux-idle-disconnect;
};
i2c@4 {
@@ -149,14 +146,12 @@
#address-cells = <1>;
#size-cells = <0>;
reg = <4>;
- i2c-mux-idle-disconnect;
};
i2c@5 {
#address-cells = <1>;
#size-cells = <0>;
reg = <5>;
- i2c-mux-idle-disconnect;
ina230@40 { compatible = "ti,ina230"; reg = <0x40>; shunt-resistor = <5000>; };
ina230@41 { compatible = "ti,ina230"; reg = <0x41>; shunt-resistor = <5000>; };
@@ -182,14 +177,12 @@
#address-cells = <1>;
#size-cells = <0>;
reg = <6>;
- i2c-mux-idle-disconnect;
};
i2c@7 {
#address-cells = <1>;
#size-cells = <0>;
reg = <7>;
- i2c-mux-idle-disconnect;
u41: pca9575@20 {
compatible = "nxp,pca9575";
diff --git a/dts/src/arm/bcm2835-rpi-zero-w.dts b/dts/src/arm/bcm2835-rpi-zero-w.dts
index 09a088f985..b75af21069 100644
--- a/dts/src/arm/bcm2835-rpi-zero-w.dts
+++ b/dts/src/arm/bcm2835-rpi-zero-w.dts
@@ -113,6 +113,7 @@
#address-cells = <1>;
#size-cells = <0>;
pinctrl-0 = <&emmc_gpio34 &gpclk2_gpio43>;
+ bus-width = <4>;
mmc-pwrseq = <&wifi_pwrseq>;
non-removable;
status = "okay";
diff --git a/dts/src/arm/bcm2837-rpi-cm3.dtsi b/dts/src/arm/bcm2837-rpi-cm3.dtsi
index 7c3cb7ece6..925cb37c22 100644
--- a/dts/src/arm/bcm2837-rpi-cm3.dtsi
+++ b/dts/src/arm/bcm2837-rpi-cm3.dtsi
@@ -9,6 +9,14 @@
reg = <0 0x40000000>;
};
+ leds {
+ /*
+ * Since there is no upstream GPIO driver yet,
+ * remove the incomplete node.
+ */
+ /delete-node/ act;
+ };
+
reg_3v3: fixed-regulator {
compatible = "regulator-fixed";
regulator-name = "3V3";
diff --git a/dts/src/arm/imx6-logicpd-som.dtsi b/dts/src/arm/imx6-logicpd-som.dtsi
index 7ceae35732..547fb141ec 100644
--- a/dts/src/arm/imx6-logicpd-som.dtsi
+++ b/dts/src/arm/imx6-logicpd-som.dtsi
@@ -207,6 +207,10 @@
vin-supply = <&sw1c_reg>;
};
+&snvs_poweroff {
+ status = "okay";
+};
+
&iomuxc {
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_hog>;
diff --git a/dts/src/arm/imx7s.dtsi b/dts/src/arm/imx7s.dtsi
index 710f850e78..e2e604d6ba 100644
--- a/dts/src/arm/imx7s.dtsi
+++ b/dts/src/arm/imx7s.dtsi
@@ -448,7 +448,7 @@
compatible = "fsl,imx7d-gpt", "fsl,imx6sx-gpt";
reg = <0x302d0000 0x10000>;
interrupts = <GIC_SPI 55 IRQ_TYPE_LEVEL_HIGH>;
- clocks = <&clks IMX7D_CLK_DUMMY>,
+ clocks = <&clks IMX7D_GPT1_ROOT_CLK>,
<&clks IMX7D_GPT1_ROOT_CLK>;
clock-names = "ipg", "per";
};
@@ -457,7 +457,7 @@
compatible = "fsl,imx7d-gpt", "fsl,imx6sx-gpt";
reg = <0x302e0000 0x10000>;
interrupts = <GIC_SPI 54 IRQ_TYPE_LEVEL_HIGH>;
- clocks = <&clks IMX7D_CLK_DUMMY>,
+ clocks = <&clks IMX7D_GPT2_ROOT_CLK>,
<&clks IMX7D_GPT2_ROOT_CLK>;
clock-names = "ipg", "per";
status = "disabled";
@@ -467,7 +467,7 @@
compatible = "fsl,imx7d-gpt", "fsl,imx6sx-gpt";
reg = <0x302f0000 0x10000>;
interrupts = <GIC_SPI 53 IRQ_TYPE_LEVEL_HIGH>;
- clocks = <&clks IMX7D_CLK_DUMMY>,
+ clocks = <&clks IMX7D_GPT3_ROOT_CLK>,
<&clks IMX7D_GPT3_ROOT_CLK>;
clock-names = "ipg", "per";
status = "disabled";
@@ -477,7 +477,7 @@
compatible = "fsl,imx7d-gpt", "fsl,imx6sx-gpt";
reg = <0x30300000 0x10000>;
interrupts = <GIC_SPI 52 IRQ_TYPE_LEVEL_HIGH>;
- clocks = <&clks IMX7D_CLK_DUMMY>,
+ clocks = <&clks IMX7D_GPT4_ROOT_CLK>,
<&clks IMX7D_GPT4_ROOT_CLK>;
clock-names = "ipg", "per";
status = "disabled";
diff --git a/dts/src/arm/logicpd-torpedo-som.dtsi b/dts/src/arm/logicpd-torpedo-som.dtsi
index 3fdd0a72f8..506b118e51 100644
--- a/dts/src/arm/logicpd-torpedo-som.dtsi
+++ b/dts/src/arm/logicpd-torpedo-som.dtsi
@@ -192,3 +192,7 @@
&twl_gpio {
ti,use-leds;
};
+
+&twl_keypad {
+ status = "disabled";
+};
diff --git a/dts/src/arm/mt7629-rfb.dts b/dts/src/arm/mt7629-rfb.dts
index 3621b7d2b2..9980c10c6e 100644
--- a/dts/src/arm/mt7629-rfb.dts
+++ b/dts/src/arm/mt7629-rfb.dts
@@ -66,9 +66,21 @@
pinctrl-1 = <&ephy_leds_pins>;
status = "okay";
+ gmac0: mac@0 {
+ compatible = "mediatek,eth-mac";
+ reg = <0>;
+ phy-mode = "2500base-x";
+ fixed-link {
+ speed = <2500>;
+ full-duplex;
+ pause;
+ };
+ };
+
gmac1: mac@1 {
compatible = "mediatek,eth-mac";
reg = <1>;
+ phy-mode = "gmii";
phy-handle = <&phy0>;
};
@@ -78,7 +90,6 @@
phy0: ethernet-phy@0 {
reg = <0>;
- phy-mode = "gmii";
};
};
};
diff --git a/dts/src/arm/mt7629.dtsi b/dts/src/arm/mt7629.dtsi
index 9608bc2ccb..867b88103b 100644
--- a/dts/src/arm/mt7629.dtsi
+++ b/dts/src/arm/mt7629.dtsi
@@ -468,14 +468,12 @@
compatible = "mediatek,mt7629-sgmiisys", "syscon";
reg = <0x1b128000 0x3000>;
#clock-cells = <1>;
- mediatek,physpeed = "2500";
};
sgmiisys1: syscon@1b130000 {
compatible = "mediatek,mt7629-sgmiisys", "syscon";
reg = <0x1b130000 0x3000>;
#clock-cells = <1>;
- mediatek,physpeed = "2500";
};
};
};
diff --git a/dts/src/arm/omap4-droid4-xt894.dts b/dts/src/arm/omap4-droid4-xt894.dts
index 4454449de0..a40fe8d49d 100644
--- a/dts/src/arm/omap4-droid4-xt894.dts
+++ b/dts/src/arm/omap4-droid4-xt894.dts
@@ -369,7 +369,7 @@
compatible = "ti,wl1285", "ti,wl1283";
reg = <2>;
/* gpio_100 with gpmc_wait2 pad as wakeirq */
- interrupts-extended = <&gpio4 4 IRQ_TYPE_EDGE_RISING>,
+ interrupts-extended = <&gpio4 4 IRQ_TYPE_LEVEL_HIGH>,
<&omap4_pmx_core 0x4e>;
interrupt-names = "irq", "wakeup";
ref-clock-frequency = <26000000>;
diff --git a/dts/src/arm/omap4-panda-common.dtsi b/dts/src/arm/omap4-panda-common.dtsi
index 14be2ecb62..55ea8b6189 100644
--- a/dts/src/arm/omap4-panda-common.dtsi
+++ b/dts/src/arm/omap4-panda-common.dtsi
@@ -474,7 +474,7 @@
compatible = "ti,wl1271";
reg = <2>;
/* gpio_53 with gpmc_ncs3 pad as wakeup */
- interrupts-extended = <&gpio2 21 IRQ_TYPE_EDGE_RISING>,
+ interrupts-extended = <&gpio2 21 IRQ_TYPE_LEVEL_HIGH>,
<&omap4_pmx_core 0x3a>;
interrupt-names = "irq", "wakeup";
ref-clock-frequency = <38400000>;
diff --git a/dts/src/arm/omap4-sdp.dts b/dts/src/arm/omap4-sdp.dts
index 3c274965ff..91480ac1f3 100644
--- a/dts/src/arm/omap4-sdp.dts
+++ b/dts/src/arm/omap4-sdp.dts
@@ -512,7 +512,7 @@
compatible = "ti,wl1281";
reg = <2>;
interrupt-parent = <&gpio1>;
- interrupts = <21 IRQ_TYPE_EDGE_RISING>; /* gpio 53 */
+ interrupts = <21 IRQ_TYPE_LEVEL_HIGH>; /* gpio 53 */
ref-clock-frequency = <26000000>;
tcxo-clock-frequency = <26000000>;
};
diff --git a/dts/src/arm/omap4-var-som-om44-wlan.dtsi b/dts/src/arm/omap4-var-som-om44-wlan.dtsi
index 6dbbc9b322..d003221310 100644
--- a/dts/src/arm/omap4-var-som-om44-wlan.dtsi
+++ b/dts/src/arm/omap4-var-som-om44-wlan.dtsi
@@ -69,7 +69,7 @@
compatible = "ti,wl1271";
reg = <2>;
interrupt-parent = <&gpio2>;
- interrupts = <9 IRQ_TYPE_EDGE_RISING>; /* gpio 41 */
+ interrupts = <9 IRQ_TYPE_LEVEL_HIGH>; /* gpio 41 */
ref-clock-frequency = <38400000>;
};
};
diff --git a/dts/src/arm/omap5-board-common.dtsi b/dts/src/arm/omap5-board-common.dtsi
index 7fff555ee3..68ac04641b 100644
--- a/dts/src/arm/omap5-board-common.dtsi
+++ b/dts/src/arm/omap5-board-common.dtsi
@@ -362,7 +362,7 @@
pinctrl-names = "default";
pinctrl-0 = <&wlcore_irq_pin>;
interrupt-parent = <&gpio1>;
- interrupts = <14 IRQ_TYPE_EDGE_RISING>; /* gpio 14 */
+ interrupts = <14 IRQ_TYPE_LEVEL_HIGH>; /* gpio 14 */
ref-clock-frequency = <26000000>;
};
};
diff --git a/dts/src/arm/omap54xx-clocks.dtsi b/dts/src/arm/omap54xx-clocks.dtsi
index fac2e57dcc..4791834dac 100644
--- a/dts/src/arm/omap54xx-clocks.dtsi
+++ b/dts/src/arm/omap54xx-clocks.dtsi
@@ -1146,7 +1146,7 @@
};
};
- gpu_cm: clock-controller@1500 {
+ gpu_cm: gpu_cm@1500 {
compatible = "ti,omap4-cm";
reg = <0x1500 0x100>;
#address-cells = <1>;
diff --git a/dts/src/arm/stm32mp157-pinctrl.dtsi b/dts/src/arm/stm32mp157-pinctrl.dtsi
index e4a0d51ec3..0a3a7d6673 100644
--- a/dts/src/arm/stm32mp157-pinctrl.dtsi
+++ b/dts/src/arm/stm32mp157-pinctrl.dtsi
@@ -609,13 +609,13 @@
<STM32_PINMUX('F', 6, AF9)>; /* QSPI_BK1_IO3 */
bias-disable;
drive-push-pull;
- slew-rate = <3>;
+ slew-rate = <1>;
};
pins2 {
pinmux = <STM32_PINMUX('B', 6, AF10)>; /* QSPI_BK1_NCS */
bias-pull-up;
drive-push-pull;
- slew-rate = <3>;
+ slew-rate = <1>;
};
};
@@ -637,13 +637,13 @@
<STM32_PINMUX('G', 7, AF11)>; /* QSPI_BK2_IO3 */
bias-disable;
drive-push-pull;
- slew-rate = <3>;
+ slew-rate = <1>;
};
pins2 {
pinmux = <STM32_PINMUX('C', 0, AF10)>; /* QSPI_BK2_NCS */
bias-pull-up;
drive-push-pull;
- slew-rate = <3>;
+ slew-rate = <1>;
};
};
diff --git a/dts/src/arm/sun7i-a20.dtsi b/dts/src/arm/sun7i-a20.dtsi
index 874231be04..8aebefd6ac 100644
--- a/dts/src/arm/sun7i-a20.dtsi
+++ b/dts/src/arm/sun7i-a20.dtsi
@@ -380,9 +380,8 @@
compatible = "allwinner,sun7i-a20-csi0";
reg = <0x01c09000 0x1000>;
interrupts = <GIC_SPI 42 IRQ_TYPE_LEVEL_HIGH>;
- clocks = <&ccu CLK_AHB_CSI0>, <&ccu CLK_CSI0>,
- <&ccu CLK_CSI_SCLK>, <&ccu CLK_DRAM_CSI0>;
- clock-names = "bus", "mod", "isp", "ram";
+ clocks = <&ccu CLK_AHB_CSI0>, <&ccu CLK_CSI_SCLK>, <&ccu CLK_DRAM_CSI0>;
+ clock-names = "bus", "isp", "ram";
resets = <&ccu RST_CSI0>;
status = "disabled";
};
diff --git a/dts/src/arm/vf610-zii-scu4-aib.dts b/dts/src/arm/vf610-zii-scu4-aib.dts
index dc8a5f37a1..c8ebb23c4e 100644
--- a/dts/src/arm/vf610-zii-scu4-aib.dts
+++ b/dts/src/arm/vf610-zii-scu4-aib.dts
@@ -602,6 +602,7 @@
#address-cells = <1>;
#size-cells = <0>;
reg = <0x70>;
+ i2c-mux-idle-disconnect;
sff0_i2c: i2c@1 {
#address-cells = <1>;
@@ -640,6 +641,7 @@
reg = <0x71>;
#address-cells = <1>;
#size-cells = <0>;
+ i2c-mux-idle-disconnect;
sff5_i2c: i2c@1 {
#address-cells = <1>;
diff --git a/dts/src/arm64/allwinner/sun50i-a64-pine64-plus.dts b/dts/src/arm64/allwinner/sun50i-a64-pine64-plus.dts
index 24f1aac366..d5b6e8159a 100644
--- a/dts/src/arm64/allwinner/sun50i-a64-pine64-plus.dts
+++ b/dts/src/arm64/allwinner/sun50i-a64-pine64-plus.dts
@@ -63,3 +63,12 @@
reg = <1>;
};
};
+
+&reg_dc1sw {
+ /*
+ * Ethernet PHY needs 30ms to properly power up and some more
+ * to initialize. 100ms should be plenty of time to finish
+ * whole process.
+ */
+ regulator-enable-ramp-delay = <100000>;
+};
diff --git a/dts/src/arm64/allwinner/sun50i-a64-sopine-baseboard.dts b/dts/src/arm64/allwinner/sun50i-a64-sopine-baseboard.dts
index e6fb9683f2..25099202c5 100644
--- a/dts/src/arm64/allwinner/sun50i-a64-sopine-baseboard.dts
+++ b/dts/src/arm64/allwinner/sun50i-a64-sopine-baseboard.dts
@@ -159,6 +159,12 @@
};
&reg_dc1sw {
+ /*
+ * Ethernet PHY needs 30ms to properly power up and some more
+ * to initialize. 100ms should be plenty of time to finish
+ * whole process.
+ */
+ regulator-enable-ramp-delay = <100000>;
regulator-name = "vcc-phy";
};
diff --git a/dts/src/arm64/allwinner/sun50i-a64.dtsi b/dts/src/arm64/allwinner/sun50i-a64.dtsi
index 3eccbdba71..70f4cce6be 100644
--- a/dts/src/arm64/allwinner/sun50i-a64.dtsi
+++ b/dts/src/arm64/allwinner/sun50i-a64.dtsi
@@ -142,15 +142,6 @@
clock-output-names = "ext-osc32k";
};
- pmu {
- compatible = "arm,cortex-a53-pmu";
- interrupts = <GIC_SPI 152 IRQ_TYPE_LEVEL_HIGH>,
- <GIC_SPI 153 IRQ_TYPE_LEVEL_HIGH>,
- <GIC_SPI 154 IRQ_TYPE_LEVEL_HIGH>,
- <GIC_SPI 155 IRQ_TYPE_LEVEL_HIGH>;
- interrupt-affinity = <&cpu0>, <&cpu1>, <&cpu2>, <&cpu3>;
- };
-
psci {
compatible = "arm,psci-0.2";
method = "smc";
diff --git a/dts/src/arm64/broadcom/stingray/stingray-pinctrl.dtsi b/dts/src/arm64/broadcom/stingray/stingray-pinctrl.dtsi
index 8a3a770e8f..56789ccf94 100644
--- a/dts/src/arm64/broadcom/stingray/stingray-pinctrl.dtsi
+++ b/dts/src/arm64/broadcom/stingray/stingray-pinctrl.dtsi
@@ -42,13 +42,14 @@
pinmux: pinmux@14029c {
compatible = "pinctrl-single";
- reg = <0x0014029c 0x250>;
+ reg = <0x0014029c 0x26c>;
#address-cells = <1>;
#size-cells = <1>;
pinctrl-single,register-width = <32>;
pinctrl-single,function-mask = <0xf>;
pinctrl-single,gpio-range = <
- &range 0 154 MODE_GPIO
+ &range 0 91 MODE_GPIO
+ &range 95 60 MODE_GPIO
>;
range: gpio-range {
#pinctrl-single,gpio-range-cells = <3>;
diff --git a/dts/src/arm64/broadcom/stingray/stingray.dtsi b/dts/src/arm64/broadcom/stingray/stingray.dtsi
index 71e2e34400..0098dfdef9 100644
--- a/dts/src/arm64/broadcom/stingray/stingray.dtsi
+++ b/dts/src/arm64/broadcom/stingray/stingray.dtsi
@@ -464,8 +464,7 @@
<&pinmux 108 16 27>,
<&pinmux 135 77 6>,
<&pinmux 141 67 4>,
- <&pinmux 145 149 6>,
- <&pinmux 151 91 4>;
+ <&pinmux 145 149 6>;
};
i2c1: i2c@e0000 {
diff --git a/dts/src/arm64/freescale/fsl-lx2160a.dtsi b/dts/src/arm64/freescale/fsl-lx2160a.dtsi
index 408e0ecdce..b032f3890c 100644
--- a/dts/src/arm64/freescale/fsl-lx2160a.dtsi
+++ b/dts/src/arm64/freescale/fsl-lx2160a.dtsi
@@ -33,7 +33,7 @@
i-cache-line-size = <64>;
i-cache-sets = <192>;
next-level-cache = <&cluster0_l2>;
- cpu-idle-states = <&cpu_pw20>;
+ cpu-idle-states = <&cpu_pw15>;
};
cpu@1 {
@@ -49,7 +49,7 @@
i-cache-line-size = <64>;
i-cache-sets = <192>;
next-level-cache = <&cluster0_l2>;
- cpu-idle-states = <&cpu_pw20>;
+ cpu-idle-states = <&cpu_pw15>;
};
cpu@100 {
@@ -65,7 +65,7 @@
i-cache-line-size = <64>;
i-cache-sets = <192>;
next-level-cache = <&cluster1_l2>;
- cpu-idle-states = <&cpu_pw20>;
+ cpu-idle-states = <&cpu_pw15>;
};
cpu@101 {
@@ -81,7 +81,7 @@
i-cache-line-size = <64>;
i-cache-sets = <192>;
next-level-cache = <&cluster1_l2>;
- cpu-idle-states = <&cpu_pw20>;
+ cpu-idle-states = <&cpu_pw15>;
};
cpu@200 {
@@ -97,7 +97,7 @@
i-cache-line-size = <64>;
i-cache-sets = <192>;
next-level-cache = <&cluster2_l2>;
- cpu-idle-states = <&cpu_pw20>;
+ cpu-idle-states = <&cpu_pw15>;
};
cpu@201 {
@@ -113,7 +113,7 @@
i-cache-line-size = <64>;
i-cache-sets = <192>;
next-level-cache = <&cluster2_l2>;
- cpu-idle-states = <&cpu_pw20>;
+ cpu-idle-states = <&cpu_pw15>;
};
cpu@300 {
@@ -129,7 +129,7 @@
i-cache-line-size = <64>;
i-cache-sets = <192>;
next-level-cache = <&cluster3_l2>;
- cpu-idle-states = <&cpu_pw20>;
+ cpu-idle-states = <&cpu_pw15>;
};
cpu@301 {
@@ -145,7 +145,7 @@
i-cache-line-size = <64>;
i-cache-sets = <192>;
next-level-cache = <&cluster3_l2>;
- cpu-idle-states = <&cpu_pw20>;
+ cpu-idle-states = <&cpu_pw15>;
};
cpu@400 {
@@ -161,7 +161,7 @@
i-cache-line-size = <64>;
i-cache-sets = <192>;
next-level-cache = <&cluster4_l2>;
- cpu-idle-states = <&cpu_pw20>;
+ cpu-idle-states = <&cpu_pw15>;
};
cpu@401 {
@@ -177,7 +177,7 @@
i-cache-line-size = <64>;
i-cache-sets = <192>;
next-level-cache = <&cluster4_l2>;
- cpu-idle-states = <&cpu_pw20>;
+ cpu-idle-states = <&cpu_pw15>;
};
cpu@500 {
@@ -193,7 +193,7 @@
i-cache-line-size = <64>;
i-cache-sets = <192>;
next-level-cache = <&cluster5_l2>;
- cpu-idle-states = <&cpu_pw20>;
+ cpu-idle-states = <&cpu_pw15>;
};
cpu@501 {
@@ -209,7 +209,7 @@
i-cache-line-size = <64>;
i-cache-sets = <192>;
next-level-cache = <&cluster5_l2>;
- cpu-idle-states = <&cpu_pw20>;
+ cpu-idle-states = <&cpu_pw15>;
};
cpu@600 {
@@ -225,7 +225,7 @@
i-cache-line-size = <64>;
i-cache-sets = <192>;
next-level-cache = <&cluster6_l2>;
- cpu-idle-states = <&cpu_pw20>;
+ cpu-idle-states = <&cpu_pw15>;
};
cpu@601 {
@@ -241,7 +241,7 @@
i-cache-line-size = <64>;
i-cache-sets = <192>;
next-level-cache = <&cluster6_l2>;
- cpu-idle-states = <&cpu_pw20>;
+ cpu-idle-states = <&cpu_pw15>;
};
cpu@700 {
@@ -257,7 +257,7 @@
i-cache-line-size = <64>;
i-cache-sets = <192>;
next-level-cache = <&cluster7_l2>;
- cpu-idle-states = <&cpu_pw20>;
+ cpu-idle-states = <&cpu_pw15>;
};
cpu@701 {
@@ -273,7 +273,7 @@
i-cache-line-size = <64>;
i-cache-sets = <192>;
next-level-cache = <&cluster7_l2>;
- cpu-idle-states = <&cpu_pw20>;
+ cpu-idle-states = <&cpu_pw15>;
};
cluster0_l2: l2-cache0 {
@@ -340,9 +340,9 @@
cache-level = <2>;
};
- cpu_pw20: cpu-pw20 {
+ cpu_pw15: cpu-pw15 {
compatible = "arm,idle-state";
- idle-state-name = "PW20";
+ idle-state-name = "PW15";
arm,psci-suspend-param = <0x0>;
entry-latency-us = <2000>;
exit-latency-us = <2000>;
diff --git a/dts/src/arm64/freescale/imx8mm.dtsi b/dts/src/arm64/freescale/imx8mm.dtsi
index 5f9d0da196..58b8cd06ca 100644
--- a/dts/src/arm64/freescale/imx8mm.dtsi
+++ b/dts/src/arm64/freescale/imx8mm.dtsi
@@ -694,7 +694,7 @@
compatible = "fsl,imx8mm-usdhc", "fsl,imx7d-usdhc";
reg = <0x30b40000 0x10000>;
interrupts = <GIC_SPI 22 IRQ_TYPE_LEVEL_HIGH>;
- clocks = <&clk IMX8MM_CLK_DUMMY>,
+ clocks = <&clk IMX8MM_CLK_IPG_ROOT>,
<&clk IMX8MM_CLK_NAND_USDHC_BUS>,
<&clk IMX8MM_CLK_USDHC1_ROOT>;
clock-names = "ipg", "ahb", "per";
@@ -710,7 +710,7 @@
compatible = "fsl,imx8mm-usdhc", "fsl,imx7d-usdhc";
reg = <0x30b50000 0x10000>;
interrupts = <GIC_SPI 23 IRQ_TYPE_LEVEL_HIGH>;
- clocks = <&clk IMX8MM_CLK_DUMMY>,
+ clocks = <&clk IMX8MM_CLK_IPG_ROOT>,
<&clk IMX8MM_CLK_NAND_USDHC_BUS>,
<&clk IMX8MM_CLK_USDHC2_ROOT>;
clock-names = "ipg", "ahb", "per";
@@ -724,7 +724,7 @@
compatible = "fsl,imx8mm-usdhc", "fsl,imx7d-usdhc";
reg = <0x30b60000 0x10000>;
interrupts = <GIC_SPI 24 IRQ_TYPE_LEVEL_HIGH>;
- clocks = <&clk IMX8MM_CLK_DUMMY>,
+ clocks = <&clk IMX8MM_CLK_IPG_ROOT>,
<&clk IMX8MM_CLK_NAND_USDHC_BUS>,
<&clk IMX8MM_CLK_USDHC3_ROOT>;
clock-names = "ipg", "ahb", "per";
diff --git a/dts/src/arm64/freescale/imx8mn.dtsi b/dts/src/arm64/freescale/imx8mn.dtsi
index 785f4c420f..98496f5707 100644
--- a/dts/src/arm64/freescale/imx8mn.dtsi
+++ b/dts/src/arm64/freescale/imx8mn.dtsi
@@ -569,7 +569,7 @@
compatible = "fsl,imx8mn-usdhc", "fsl,imx7d-usdhc";
reg = <0x30b40000 0x10000>;
interrupts = <GIC_SPI 22 IRQ_TYPE_LEVEL_HIGH>;
- clocks = <&clk IMX8MN_CLK_DUMMY>,
+ clocks = <&clk IMX8MN_CLK_IPG_ROOT>,
<&clk IMX8MN_CLK_NAND_USDHC_BUS>,
<&clk IMX8MN_CLK_USDHC1_ROOT>;
clock-names = "ipg", "ahb", "per";
@@ -585,7 +585,7 @@
compatible = "fsl,imx8mn-usdhc", "fsl,imx7d-usdhc";
reg = <0x30b50000 0x10000>;
interrupts = <GIC_SPI 23 IRQ_TYPE_LEVEL_HIGH>;
- clocks = <&clk IMX8MN_CLK_DUMMY>,
+ clocks = <&clk IMX8MN_CLK_IPG_ROOT>,
<&clk IMX8MN_CLK_NAND_USDHC_BUS>,
<&clk IMX8MN_CLK_USDHC2_ROOT>;
clock-names = "ipg", "ahb", "per";
@@ -599,7 +599,7 @@
compatible = "fsl,imx8mn-usdhc", "fsl,imx7d-usdhc";
reg = <0x30b60000 0x10000>;
interrupts = <GIC_SPI 24 IRQ_TYPE_LEVEL_HIGH>;
- clocks = <&clk IMX8MN_CLK_DUMMY>,
+ clocks = <&clk IMX8MN_CLK_IPG_ROOT>,
<&clk IMX8MN_CLK_NAND_USDHC_BUS>,
<&clk IMX8MN_CLK_USDHC3_ROOT>;
clock-names = "ipg", "ahb", "per";
diff --git a/dts/src/arm64/freescale/imx8mq-zii-ultra.dtsi b/dts/src/arm64/freescale/imx8mq-zii-ultra.dtsi
index af99473ada..087b5b6ebe 100644
--- a/dts/src/arm64/freescale/imx8mq-zii-ultra.dtsi
+++ b/dts/src/arm64/freescale/imx8mq-zii-ultra.dtsi
@@ -89,8 +89,8 @@
regulator-min-microvolt = <900000>;
regulator-max-microvolt = <1000000>;
gpios = <&gpio3 19 GPIO_ACTIVE_HIGH>;
- states = <1000000 0x0
- 900000 0x1>;
+ states = <1000000 0x1
+ 900000 0x0>;
regulator-always-on;
};
};
diff --git a/dts/src/arm64/freescale/imx8mq.dtsi b/dts/src/arm64/freescale/imx8mq.dtsi
index 04115ca6bf..55a3d1c4bd 100644
--- a/dts/src/arm64/freescale/imx8mq.dtsi
+++ b/dts/src/arm64/freescale/imx8mq.dtsi
@@ -850,7 +850,7 @@
"fsl,imx7d-usdhc";
reg = <0x30b40000 0x10000>;
interrupts = <GIC_SPI 22 IRQ_TYPE_LEVEL_HIGH>;
- clocks = <&clk IMX8MQ_CLK_DUMMY>,
+ clocks = <&clk IMX8MQ_CLK_IPG_ROOT>,
<&clk IMX8MQ_CLK_NAND_USDHC_BUS>,
<&clk IMX8MQ_CLK_USDHC1_ROOT>;
clock-names = "ipg", "ahb", "per";
@@ -867,7 +867,7 @@
"fsl,imx7d-usdhc";
reg = <0x30b50000 0x10000>;
interrupts = <GIC_SPI 23 IRQ_TYPE_LEVEL_HIGH>;
- clocks = <&clk IMX8MQ_CLK_DUMMY>,
+ clocks = <&clk IMX8MQ_CLK_IPG_ROOT>,
<&clk IMX8MQ_CLK_NAND_USDHC_BUS>,
<&clk IMX8MQ_CLK_USDHC2_ROOT>;
clock-names = "ipg", "ahb", "per";
diff --git a/dts/src/arm64/marvell/armada-3720-turris-mox.dts b/dts/src/arm64/marvell/armada-3720-turris-mox.dts
index d105986c6b..5f350cc71a 100644
--- a/dts/src/arm64/marvell/armada-3720-turris-mox.dts
+++ b/dts/src/arm64/marvell/armada-3720-turris-mox.dts
@@ -60,11 +60,6 @@
gpio = <&gpiosb 0 GPIO_ACTIVE_HIGH>;
};
- usb3_phy: usb3-phy {
- compatible = "usb-nop-xceiv";
- vcc-supply = <&exp_usb3_vbus>;
- };
-
vsdc_reg: vsdc-reg {
compatible = "regulator-gpio";
regulator-name = "vsdc";
@@ -255,10 +250,16 @@
status = "okay";
};
+&comphy2 {
+ connector {
+ compatible = "usb-a-connector";
+ phy-supply = <&exp_usb3_vbus>;
+ };
+};
+
&usb3 {
status = "okay";
phys = <&comphy2 0>;
- usb-phy = <&usb3_phy>;
};
&mdio {
diff --git a/dts/src/arm64/rockchip/rk3399-gru-kevin.dts b/dts/src/arm64/rockchip/rk3399-gru-kevin.dts
index e152b0ca02..b8066868a3 100644
--- a/dts/src/arm64/rockchip/rk3399-gru-kevin.dts
+++ b/dts/src/arm64/rockchip/rk3399-gru-kevin.dts
@@ -44,7 +44,7 @@
power-supply = <&pp3300_disp>;
panel-timing {
- clock-frequency = <266604720>;
+ clock-frequency = <266666667>;
hactive = <2400>;
hfront-porch = <48>;
hback-porch = <84>;
diff --git a/dts/src/arm64/rockchip/rk3399-hugsun-x99.dts b/dts/src/arm64/rockchip/rk3399-hugsun-x99.dts
index 0d1f5f9a0d..c133e8d64b 100644
--- a/dts/src/arm64/rockchip/rk3399-hugsun-x99.dts
+++ b/dts/src/arm64/rockchip/rk3399-hugsun-x99.dts
@@ -644,7 +644,7 @@
status = "okay";
u2phy0_host: host-port {
- phy-supply = <&vcc5v0_host>;
+ phy-supply = <&vcc5v0_typec>;
status = "okay";
};
@@ -712,7 +712,7 @@
&usbdrd_dwc3_0 {
status = "okay";
- dr_mode = "otg";
+ dr_mode = "host";
};
&usbdrd3_1 {
diff --git a/dts/src/arm64/rockchip/rk3399-rockpro64.dts b/dts/src/arm64/rockchip/rk3399-rockpro64.dts
index 0401d4ec1f..e544deb61d 100644
--- a/dts/src/arm64/rockchip/rk3399-rockpro64.dts
+++ b/dts/src/arm64/rockchip/rk3399-rockpro64.dts
@@ -173,7 +173,7 @@
regulator-always-on;
regulator-boot-on;
regulator-min-microvolt = <800000>;
- regulator-max-microvolt = <1400000>;
+ regulator-max-microvolt = <1700000>;
vin-supply = <&vcc5v0_sys>;
};
};
@@ -247,8 +247,8 @@
rk808: pmic@1b {
compatible = "rockchip,rk808";
reg = <0x1b>;
- interrupt-parent = <&gpio1>;
- interrupts = <21 IRQ_TYPE_LEVEL_LOW>;
+ interrupt-parent = <&gpio3>;
+ interrupts = <10 IRQ_TYPE_LEVEL_LOW>;
#clock-cells = <1>;
clock-output-names = "xin32k", "rk808-clkout2";
pinctrl-names = "default";
@@ -574,7 +574,7 @@
pmic {
pmic_int_l: pmic-int-l {
- rockchip,pins = <1 RK_PC5 RK_FUNC_GPIO &pcfg_pull_up>;
+ rockchip,pins = <3 RK_PB2 RK_FUNC_GPIO &pcfg_pull_up>;
};
vsel1_gpio: vsel1-gpio {
@@ -624,7 +624,6 @@
&sdmmc {
bus-width = <4>;
- cap-mmc-highspeed;
cap-sd-highspeed;
cd-gpios = <&gpio0 7 GPIO_ACTIVE_LOW>;
disable-wp;
@@ -636,8 +635,7 @@
&sdhci {
bus-width = <8>;
- mmc-hs400-1_8v;
- mmc-hs400-enhanced-strobe;
+ mmc-hs200-1_8v;
non-removable;
status = "okay";
};
diff --git a/dts/src/riscv/sifive/hifive-unleashed-a00.dts b/dts/src/riscv/sifive/hifive-unleashed-a00.dts
index 104d334511..88cfcb96bf 100644
--- a/dts/src/riscv/sifive/hifive-unleashed-a00.dts
+++ b/dts/src/riscv/sifive/hifive-unleashed-a00.dts
@@ -13,6 +13,7 @@
compatible = "sifive,hifive-unleashed-a00", "sifive,fu540-c000";
chosen {
+ stdout-path = "serial0";
};
cpus {
diff --git a/dts/src/xtensa/virt.dts b/dts/src/xtensa/virt.dts
index a9dcd87b6e..611b98a02a 100644
--- a/dts/src/xtensa/virt.dts
+++ b/dts/src/xtensa/virt.dts
@@ -56,7 +56,7 @@
reg = <0xf0100000 0x03f00000>;
// BUS_ADDRESS(3) CPU_PHYSICAL(1) SIZE(2)
- ranges = <0x01000000 0x0 0xf0000000 0xf0000000 0x0 0x00010000>,
+ ranges = <0x01000000 0x0 0x00000000 0xf0000000 0x0 0x00010000>,
<0x02000000 0x0 0xf4000000 0xf4000000 0x0 0x08000000>;
// PCI_DEVICE(3) INT#(1) CONTROLLER(PHANDLE) CONTROLLER_DATA(2)
diff --git a/fs/devfs-core.c b/fs/devfs-core.c
index 258bb2dbaa..5341e39e67 100644
--- a/fs/devfs-core.c
+++ b/fs/devfs-core.c
@@ -104,7 +104,7 @@ struct cdev *cdev_by_partuuid(const char *partuuid)
return NULL;
list_for_each_entry(cdev, &cdev_list, list) {
- if (!strcmp(cdev->partuuid, partuuid))
+ if (!strcasecmp(cdev->partuuid, partuuid))
return cdev;
}
return NULL;
diff --git a/fs/efivarfs.c b/fs/efivarfs.c
index 1e80493621..9eadda4121 100644
--- a/fs/efivarfs.c
+++ b/fs/efivarfs.c
@@ -145,7 +145,7 @@ static int efivars_create(struct device_d *dev, const char *pathname, mode_t mod
if (ret)
return -ENOENT;
- if (memcmp(&vendor, &EFI_BAREBOX_VENDOR_GUID, sizeof(efi_guid_t)))
+ if (efi_guidcmp(vendor, EFI_BAREBOX_VENDOR_GUID))
return -EPERM;
inode = xzalloc(sizeof(*inode));
diff --git a/fs/ext4/ext4_common.c b/fs/ext4/ext4_common.c
index 55e837b4bd..c9f27f1278 100644
--- a/fs/ext4/ext4_common.c
+++ b/fs/ext4/ext4_common.c
@@ -52,7 +52,7 @@ static struct ext4_extent_header *ext4fs_get_extent_block(struct ext2_data *data
index = (struct ext4_extent_idx *)(ext_block + 1);
if (le16_to_cpu(ext_block->eh_magic) != EXT4_EXT_MAGIC)
- return 0;
+ return NULL;
if (ext_block->eh_depth == 0)
return ext_block;
@@ -64,7 +64,7 @@ static struct ext4_extent_header *ext4fs_get_extent_block(struct ext2_data *data
} while (fileblock >= le32_to_cpu(index[i].ei_block));
if (--i < 0)
- return 0;
+ return NULL;
block = le16_to_cpu(index[i].ei_leaf_hi);
block = (block << 32) + le32_to_cpu(index[i].ei_leaf_lo);
@@ -167,10 +167,11 @@ long int read_allocated_block(struct ext2fs_node *node, int fileblock)
log2_blksz = LOG2_EXT2_BLOCK_SIZE(node->data);
if (le32_to_cpu(inode->flags) & EXT4_EXTENTS_FL) {
+ long int startblock, endblock;
char *buf = zalloc(blksz);
struct ext4_extent_header *ext_block;
struct ext4_extent *extent;
- int i = -1;
+ int i;
if (!buf)
return -ENOMEM;
@@ -186,28 +187,27 @@ long int read_allocated_block(struct ext2fs_node *node, int fileblock)
extent = (struct ext4_extent *)(ext_block + 1);
- do {
- i++;
- if (i >= le16_to_cpu(ext_block->eh_entries))
- break;
- } while (fileblock >= le32_to_cpu(extent[i].ee_block));
+ for (i = 0; i < le16_to_cpu(ext_block->eh_entries); i++) {
+ startblock = le32_to_cpu(extent[i].ee_block);
+ endblock = startblock + le16_to_cpu(extent[i].ee_len);
- if (--i >= 0) {
- fileblock -= le32_to_cpu(extent[i].ee_block);
- if (fileblock >= le16_to_cpu(extent[i].ee_len)) {
+ if (startblock > fileblock) {
+ /* Sparse file */
free(buf);
return 0;
}
- start = le16_to_cpu(extent[i].ee_start_hi);
- start = (start << 32) +
+ if (fileblock < endblock) {
+ start = le16_to_cpu(extent[i].ee_start_hi);
+ start = (start << 32) +
le32_to_cpu(extent[i].ee_start_lo);
- free(buf);
- return fileblock + start;
+ free(buf);
+ return (fileblock - startblock) + start;
+ }
}
free(buf);
- return -EIO;
+ return 0;
}
if (fileblock < INDIRECT_BLOCKS) {
diff --git a/fs/ext4/ext4fs.c b/fs/ext4/ext4fs.c
index bfc5f27cc3..2d231d273a 100644
--- a/fs/ext4/ext4fs.c
+++ b/fs/ext4/ext4fs.c
@@ -55,12 +55,6 @@ int ext4fs_read_file(struct ext2fs_node *node, int pos,
int log2blocksize = LOG2_EXT2_BLOCK_SIZE(node->data);
int blocksize = 1 << (log2blocksize + DISK_SECTOR_BITS);
unsigned int filesize = le32_to_cpu(node->inode.size);
- int previous_block_number = -1;
- int delayed_start = 0;
- int delayed_extent = 0;
- int delayed_skipfirst = 0;
- int delayed_next = 0;
- char *delayed_buf = NULL;
short ret;
struct ext_filesystem *fs = node->data->fs;
@@ -75,6 +69,7 @@ int ext4fs_read_file(struct ext2fs_node *node, int pos,
int blockoff = pos % blocksize;
int blockend = blocksize;
int skipfirst = 0;
+
blknr = read_allocated_block(node, i);
if (blknr < 0)
return blknr;
@@ -95,59 +90,17 @@ int ext4fs_read_file(struct ext2fs_node *node, int pos,
skipfirst = blockoff;
blockend -= skipfirst;
}
+
if (blknr) {
- if (previous_block_number != -1) {
- if (delayed_next == blknr) {
- delayed_extent += blockend;
- delayed_next += blockend >> SECTOR_BITS;
- } else { /* spill */
- ret = ext4fs_devread(fs, delayed_start,
- delayed_skipfirst,
- delayed_extent,
- delayed_buf);
- if (ret)
- return ret;
- previous_block_number = blknr;
- delayed_start = blknr;
- delayed_extent = blockend;
- delayed_skipfirst = skipfirst;
- delayed_buf = buf;
- delayed_next = blknr +
- (blockend >> SECTOR_BITS);
- }
- } else {
- previous_block_number = blknr;
- delayed_start = blknr;
- delayed_extent = blockend;
- delayed_skipfirst = skipfirst;
- delayed_buf = buf;
- delayed_next = blknr +
- (blockend >> SECTOR_BITS);
- }
+ ret = ext4fs_devread(fs, blknr, skipfirst, blockend, buf);
+ if (ret)
+ return ret;
} else {
- if (previous_block_number != -1) {
- /* spill */
- ret = ext4fs_devread(fs, delayed_start,
- delayed_skipfirst,
- delayed_extent,
- delayed_buf);
- if (ret)
- return ret;
- previous_block_number = -1;
- }
- memset(buf, 0, blocksize - skipfirst);
+ memset(buf, 0, blockend);
}
+
buf += blocksize - skipfirst;
}
- if (previous_block_number != -1) {
- /* spill */
- ret = ext4fs_devread(fs, delayed_start,
- delayed_skipfirst, delayed_extent,
- delayed_buf);
- if (ret)
- return ret;
- previous_block_number = -1;
- }
return len;
}
diff --git a/fs/ubootvarfs.c b/fs/ubootvarfs.c
index 81ec05d5ef..475e4b7a79 100644
--- a/fs/ubootvarfs.c
+++ b/fs/ubootvarfs.c
@@ -409,7 +409,7 @@ static void ubootvarfs_parse(struct ubootvarfs_data *data, char *blob,
list_add_tail(&var->list, &data->var_list);
} else {
- pr_err("No separator in data @ 0x%08x. Skipped.",
+ pr_err("No separator in data @ 0x%08tx. Skipped.",
blob - start);
free(var);
}
diff --git a/include/efi.h b/include/efi.h
index 218333f824..166803a58f 100644
--- a/include/efi.h
+++ b/include/efi.h
@@ -664,11 +664,6 @@ typedef union {
efi_ipv6_address v6;
} efi_ip_address;
-static inline int efi_compare_guid(efi_guid_t *a, efi_guid_t *b)
-{
- return memcmp(a, b, sizeof(efi_guid_t));
-}
-
struct efi_device_path *device_path_from_handle(efi_handle_t Handle);
char *device_path_to_str(struct efi_device_path *dev_path);
u8 device_path_to_type(struct efi_device_path *dev_path);
diff --git a/include/efi/efi-device.h b/include/efi/efi-device.h
index 15c293bb1b..5eaf1f260d 100644
--- a/include/efi/efi-device.h
+++ b/include/efi/efi-device.h
@@ -43,5 +43,6 @@ static inline int efi_driver_register(struct efi_driver *efidrv)
int efi_connect_all(void);
void efi_register_devices(void);
+struct efi_device *efi_get_bootsource(void);
#endif /* __EFI_EFI_DEVICE_H */
diff --git a/include/linux/mfd/stpmic1.h b/include/linux/mfd/stpmic1.h
new file mode 100644
index 0000000000..3a8d6a7dcf
--- /dev/null
+++ b/include/linux/mfd/stpmic1.h
@@ -0,0 +1,199 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (C) STMicroelectronics 2018 - All Rights Reserved
+ * Author: Philippe Peurichard <philippe.peurichard@st.com>,
+ * Pascal Paillet <p.paillet@st.com> for STMicroelectronics.
+ */
+
+#ifndef __LINUX_MFD_STPMIC1_H
+#define __LINUX_MFD_STPMIC1_H
+
+#define TURN_ON_SR 0x1
+#define TURN_OFF_SR 0x2
+#define ICC_LDO_TURN_OFF_SR 0x3
+#define ICC_BUCK_TURN_OFF_SR 0x4
+#define RREQ_STATE_SR 0x5
+#define VERSION_SR 0x6
+
+#define SWOFF_PWRCTRL_CR 0x10
+#define PADS_PULL_CR 0x11
+#define BUCKS_PD_CR 0x12
+#define LDO14_PD_CR 0x13
+#define LDO56_VREF_PD_CR 0x14
+#define VBUS_DET_VIN_CR 0x15
+#define PKEY_TURNOFF_CR 0x16
+#define BUCKS_MASK_RANK_CR 0x17
+#define BUCKS_MASK_RESET_CR 0x18
+#define LDOS_MASK_RANK_CR 0x19
+#define LDOS_MASK_RESET_CR 0x1A
+#define WCHDG_CR 0x1B
+#define WCHDG_TIMER_CR 0x1C
+#define BUCKS_ICCTO_CR 0x1D
+#define LDOS_ICCTO_CR 0x1E
+
+#define BUCK1_ACTIVE_CR 0x20
+#define BUCK2_ACTIVE_CR 0x21
+#define BUCK3_ACTIVE_CR 0x22
+#define BUCK4_ACTIVE_CR 0x23
+#define VREF_DDR_ACTIVE_CR 0x24
+#define LDO1_ACTIVE_CR 0x25
+#define LDO2_ACTIVE_CR 0x26
+#define LDO3_ACTIVE_CR 0x27
+#define LDO4_ACTIVE_CR 0x28
+#define LDO5_ACTIVE_CR 0x29
+#define LDO6_ACTIVE_CR 0x2A
+
+#define BUCK1_STDBY_CR 0x30
+#define BUCK2_STDBY_CR 0x31
+#define BUCK3_STDBY_CR 0x32
+#define BUCK4_STDBY_CR 0x33
+#define VREF_DDR_STDBY_CR 0x34
+#define LDO1_STDBY_CR 0x35
+#define LDO2_STDBY_CR 0x36
+#define LDO3_STDBY_CR 0x37
+#define LDO4_STDBY_CR 0x38
+#define LDO5_STDBY_CR 0x39
+#define LDO6_STDBY_CR 0x3A
+
+#define BST_SW_CR 0x40
+
+#define INT_PENDING_R1 0x50
+#define INT_PENDING_R2 0x51
+#define INT_PENDING_R3 0x52
+#define INT_PENDING_R4 0x53
+
+#define INT_DBG_LATCH_R1 0x60
+#define INT_DBG_LATCH_R2 0x61
+#define INT_DBG_LATCH_R3 0x62
+#define INT_DBG_LATCH_R4 0x63
+
+#define INT_CLEAR_R1 0x70
+#define INT_CLEAR_R2 0x71
+#define INT_CLEAR_R3 0x72
+#define INT_CLEAR_R4 0x73
+
+#define INT_MASK_R1 0x80
+#define INT_MASK_R2 0x81
+#define INT_MASK_R3 0x82
+#define INT_MASK_R4 0x83
+
+#define INT_SET_MASK_R1 0x90
+#define INT_SET_MASK_R2 0x91
+#define INT_SET_MASK_R3 0x92
+#define INT_SET_MASK_R4 0x93
+
+#define INT_CLEAR_MASK_R1 0xA0
+#define INT_CLEAR_MASK_R2 0xA1
+#define INT_CLEAR_MASK_R3 0xA2
+#define INT_CLEAR_MASK_R4 0xA3
+
+#define INT_SRC_R1 0xB0
+#define INT_SRC_R2 0xB1
+#define INT_SRC_R3 0xB2
+#define INT_SRC_R4 0xB3
+
+#define PMIC_MAX_REGISTER_ADDRESS INT_SRC_R4
+
+#define STPMIC1_PMIC_NUM_IRQ_REGS 4
+
+#define TURN_OFF_SR_ICC_EVENT 0x08
+
+#define LDO_VOLTAGE_MASK GENMASK(6, 2)
+#define BUCK_VOLTAGE_MASK GENMASK(7, 2)
+#define LDO_BUCK_VOLTAGE_SHIFT 2
+
+#define LDO_ENABLE_MASK BIT(0)
+#define BUCK_ENABLE_MASK BIT(0)
+
+#define BUCK_HPLP_ENABLE_MASK BIT(1)
+#define BUCK_HPLP_SHIFT 1
+
+#define STDBY_ENABLE_MASK BIT(0)
+
+#define BUCKS_PD_CR_REG_MASK GENMASK(7, 0)
+#define BUCK_MASK_RANK_REGISTER_MASK GENMASK(3, 0)
+#define BUCK_MASK_RESET_REGISTER_MASK GENMASK(3, 0)
+#define LDO1234_PULL_DOWN_REGISTER_MASK GENMASK(7, 0)
+#define LDO56_VREF_PD_CR_REG_MASK GENMASK(5, 0)
+#define LDO_MASK_RANK_REGISTER_MASK GENMASK(5, 0)
+#define LDO_MASK_RESET_REGISTER_MASK GENMASK(5, 0)
+
+#define BUCK1_PULL_DOWN_REG BUCKS_PD_CR
+#define BUCK1_PULL_DOWN_MASK BIT(0)
+#define BUCK2_PULL_DOWN_REG BUCKS_PD_CR
+#define BUCK2_PULL_DOWN_MASK BIT(2)
+#define BUCK3_PULL_DOWN_REG BUCKS_PD_CR
+#define BUCK3_PULL_DOWN_MASK BIT(4)
+#define BUCK4_PULL_DOWN_REG BUCKS_PD_CR
+#define BUCK4_PULL_DOWN_MASK BIT(6)
+
+#define LDO1_PULL_DOWN_REG LDO14_PD_CR
+#define LDO1_PULL_DOWN_MASK BIT(0)
+#define LDO2_PULL_DOWN_REG LDO14_PD_CR
+#define LDO2_PULL_DOWN_MASK BIT(2)
+#define LDO3_PULL_DOWN_REG LDO14_PD_CR
+#define LDO3_PULL_DOWN_MASK BIT(4)
+#define LDO4_PULL_DOWN_REG LDO14_PD_CR
+#define LDO4_PULL_DOWN_MASK BIT(6)
+#define LDO5_PULL_DOWN_REG LDO56_VREF_PD_CR
+#define LDO5_PULL_DOWN_MASK BIT(0)
+#define LDO6_PULL_DOWN_REG LDO56_VREF_PD_CR
+#define LDO6_PULL_DOWN_MASK BIT(2)
+#define VREF_DDR_PULL_DOWN_REG LDO56_VREF_PD_CR
+#define VREF_DDR_PULL_DOWN_MASK BIT(4)
+
+#define BUCKS_ICCTO_CR_REG_MASK GENMASK(6, 0)
+#define LDOS_ICCTO_CR_REG_MASK GENMASK(5, 0)
+
+#define LDO_BYPASS_MASK BIT(7)
+
+/* Main PMIC Control Register
+ * SWOFF_PWRCTRL_CR
+ * Address : 0x10
+ */
+#define ICC_EVENT_ENABLED BIT(4)
+#define PWRCTRL_POLARITY_HIGH BIT(3)
+#define PWRCTRL_PIN_VALID BIT(2)
+#define RESTART_REQUEST_ENABLED BIT(1)
+#define SOFTWARE_SWITCH_OFF_ENABLED BIT(0)
+
+/* Main PMIC PADS Control Register
+ * PADS_PULL_CR
+ * Address : 0x11
+ */
+#define WAKEUP_DETECTOR_DISABLED BIT(4)
+#define PWRCTRL_PD_ACTIVE BIT(3)
+#define PWRCTRL_PU_ACTIVE BIT(2)
+#define WAKEUP_PD_ACTIVE BIT(1)
+#define PONKEY_PU_INACTIVE BIT(0)
+
+/* Main PMIC VINLOW Control Register
+ * VBUS_DET_VIN_CRC DMSC
+ * Address : 0x15
+ */
+#define SWIN_DETECTOR_ENABLED BIT(7)
+#define SWOUT_DETECTOR_ENABLED BIT(6)
+#define VINLOW_ENABLED BIT(0)
+#define VINLOW_CTRL_REG_MASK GENMASK(7, 0)
+
+/* USB Control Register
+ * Address : 0x40
+ */
+#define BOOST_OVP_DISABLED BIT(7)
+#define VBUS_OTG_DETECTION_DISABLED BIT(6)
+#define SW_OUT_DISCHARGE BIT(5)
+#define VBUS_OTG_DISCHARGE BIT(4)
+#define OCP_LIMIT_HIGH BIT(3)
+#define SWIN_SWOUT_ENABLED BIT(2)
+#define USBSW_OTG_SWITCH_ENABLED BIT(1)
+#define BOOST_ENABLED BIT(0)
+
+/* PKEY_TURNOFF_CR
+ * Address : 0x16
+ */
+#define PONKEY_PWR_OFF BIT(7)
+#define PONKEY_CC_FLAG_CLEAR BIT(6)
+#define PONKEY_TURNOFF_TIMER_MASK GENMASK(3, 0)
+#define PONKEY_TURNOFF_MASK GENMASK(7, 0)
+
+#endif /* __LINUX_MFD_STPMIC1_H */
diff --git a/include/linux/regulator/machine.h b/include/linux/regulator/machine.h
new file mode 100644
index 0000000000..bb8bc7c4e0
--- /dev/null
+++ b/include/linux/regulator/machine.h
@@ -0,0 +1,207 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * machine.h -- SoC Regulator support, machine/board driver API.
+ *
+ * Copyright (C) 2007, 2008 Wolfson Microelectronics PLC.
+ *
+ * Author: Liam Girdwood <lrg@slimlogic.co.uk>
+ *
+ * Regulator Machine/Board Interface.
+ */
+
+#ifndef __LINUX_REGULATOR_MACHINE_H_
+#define __LINUX_REGULATOR_MACHINE_H_
+
+#include <regulator.h>
+
+struct regulator;
+
+/*
+ * Regulator operation constraint flags. These flags are used to enable
+ * certain regulator operations and can be OR'ed together.
+ *
+ * VOLTAGE: Regulator output voltage can be changed by software on this
+ * board/machine.
+ * CURRENT: Regulator output current can be changed by software on this
+ * board/machine.
+ * MODE: Regulator operating mode can be changed by software on this
+ * board/machine.
+ * STATUS: Regulator can be enabled and disabled.
+ * DRMS: Dynamic Regulator Mode Switching is enabled for this regulator.
+ * BYPASS: Regulator can be put into bypass mode
+ */
+
+#define REGULATOR_CHANGE_VOLTAGE 0x1
+#define REGULATOR_CHANGE_CURRENT 0x2
+#define REGULATOR_CHANGE_MODE 0x4
+#define REGULATOR_CHANGE_STATUS 0x8
+#define REGULATOR_CHANGE_DRMS 0x10
+#define REGULATOR_CHANGE_BYPASS 0x20
+
+/* Regulator active discharge flags */
+enum regulator_active_discharge {
+ REGULATOR_ACTIVE_DISCHARGE_DEFAULT,
+ REGULATOR_ACTIVE_DISCHARGE_DISABLE,
+ REGULATOR_ACTIVE_DISCHARGE_ENABLE,
+};
+
+/**
+ * struct regulation_constraints - regulator operating constraints.
+ *
+ * This struct describes regulator and board/machine specific constraints.
+ *
+ * @name: Descriptive name for the constraints, used for display purposes.
+ *
+ * @min_uV: Smallest voltage consumers may set.
+ * @max_uV: Largest voltage consumers may set.
+ * @uV_offset: Offset applied to voltages from consumer to compensate for
+ * voltage drops.
+ *
+ * @min_uA: Smallest current consumers may set.
+ * @max_uA: Largest current consumers may set.
+ * @ilim_uA: Maximum input current.
+ * @system_load: Load that isn't captured by any consumer requests.
+ *
+ * @max_spread: Max possible spread between coupled regulators
+ * @valid_modes_mask: Mask of modes which may be configured by consumers.
+ * @valid_ops_mask: Operations which may be performed by consumers.
+ *
+ * @always_on: Set if the regulator should never be disabled.
+ * @boot_on: Set if the regulator is enabled when the system is initially
+ * started. If the regulator is not enabled by the hardware or
+ * bootloader then it will be enabled when the constraints are
+ * applied.
+ * @apply_uV: Apply the voltage constraint when initialising.
+ * @ramp_disable: Disable ramp delay when initialising or when setting voltage.
+ * @soft_start: Enable soft start so that voltage ramps slowly.
+ * @pull_down: Enable pull down when regulator is disabled.
+ * @over_current_protection: Auto disable on over current event.
+ *
+ * @input_uV: Input voltage for regulator when supplied by another regulator.
+ *
+ * @initial_mode: Mode to set at startup.
+ * @ramp_delay: Time to settle down after voltage change (unit: uV/us)
+ * @settling_time: Time to settle down after voltage change when voltage
+ * change is non-linear (unit: microseconds).
+ * @settling_time_up: Time to settle down after voltage increase when voltage
+ * change is non-linear (unit: microseconds).
+ * @settling_time_down : Time to settle down after voltage decrease when
+ * voltage change is non-linear (unit: microseconds).
+ * @active_discharge: Enable/disable active discharge. The enum
+ * regulator_active_discharge values are used for
+ * initialisation.
+ * @enable_time: Turn-on time of the rails (unit: microseconds)
+ */
+struct regulation_constraints {
+
+ const char *name;
+
+ /* voltage output range (inclusive) - for voltage control */
+ int min_uV;
+ int max_uV;
+
+ int uV_offset;
+
+ /* current output range (inclusive) - for current control */
+ int min_uA;
+ int max_uA;
+ int ilim_uA;
+
+ int system_load;
+
+ /* used for coupled regulators */
+ u32 *max_spread;
+
+ /* used for changing voltage in steps */
+ int max_uV_step;
+
+ /* valid regulator operating modes for this machine */
+ unsigned int valid_modes_mask;
+
+ /* valid operations for regulator on this machine */
+ unsigned int valid_ops_mask;
+
+ /* regulator input voltage - only if supply is another regulator */
+ int input_uV;
+
+ /* mode to set on startup */
+ unsigned int initial_mode;
+
+ unsigned int ramp_delay;
+ unsigned int settling_time;
+ unsigned int settling_time_up;
+ unsigned int settling_time_down;
+ unsigned int enable_time;
+
+ unsigned int active_discharge;
+
+ /* constraint flags */
+ unsigned always_on:1; /* regulator never off when system is on */
+ unsigned boot_on:1; /* bootloader/firmware enabled regulator */
+ unsigned apply_uV:1; /* apply uV constraint if min == max */
+ unsigned ramp_disable:1; /* disable ramp delay */
+ unsigned soft_start:1; /* ramp voltage slowly */
+ unsigned pull_down:1; /* pull down resistor when regulator off */
+ unsigned over_current_protection:1; /* auto disable on over current */
+};
+
+/**
+ * struct regulator_consumer_supply - supply -> device mapping
+ *
+ * This maps a supply name to a device. Use of dev_name allows support for
+ * buses which make struct device available late such as I2C.
+ *
+ * @dev_name: Result of dev_name() for the consumer.
+ * @supply: Name for the supply.
+ */
+struct regulator_consumer_supply {
+ const char *dev_name; /* dev_name() for consumer */
+ const char *supply; /* consumer supply - e.g. "vcc" */
+};
+
+/* Initialize struct regulator_consumer_supply */
+#define REGULATOR_SUPPLY(_name, _dev_name) \
+{ \
+ .supply = _name, \
+ .dev_name = _dev_name, \
+}
+
+/**
+ * struct regulator_init_data - regulator platform initialisation data.
+ *
+ * Initialisation constraints, our supply and consumers supplies.
+ *
+ * @supply_regulator: Parent regulator. Specified using the regulator name
+ * as it appears in the name field in sysfs, which can
+ * be explicitly set using the constraints field 'name'.
+ *
+ * @constraints: Constraints. These must be specified for the regulator to
+ * be usable.
+ * @num_consumer_supplies: Number of consumer device supplies.
+ * @consumer_supplies: Consumer device supply configuration.
+ *
+ * @regulator_init: Callback invoked when the regulator has been registered.
+ * @driver_data: Data passed to regulator_init.
+ */
+struct regulator_init_data {
+ const char *supply_regulator; /* or NULL for system supply */
+
+ struct regulation_constraints constraints;
+
+ int num_consumer_supplies;
+ struct regulator_consumer_supply *consumer_supplies;
+
+ /* optional regulator machine specific init */
+ int (*regulator_init)(void *driver_data);
+ void *driver_data; /* core does not touch this */
+};
+
+#ifdef CONFIG_REGULATOR
+void regulator_has_full_constraints(void);
+#else
+static inline void regulator_has_full_constraints(void)
+{
+}
+#endif
+
+#endif
diff --git a/include/linux/regulator/of_regulator.h b/include/linux/regulator/of_regulator.h
new file mode 100644
index 0000000000..265b98d1ee
--- /dev/null
+++ b/include/linux/regulator/of_regulator.h
@@ -0,0 +1,48 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * OpenFirmware regulator support routines
+ */
+
+#ifndef __LINUX_OF_REG_H
+#define __LINUX_OF_REG_H
+
+#include <linux/types.h>
+
+struct device_d;
+struct regulator_desc;
+
+struct of_regulator_match {
+ const char *name;
+ void *driver_data;
+ struct regulator_init_data *init_data;
+ struct device_node *of_node;
+ const struct regulator_desc *desc;
+};
+
+#if defined(CONFIG_OFDEVICE)
+extern struct regulator_init_data
+ *of_get_regulator_init_data(struct device_d *dev,
+ struct device_node *node,
+ const struct regulator_desc *desc);
+extern int of_regulator_match(struct device_d *dev, struct device_node *node,
+ struct of_regulator_match *matches,
+ unsigned int num_matches);
+#else
+static inline struct regulator_init_data
+ *of_get_regulator_init_data(struct device_d *dev,
+ struct device_node *node,
+ const struct regulator_desc *desc)
+{
+ return NULL;
+}
+
+static inline int of_regulator_match(struct device_d *dev,
+ struct device_node *node,
+ struct of_regulator_match *matches,
+ unsigned int num_matches)
+{
+ return 0;
+}
+#endif /* CONFIG_OF */
+
+#endif /* __LINUX_OF_REG_H */
diff --git a/include/param.h b/include/param.h
index dea6990497..4ac502e726 100644
--- a/include/param.h
+++ b/include/param.h
@@ -264,8 +264,6 @@ static inline struct param_d *dev_add_param_bool_ro(struct device_d *dev, const
}
static inline struct param_d *dev_add_param_string_ro(struct device_d *dev, const char *name,
- int (*set)(struct param_d *p, void *priv),
- int (*get)(struct param_d *p, void *priv),
char **value, void *priv)
{
return dev_add_param_string(dev, name, param_set_readonly, NULL, value, NULL);
@@ -285,9 +283,7 @@ static inline struct param_d *dev_add_param_enum_ro(struct device_d *dev, const
}
static inline struct param_d *dev_add_param_bitmask_ro(struct device_d *dev, const char *name,
- int (*set)(struct param_d *p, void *priv),
- int (*get)(struct param_d *p, void *priv),
- unsigned long *value, const char * const *names, int max, void *priv)
+ unsigned long *value, const char * const *names, int max)
{
return dev_add_param_bitmask(dev, name, param_set_readonly, NULL,
value, names, max, NULL);
diff --git a/include/regulator.h b/include/regulator.h
index cd1d3ccf55..156acb82f8 100644
--- a/include/regulator.h
+++ b/include/regulator.h
@@ -4,6 +4,35 @@
/* struct regulator is an opaque object for consumers */
struct regulator;
+/**
+ * struct regulator_desc - Static regulator descriptor
+ *
+ * Each regulator registered with the core is described with a
+ * structure of this type and a struct regulator_config. This
+ * structure contains the non-varying parts of the regulator
+ * description.
+ *
+ * @n_voltages: Number of selectors available for ops.list_voltage().
+ * @ops: Regulator operations table.
+ *
+ * @min_uV: Voltage given by the lowest selector (if linear mapping)
+ * @uV_step: Voltage increase with each selector (if linear mapping)
+ * @linear_min_sel: Minimal selector for starting linear mapping
+ *
+ * @vsel_reg: Register for selector when using regulator_regmap_X_voltage_
+ * @vsel_mask: Mask for register bitfield used for selector
+ * @apply_reg: Register for initiate voltage change on the output when
+ * using regulator_set_voltage_sel_regmap
+ * @apply_bit: Register bitfield used for initiate voltage change on the
+ * output when using regulator_set_voltage_sel_regmap
+ * @enable_reg: Register for control when using regmap enable/disable ops
+ * @enable_mask: Mask for control when using regmap enable/disable ops
+ * @enable_val: Enabling value for control when using regmap enable/disable ops
+ * @disable_val: Disabling value for control when using regmap enable/disable ops
+ * @enable_is_inverted: A flag to indicate set enable_mask bits to disable
+ * when using regulator_enable_regmap and friends APIs.
+ */
+
struct regulator_desc {
unsigned n_voltages;
const struct regulator_ops *ops;
@@ -21,6 +50,9 @@ struct regulator_desc {
unsigned int enable_val;
unsigned int disable_val;
bool enable_is_inverted;
+
+ const struct regulator_linear_range *linear_ranges;
+ int n_linear_ranges;
};
struct regulator_dev {
@@ -37,8 +69,36 @@ struct regulator_ops {
int (*list_voltage) (struct regulator_dev *, unsigned int);
int (*set_voltage_sel) (struct regulator_dev *, unsigned int);
+ int (*map_voltage)(struct regulator_dev *, int min_uV, int max_uV);
+};
+
+/*
+ * struct regulator_linear_range - specify linear voltage ranges
+ *
+ * Specify a range of voltages for regulator_map_linear_range() and
+ * regulator_list_linear_range().
+ *
+ * @min_uV: Lowest voltage in range
+ * @min_sel: Lowest selector for range
+ * @max_sel: Highest selector for range
+ * @uV_step: Step size
+ */
+struct regulator_linear_range {
+ unsigned int min_uV;
+ unsigned int min_sel;
+ unsigned int max_sel;
+ unsigned int uV_step;
};
+/* Initialize struct regulator_linear_range */
+#define REGULATOR_LINEAR_RANGE(_min_uV, _min_sel, _max_sel, _step_uV) \
+{ \
+ .min_uV = _min_uV, \
+ .min_sel = _min_sel, \
+ .max_sel = _max_sel, \
+ .uV_step = _step_uV, \
+}
+
#ifdef CONFIG_OFDEVICE
int of_regulator_register(struct regulator_dev *rd, struct device_node *node);
#else
@@ -65,8 +125,22 @@ int regulator_set_voltage_sel_regmap(struct regulator_dev *, unsigned);
int regulator_set_voltage(struct regulator *regulator, int min_uV, int max_uV);
int regulator_map_voltage_linear(struct regulator_dev *rdev,
int min_uV, int max_uV);
+int regulator_map_voltage_linear_range(struct regulator_dev *rdev,
+ int min_uV, int max_uV);
int regulator_list_voltage_linear(struct regulator_dev *rdev,
unsigned int selector);
+int regulator_list_voltage_linear_range(struct regulator_dev *rdev,
+ unsigned int selector);
+int regulator_get_voltage_sel_regmap(struct regulator_dev *rdev);
+int regulator_map_voltage_iterate(struct regulator_dev *rdev,
+ int min_uV, int max_uV);
+
+/*
+ * Helper functions intended to be used by regulator drivers prior registering
+ * their regulators.
+ */
+int regulator_desc_list_voltage_linear_range(const struct regulator_desc *desc,
+ unsigned int selector);
#else
static inline struct regulator *regulator_get(struct device_d *dev, const char *id)
diff --git a/lib/libfile.c b/lib/libfile.c
index 02078dd43d..5a1817e32a 100644
--- a/lib/libfile.c
+++ b/lib/libfile.c
@@ -332,7 +332,7 @@ int copy_file(const char *src, const char *dst, int verbose)
{
char *rw_buf = NULL;
int srcfd = 0, dstfd = 0;
- int r;
+ int r, s;
int ret = 1, err1 = 0;
int mode;
int total = 0;
@@ -343,22 +343,27 @@ int copy_file(const char *src, const char *dst, int verbose)
srcfd = open(src, O_RDONLY);
if (srcfd < 0) {
printf("could not open %s: %s\n", src, errno_str());
+ ret = srcfd;
goto out;
}
mode = O_WRONLY | O_CREAT;
- ret = stat(dst, &dststat);
- if (ret && ret != -ENOENT)
+ s = stat(dst, &dststat);
+ if (s && s != -ENOENT) {
+ printf("could not stat %s: %s\n", dst, errno_str());
+ ret = s;
goto out;
+ }
/* Set O_TRUNC only if file exist and is a regular file */
- if (!ret && S_ISREG(dststat.st_mode))
+ if (!s && S_ISREG(dststat.st_mode))
mode |= O_TRUNC;
dstfd = open(dst, mode);
if (dstfd < 0) {
printf("could not open %s: %s\n", dst, errno_str());
+ ret = dstfd;
goto out;
}
@@ -373,12 +378,14 @@ int copy_file(const char *src, const char *dst, int verbose)
r = read(srcfd, rw_buf, RW_BUF_SIZE);
if (r < 0) {
perror("read");
+ ret = r;
goto out;
}
if (!r)
break;
- if (write_full(dstfd, rw_buf, r) < 0) {
+ ret = write_full(dstfd, rw_buf, r);
+ if (ret < 0) {
perror("write");
goto out;
}
diff --git a/lib/parameter.c b/lib/parameter.c
index 00e9a9ff4e..fdbb2e71d1 100644
--- a/lib/parameter.c
+++ b/lib/parameter.c
@@ -253,11 +253,14 @@ static int param_string_set(struct device_d *dev, struct param_d *p, const char
struct param_string *ps = to_param_string(p);
int ret;
char *value_save = *ps->value;
+ char *value_new;
if (!val)
val = "";
- *ps->value = xstrdup(val);
+ value_new = xstrdup(val);
+ value_new = strim(value_new);
+ *ps->value = value_new;
if (!ps->set)
return 0;
diff --git a/lib/readline.c b/lib/readline.c
index d026af1104..3d16c1838c 100644
--- a/lib/readline.c
+++ b/lib/readline.c
@@ -290,9 +290,17 @@ int readline(const char *prompt, char *buf, int len)
insert = !insert;
break;
case BB_KEY_ERASE_LINE:
+ BEGINNING_OF_LINE();
+ ERASE_TO_EOL();
+ break;
case CTL_CH('u'):
+ wlen = eol_num - num;
+ memmove(buf, buf+num, wlen);
BEGINNING_OF_LINE();
ERASE_TO_EOL();
+ eol_num = wlen;
+ REFRESH_TO_EOL();
+ BEGINNING_OF_LINE();
break;
case DEL:
case BB_KEY_DEL7:
diff --git a/scripts/Kbuild.include b/scripts/Kbuild.include
index fe0de87240..919f286162 100644
--- a/scripts/Kbuild.include
+++ b/scripts/Kbuild.include
@@ -134,11 +134,6 @@ cc-ifversion = $(shell [ $(call cc-version, $(CC)) $(1) $(2) ] && echo $(3))
ld-option = $(call try-run,\
$(CC) -x c /dev/null -c -o "$$TMPO" ; $(LD) $(1) "$$TMPO" -o "$$TMP",$(1),$(2))
-# ar-option
-# Usage: KBUILD_ARFLAGS := $(call ar-option,D)
-# Important: no spaces around options
-ar-option = $(call try-run, $(AR) rc$(1) "$$TMP",$(1),$(2))
-
######
###