summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Documentation/boards/efi.rst2
-rw-r--r--Documentation/boards/stm32mp.rst28
-rw-r--r--Documentation/user/user-manual.rst1
-rw-r--r--Documentation/user/watchdog.rst91
-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--commands/wd.c34
-rw-r--r--common/Kconfig6
-rw-r--r--common/boot.c3
-rw-r--r--common/efi-devicepath.c2
-rw-r--r--common/efi-guid.c2
-rw-r--r--common/efi/efi-image.c1
-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/da9063.c14
-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/efi_wdt.c1
-rw-r--r--drivers/watchdog/stm32_iwdg.c1
-rw-r--r--drivers/watchdog/stpmic1_wdt.c6
-rw-r--r--drivers/watchdog/wd_core.c73
-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--include/watchdog.h20
-rw-r--r--lib/libfile.c17
-rw-r--r--lib/parameter.c5
-rw-r--r--lib/readline.c8
-rw-r--r--scripts/Kbuild.include5
152 files changed, 5986 insertions, 535 deletions
diff --git a/Documentation/boards/efi.rst b/Documentation/boards/efi.rst
index 2178c9ab42..f04b1d3237 100644
--- a/Documentation/boards/efi.rst
+++ b/Documentation/boards/efi.rst
@@ -350,7 +350,7 @@ https://uefi.org/sites/default/files/resources/UEFI_Spec_2_1_D.pdf
Current linux kernel (v5.0) will execute ExitBootServices() during the early
boot stage and thus will automatically disable the (U)EFI watchdog. Since it is
-a proper behavior according to the (U)EFI specification, it is impossible to
+the proper behavior according to the (U)EFI specification, it is impossible to
protect full boot chain by using this watchdog only. It is recommended to use
an alternative hardware watchdog, preferably started before the bootloader. If (U)EFI
firmware lacks this feature, the bootloader should be able to start an alternative
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/Documentation/user/user-manual.rst b/Documentation/user/user-manual.rst
index f04981c3f0..41fdb8805c 100644
--- a/Documentation/user/user-manual.rst
+++ b/Documentation/user/user-manual.rst
@@ -34,6 +34,7 @@ Contents:
state
random
debugging
+ watchdog
* :ref:`search`
* :ref:`genindex`
diff --git a/Documentation/user/watchdog.rst b/Documentation/user/watchdog.rst
new file mode 100644
index 0000000000..02bd576a89
--- /dev/null
+++ b/Documentation/user/watchdog.rst
@@ -0,0 +1,91 @@
+Watchdog Support
+================
+
+Barebox Watchdog Functionality
+------------------------------
+
+In some cases we are not able to influence the hardware design anymore or while
+developing one needs to be able to feed the watchdog to disable it from within
+the bootloader. For these scenarios barebox provides the watchdog framework
+with the following functionality and at least ``CONFIG_WATCHDOG`` should be
+enabled.
+
+Polling
+~~~~~~~
+
+Watchdog polling/feeding allows to feed the watchdog and keep it running on one
+side and to not reset the system on the other side. It is needed on hardware
+with short-time watchdogs. For example the Atheros ar9331 watchdog has a
+maximal timeout of 7 seconds, so it may reset even on netboot.
+Or it can be used on systems where the watchdog is already running and can't be
+disabled, an example for that is the watchdog of the i.MX2 series.
+This functionally can be seen as a threat, since in error cases barebox will
+continue to feed the watchdog even if that is not desired. So, depending on
+your needs ``CONFIG_WATCHDOG_POLLER`` can be enabled or disabled at compile
+time. Even if barebox was built with watchdog polling support, it is not
+enabled by default. To start polling from command line run:
+
+.. code-block:: console
+
+ wdog0.autoping=1
+
+**NOTE** Using this feature might have the effect that the watchdog is
+effectively disabled. In case barebox is stuck in a loop that includes feeding
+the watchdog, then the watchdog will never trigger. Only use this feature
+during development or when a bad watchdog design (Short watchdog timeout
+enabled as boot default) doesn't give you another choice.
+
+The poller interval is not configurable, but fixed at 500ms and the watchdog
+timeout is configured by default to the maximum of the supported values by
+hardware. To change the timeout used by the poller, run:
+
+.. code-block:: console
+
+ wdog0.timeout_cur=7
+
+To read the current watchdog's configuration, run:
+
+.. code-block:: console
+
+ devinfo wdog0
+
+The output may look as follows where ``timeout_cur`` and ``timeout_max`` are
+measured in seconds:
+
+.. code-block:: console
+
+ barebox@DPTechnics DPT-Module:/ devinfo wdog0
+ Parameters:
+ autoping: 1 (type: bool)
+ timeout_cur: 7 (type: uint32)
+ timeout_max: 10 (type: uint32)
+
+Use barebox' environment to persist these changes between reboots:
+
+.. code-block:: console
+
+ nv dev.wdog0.autoping=1
+ nv dev.wdog0.timeout_cur=7
+
+Boot Watchdog Timeout
+~~~~~~~~~~~~~~~~~~~~~
+
+With this functionality barebox may start a watchdog or update the timeout of
+an already-running one, just before kicking the boot image. It can be
+configured temporarily via
+
+.. code-block:: console
+
+ global boot.watchdog_timeout=10
+
+or persistently by
+
+.. code-block:: console
+
+ nv boot.watchdog_timeout=10
+
+where the used value again is measured in seconds.
+
+On a system with multiple watchdogs, the watchdog with the highest positive
+priority is the one affected by the ``boot.watchdog_timeout`` parameter. If
+multiple watchdogs share the same priority, only one will be started.
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/commands/wd.c b/commands/wd.c
index 26823f869a..8029bab1ce 100644
--- a/commands/wd.c
+++ b/commands/wd.c
@@ -16,6 +16,8 @@
#include <command.h>
#include <errno.h>
#include <linux/ctype.h>
+#include <getopt.h>
+#include <complete.h>
#include <watchdog.h>
/* default timeout in [sec] */
@@ -23,18 +25,30 @@ static unsigned timeout = CONFIG_CMD_WD_DEFAULT_TIMOUT;
static int do_wd(int argc, char *argv[])
{
+ struct watchdog *wd = watchdog_get_default();
+ int opt;
int rc;
- if (argc > 1) {
- if (isdigit(*argv[1])) {
- timeout = simple_strtoul(argv[1], NULL, 0);
+ while ((opt = getopt(argc, argv, "d:")) > 0) {
+ switch (opt) {
+ case 'd':
+ wd = watchdog_get_by_name(optarg);
+ break;
+ default:
+ return COMMAND_ERROR_USAGE;
+ }
+ }
+
+ if (optind < argc) {
+ if (isdigit(*argv[optind])) {
+ timeout = simple_strtoul(argv[optind], NULL, 0);
} else {
printf("numerical parameter expected\n");
- return 1;
+ return COMMAND_ERROR_USAGE;
}
}
- rc = watchdog_set_timeout(timeout);
+ rc = watchdog_set_timeout(wd, timeout);
if (rc < 0) {
switch (rc) {
case -EINVAL:
@@ -43,12 +57,15 @@ static int do_wd(int argc, char *argv[])
case -ENOSYS:
printf("Watchdog cannot be disabled\n");
break;
+ case -ENODEV:
+ printf("Watchdog device doesn't exist.\n");
+ break;
default:
printf("Watchdog fails: '%s'\n", strerror(-rc));
break;
}
- return 1;
+ return COMMAND_ERROR;
}
return 0;
@@ -58,12 +75,15 @@ BAREBOX_CMD_HELP_START(wd)
BAREBOX_CMD_HELP_TEXT("Enable the watchdog to bark in TIME seconds.")
BAREBOX_CMD_HELP_TEXT("When TIME is 0, the watchdog gets disabled,")
BAREBOX_CMD_HELP_TEXT("Without a parameter the watchdog will be re-triggered.")
+BAREBOX_CMD_HELP_TEXT("Options:")
+BAREBOX_CMD_HELP_OPT("-d DEVICE\t", "watchdog name (default is highest priority watchdog)")
BAREBOX_CMD_HELP_END
BAREBOX_CMD_START(wd)
.cmd = do_wd,
BAREBOX_CMD_DESC("enable/disable/trigger the watchdog")
- BAREBOX_CMD_OPTS("[TIME]")
+ BAREBOX_CMD_OPTS("[-d DEVICE] [TIME]")
BAREBOX_CMD_GROUP(CMD_GRP_HWMANIP)
BAREBOX_CMD_HELP(cmd_wd_help)
+ BAREBOX_CMD_COMPLETE(device_complete)
BAREBOX_CMD_END
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/boot.c b/common/boot.c
index 14d4fe9d64..dcbe5cc2ec 100644
--- a/common/boot.c
+++ b/common/boot.c
@@ -146,7 +146,8 @@ int boot_entry(struct bootentry *be, int verbose, int dryrun)
printf("Booting entry '%s'\n", be->title);
if (IS_ENABLED(CONFIG_WATCHDOG) && boot_watchdog_timeout) {
- ret = watchdog_set_timeout(boot_watchdog_timeout);
+ ret = watchdog_set_timeout(watchdog_get_default(),
+ boot_watchdog_timeout);
if (ret)
pr_warn("Failed to enable watchdog: %s\n", strerror(-ret));
}
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-image.c b/common/efi/efi-image.c
index 939663a6e2..9c66c9f882 100644
--- a/common/efi/efi-image.c
+++ b/common/efi/efi-image.c
@@ -174,7 +174,6 @@ static inline void linux_efi_handover(efi_handle_t handle,
{
handover_fn handover;
- asm volatile ("cli");
handover = (handover_fn)((long)header->code32_start + 512 +
header->handover_offset);
handover(handle, efi_sys_table, header);
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/da9063.c b/drivers/mfd/da9063.c
index b61e764876..e1343bac76 100644
--- a/drivers/mfd/da9063.c
+++ b/drivers/mfd/da9063.c
@@ -14,6 +14,7 @@
*/
#include <common.h>
+#include <clock.h>
#include <driver.h>
#include <gpio.h>
#include <restart.h>
@@ -33,6 +34,7 @@ struct da9063 {
struct i2c_client *client1;
struct device_d *dev;
unsigned int timeout;
+ uint64_t last_ping;
};
/* forbidden/impossible value; timeout will be set to this value initially to
@@ -237,6 +239,14 @@ static int da9063_watchdog_ping(struct da9063 *priv)
int ret;
u8 val;
+ /*
+ * The watchdog has a cool down phase of 200ms and if we ping to fast
+ * the da9062/3 resets the system. Reject those requests has a maximum
+ * failure of 10% if the watchdog timeout is set to 2.048s.
+ */
+ if (!is_timeout(priv->last_ping, 200 * MSECOND))
+ return 0;
+
dev_dbg(priv->dev, "ping\n");
/* reset watchdog timer; register is self clearing */
@@ -245,6 +255,8 @@ static int da9063_watchdog_ping(struct da9063 *priv)
if (ret < 0)
return ret;
+ priv->last_ping = get_time_ns();
+
return 0;
}
@@ -270,7 +282,7 @@ static int da9063_watchdog_set_timeout(struct watchdog *wd, unsigned timeout)
while (timeout > (2048 << scale) && scale <= 6)
scale++;
dev_dbg(dev, "calculated TWDSCALE=%u (req=%ims calc=%ims)\n",
- scale, timeout, 2048 << scale);
+ scale + 1, timeout, 2048 << scale);
scale++; /* scale 0 disables the WD */
}
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/efi_wdt.c b/drivers/watchdog/efi_wdt.c
index 8e3e51b7a9..ea1ede1381 100644
--- a/drivers/watchdog/efi_wdt.c
+++ b/drivers/watchdog/efi_wdt.c
@@ -41,6 +41,7 @@ static int efi_wdt_probe(struct device_d *dev)
priv->wd.set_timeout = efi_wdt_set_timeout;
priv->wd.hwdev = dev;
priv->dev = dev;
+ priv->wd.priority = WATCHDOG_DEFAULT_PRIORITY - 50;
dev->priv = priv;
diff --git a/drivers/watchdog/stm32_iwdg.c b/drivers/watchdog/stm32_iwdg.c
index 20536cb4ab..4d252e558c 100644
--- a/drivers/watchdog/stm32_iwdg.c
+++ b/drivers/watchdog/stm32_iwdg.c
@@ -256,7 +256,6 @@ static int stm32_iwdg_probe(struct device_d *dev)
wdd->set_timeout = stm32_iwdg_set_timeout;
wdd->timeout_max = (RLR_MAX + 1) * data->max_prescaler * 1000;
wdd->timeout_max /= wd->rate * 1000;
- wdd->timeout_cur = wdd->timeout_max;
ret = watchdog_register(wdd);
if (ret) {
diff --git a/drivers/watchdog/stpmic1_wdt.c b/drivers/watchdog/stpmic1_wdt.c
index eb8c43f716..9b7a586387 100644
--- a/drivers/watchdog/stpmic1_wdt.c
+++ b/drivers/watchdog/stpmic1_wdt.c
@@ -169,13 +169,15 @@ 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;
wdd->set_timeout = stpmic1_wdt_set_timeout;
wdd->timeout_max = PMIC_WDT_MAX_TIMEOUT;
- wdd->timeout_cur = PMIC_WDT_DEFAULT_TIMEOUT;
/* have the watchdog reset, not power-off the system */
regmap_write_bits(wdt->regmap, MAIN_CR, RREQ_EN, RREQ_EN);
diff --git a/drivers/watchdog/wd_core.c b/drivers/watchdog/wd_core.c
index e6e5ddecd2..8b13950238 100644
--- a/drivers/watchdog/wd_core.c
+++ b/drivers/watchdog/wd_core.c
@@ -31,8 +31,15 @@ static const char *watchdog_name(struct watchdog *wd)
return "unknown";
}
-static int _watchdog_set_timeout(struct watchdog *wd, unsigned timeout)
+/*
+ * start, stop or retrigger the watchdog
+ * timeout in [seconds]. timeout of '0' will disable the watchdog (if possible)
+ */
+int watchdog_set_timeout(struct watchdog *wd, unsigned timeout)
{
+ if (!wd)
+ return -ENODEV;
+
if (timeout > wd->timeout_max)
return -EINVAL;
@@ -40,12 +47,23 @@ static int _watchdog_set_timeout(struct watchdog *wd, unsigned timeout)
return wd->set_timeout(wd, timeout);
}
+EXPORT_SYMBOL(watchdog_set_timeout);
+
+static int watchdog_set_priority(struct param_d *param, void *priv)
+{
+ struct watchdog *wd = priv;
+
+ if (wd->priority == 0)
+ return watchdog_set_timeout(wd, 0);
+
+ return 0;
+}
static int watchdog_set_cur(struct param_d *param, void *priv)
{
struct watchdog *wd = priv;
- if (wd->timeout_cur > wd->timeout_max)
+ if (wd->poller_timeout_cur > wd->timeout_max)
return -EINVAL;
return 0;
@@ -55,7 +73,7 @@ static void watchdog_poller_cb(void *priv);
static void watchdog_poller_start(struct watchdog *wd)
{
- _watchdog_set_timeout(wd, wd->timeout_cur);
+ watchdog_set_timeout(wd, wd->poller_timeout_cur);
poller_call_async(&wd->poller, 500 * MSECOND,
watchdog_poller_cb, wd);
@@ -130,24 +148,31 @@ int watchdog_register(struct watchdog *wd)
if (!wd->priority)
wd->priority = WATCHDOG_DEFAULT_PRIORITY;
+ p = dev_add_param_uint32(&wd->dev, "priority",
+ watchdog_set_priority, NULL,
+ &wd->priority, "%u", wd);
+ if (IS_ERR(p))
+ return PTR_ERR(p);
+
/* set some default sane value */
if (!wd->timeout_max)
wd->timeout_max = 60 * 60 * 24;
- if (!wd->timeout_cur || wd->timeout_cur > wd->timeout_max)
- wd->timeout_cur = wd->timeout_max;
-
p = dev_add_param_uint32_ro(&wd->dev, "timeout_max",
&wd->timeout_max, "%u");
if (IS_ERR(p))
return PTR_ERR(p);
- p = dev_add_param_uint32(&wd->dev, "timeout_cur", watchdog_set_cur, NULL,
- &wd->timeout_cur, "%u", wd);
- if (IS_ERR(p))
- return PTR_ERR(p);
-
if (IS_ENABLED(CONFIG_WATCHDOG_POLLER)) {
+ if (!wd->poller_timeout_cur ||
+ wd->poller_timeout_cur > wd->timeout_max)
+ wd->poller_timeout_cur = wd->timeout_max;
+
+ p = dev_add_param_uint32(&wd->dev, "timeout_cur", watchdog_set_cur,
+ NULL, &wd->poller_timeout_cur, "%u", wd);
+ if (IS_ERR(p))
+ return PTR_ERR(p);
+
ret = watchdog_register_poller(wd);
if (ret)
return ret;
@@ -176,7 +201,7 @@ int watchdog_deregister(struct watchdog *wd)
}
EXPORT_SYMBOL(watchdog_deregister);
-static struct watchdog *watchdog_get_default(void)
+struct watchdog *watchdog_get_default(void)
{
struct watchdog *tmp, *wd = NULL;
int priority = 0;
@@ -190,23 +215,23 @@ static struct watchdog *watchdog_get_default(void)
return wd;
}
+EXPORT_SYMBOL(watchdog_get_default);
-/*
- * start, stop or retrigger the watchdog
- * timeout in [seconds]. timeout of '0' will disable the watchdog (if possible)
- */
-int watchdog_set_timeout(unsigned timeout)
+struct watchdog *watchdog_get_by_name(const char *name)
{
- struct watchdog *wd;
+ struct watchdog *tmp;
+ struct device_d *dev = get_device_by_name(name);
+ if (!dev)
+ return NULL;
- wd = watchdog_get_default();
-
- if (!wd)
- return -ENODEV;
+ list_for_each_entry(tmp, &watchdog_list, list) {
+ if (dev == tmp->hwdev || dev == &tmp->dev)
+ return tmp;
+ }
- return _watchdog_set_timeout(wd, timeout);
+ return NULL;
}
-EXPORT_SYMBOL(watchdog_set_timeout);
+EXPORT_SYMBOL(watchdog_get_by_name);
/**
* of_get_watchdog_priority() - get the desired watchdog priority from device tree
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/include/watchdog.h b/include/watchdog.h
index 0db4263a31..184a218916 100644
--- a/include/watchdog.h
+++ b/include/watchdog.h
@@ -14,6 +14,7 @@
# define INCLUDE_WATCHDOG_H
#include <poller.h>
+#include <driver.h>
struct watchdog {
int (*set_timeout)(struct watchdog *, unsigned);
@@ -22,7 +23,7 @@ struct watchdog {
struct device_d dev;
unsigned int priority;
unsigned int timeout_max;
- unsigned int timeout_cur;
+ unsigned int poller_timeout_cur;
unsigned int poller_enable;
struct poller_async poller;
struct list_head list;
@@ -31,7 +32,9 @@ struct watchdog {
#ifdef CONFIG_WATCHDOG
int watchdog_register(struct watchdog *);
int watchdog_deregister(struct watchdog *);
-int watchdog_set_timeout(unsigned);
+struct watchdog *watchdog_get_default(void);
+struct watchdog *watchdog_get_by_name(const char *name);
+int watchdog_set_timeout(struct watchdog*, unsigned);
unsigned int of_get_watchdog_priority(struct device_node *node);
#else
static inline int watchdog_register(struct watchdog *w)
@@ -44,11 +47,22 @@ static inline int watchdog_deregister(struct watchdog *w)
return 0;
}
-static inline int watchdog_set_timeout(unsigned t)
+static inline struct watchdog *watchdog_get_default(void)
+{
+ return NULL;
+}
+
+static inline struct watchdog *watchdog_get_by_name(const char *name)
+{
+ return NULL;
+}
+
+static inline int watchdog_set_timeout(struct watchdog*w, unsigned t)
{
return 0;
}
+
static inline unsigned int of_get_watchdog_priority(struct device_node *node)
{
return 0;
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))
-
######
###