F: doc/arch/m68k.rst
F: drivers/watchdog/mcf_wdt.c
+CPU
+S: Maintained
+F: cmd/cpu.c
+F: doc/usage/cpu.rst
+
CYCLIC
S: Maintained
imx7-cm.dtb \
imx7d-colibri-emmc-eval-v3.dtb \
imx7d-colibri-eval-v3.dtb \
- imx7s-warp.dtb \
imx7d-meerkat96.dtb \
imx7d-pico-pi.dtb \
imx7d-pico-hobbit.dtb \
+++ /dev/null
-// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
-/*
- * Copyright (C) 2016 NXP Semiconductors.
- */
-
-/dts-v1/;
-
-#include <dt-bindings/input/input.h>
-#include "imx7s.dtsi"
-
-/ {
- model = "Element14 Warp i.MX7 Board";
- compatible = "element14,imx7s-warp", "fsl,imx7s";
-
- memory@80000000 {
- device_type = "memory";
- reg = <0x80000000 0x20000000>;
- };
-
- gpio-keys {
- compatible = "gpio-keys";
- pinctrl-0 = <&pinctrl_gpio>;
- autorepeat;
-
- back {
- label = "Back";
- gpios = <&gpio7 1 GPIO_ACTIVE_HIGH>;
- linux,code = <KEY_BACK>;
- wakeup-source;
- };
- };
-
- reg_brcm: regulator-brcm {
- compatible = "regulator-fixed";
- enable-active-high;
- gpio = <&gpio5 10 GPIO_ACTIVE_HIGH>;
- pinctrl-names = "default";
- pinctrl-0 = <&pinctrl_brcm_reg>;
- regulator-name = "brcm_reg";
- regulator-min-microvolt = <3300000>;
- regulator-max-microvolt = <3300000>;
- startup-delay-us = <200000>;
- };
-
- reg_bt: regulator-bt {
- compatible = "regulator-fixed";
- pinctrl-names = "default";
- pinctrl-0 = <&pinctrl_bt_reg>;
- enable-active-high;
- gpio = <&gpio5 17 GPIO_ACTIVE_HIGH>;
- regulator-name = "bt_reg";
- regulator-min-microvolt = <3300000>;
- regulator-max-microvolt = <3300000>;
- regulator-always-on;
- };
-
- reg_peri_3p15v: regulator-peri-3p15v {
- compatible = "regulator-fixed";
- regulator-name = "peri_3p15v_reg";
- regulator-min-microvolt = <3150000>;
- regulator-max-microvolt = <3150000>;
- regulator-always-on;
- };
-
- sound {
- compatible = "simple-audio-card";
- simple-audio-card,name = "imx7-sgtl5000";
- simple-audio-card,format = "i2s";
- simple-audio-card,bitclock-master = <&dailink_master>;
- simple-audio-card,frame-master = <&dailink_master>;
- simple-audio-card,cpu {
- sound-dai = <&sai1>;
- };
-
- dailink_master: simple-audio-card,codec {
- sound-dai = <&codec>;
- clocks = <&clks IMX7D_AUDIO_MCLK_ROOT_DIV>;
- };
- };
-};
-
-&clks {
- assigned-clocks = <&clks IMX7D_PLL_AUDIO_POST_DIV>;
- assigned-clock-rates = <884736000>;
-};
-
-&csi {
- status = "okay";
-};
-
-&i2c1 {
- pinctrl-names = "default";
- pinctrl-0 = <&pinctrl_i2c1>;
- status = "okay";
-
- pmic: pfuze3000@8 {
- compatible = "fsl,pfuze3000";
- reg = <0x08>;
-
- regulators {
- sw1a_reg: sw1a {
- regulator-min-microvolt = <700000>;
- regulator-max-microvolt = <1475000>;
- regulator-boot-on;
- regulator-always-on;
- regulator-ramp-delay = <6250>;
- };
-
- /* use sw1c_reg to align with pfuze100/pfuze200 */
- sw1c_reg: sw1b {
- regulator-min-microvolt = <700000>;
- regulator-max-microvolt = <1475000>;
- regulator-boot-on;
- regulator-always-on;
- regulator-ramp-delay = <6250>;
- };
-
- sw2_reg: sw2 {
- regulator-min-microvolt = <1500000>;
- regulator-max-microvolt = <1850000>;
- regulator-boot-on;
- regulator-always-on;
- };
-
- sw3a_reg: sw3 {
- regulator-min-microvolt = <900000>;
- regulator-max-microvolt = <1650000>;
- regulator-boot-on;
- regulator-always-on;
- };
-
- swbst_reg: swbst {
- regulator-min-microvolt = <5000000>;
- regulator-max-microvolt = <5150000>;
- regulator-boot-on;
- regulator-always-on;
- };
-
- snvs_reg: vsnvs {
- regulator-min-microvolt = <1000000>;
- regulator-max-microvolt = <3000000>;
- regulator-boot-on;
- regulator-always-on;
- };
-
- vref_reg: vrefddr {
- regulator-boot-on;
- regulator-always-on;
- };
-
- vgen1_reg: vldo1 {
- regulator-min-microvolt = <1800000>;
- regulator-max-microvolt = <3300000>;
- regulator-always-on;
- };
-
- vgen2_reg: vldo2 {
- regulator-min-microvolt = <800000>;
- regulator-max-microvolt = <1550000>;
- };
-
- vgen3_reg: vccsd {
- regulator-min-microvolt = <2850000>;
- regulator-max-microvolt = <3300000>;
- regulator-always-on;
- };
-
- vgen4_reg: v33 {
- regulator-min-microvolt = <2850000>;
- regulator-max-microvolt = <3300000>;
- regulator-always-on;
- };
-
- vgen5_reg: vldo3 {
- regulator-min-microvolt = <1800000>;
- regulator-max-microvolt = <3300000>;
- regulator-always-on;
- };
-
- vgen6_reg: vldo4 {
- regulator-min-microvolt = <1800000>;
- regulator-max-microvolt = <3300000>;
- regulator-always-on;
- };
- };
- };
-};
-
-&i2c2 {
- clock-frequency = <100000>;
- pinctrl-names = "default";
- pinctrl-0 = <&pinctrl_i2c2>;
- status = "okay";
-
- ov2680: camera@36 {
- compatible = "ovti,ov2680";
- pinctrl-names = "default";
- pinctrl-0 = <&pinctrl_ov2680>;
- reg = <0x36>;
- clocks = <&osc>;
- clock-names = "xvclk";
- reset-gpios = <&gpio1 3 GPIO_ACTIVE_LOW>;
- DOVDD-supply = <&sw2_reg>;
- DVDD-supply = <&sw2_reg>;
- AVDD-supply = <®_peri_3p15v>;
-
- port {
- ov2680_to_mipi: endpoint {
- remote-endpoint = <&mipi_from_sensor>;
- clock-lanes = <0>;
- data-lanes = <1>;
- };
- };
- };
-};
-
-&i2c3 {
- clock-frequency = <100000>;
- pinctrl-names = "default";
- pinctrl-0 = <&pinctrl_i2c3>;
- status = "okay";
-};
-
-&i2c4 {
- clock-frequency = <100000>;
- pinctrl-names = "default";
- pinctrl-0 = <&pinctrl_i2c4>;
- status = "okay";
-
- codec: sgtl5000@a {
- #sound-dai-cells = <0>;
- reg = <0x0a>;
- compatible = "fsl,sgtl5000";
- clocks = <&clks IMX7D_AUDIO_MCLK_ROOT_DIV>;
- pinctrl-names = "default";
- pinctrl-0 = <&pinctrl_sai1_mclk>;
- VDDA-supply = <&vgen4_reg>;
- VDDIO-supply = <&vgen4_reg>;
- VDDD-supply = <&vgen2_reg>;
- };
-
- mpl3115@60 {
- compatible = "fsl,mpl3115";
- reg = <0x60>;
- };
-};
-
-&mipi_csi {
- clock-frequency = <166000000>;
- status = "okay";
-
- ports {
- port@0 {
- reg = <0>;
-
- mipi_from_sensor: endpoint {
- remote-endpoint = <&ov2680_to_mipi>;
- data-lanes = <1>;
- };
- };
- };
-};
-
-&sai1 {
- pinctrl-names = "default";
- pinctrl-0 = <&pinctrl_sai1>;
- assigned-clocks = <&clks IMX7D_SAI1_ROOT_SRC>,
- <&clks IMX7D_SAI1_ROOT_CLK>;
- assigned-clock-parents = <&clks IMX7D_PLL_AUDIO_POST_DIV>;
- assigned-clock-rates = <0>, <36864000>;
- status = "okay";
-};
-
-&uart1 {
- pinctrl-names = "default";
- pinctrl-0 = <&pinctrl_uart1>;
- assigned-clocks = <&clks IMX7D_UART1_ROOT_SRC>;
- assigned-clock-parents = <&clks IMX7D_PLL_SYS_MAIN_240M_CLK>;
- status = "okay";
-};
-
-&uart3 {
- pinctrl-names = "default";
- pinctrl-0 = <&pinctrl_uart3>;
- assigned-clocks = <&clks IMX7D_UART3_ROOT_SRC>;
- assigned-clock-parents = <&clks IMX7D_PLL_SYS_MAIN_240M_CLK>;
- uart-has-rtscts;
- status = "okay";
-};
-
-&uart6 {
- pinctrl-names = "default";
- pinctrl-0 = <&pinctrl_uart6>;
- assigned-clocks = <&clks IMX7D_UART6_ROOT_SRC>;
- assigned-clock-parents = <&clks IMX7D_PLL_SYS_MAIN_240M_CLK>;
- fsl,dte-mode;
- status = "okay";
-};
-
-&usbotg1 {
- dr_mode = "peripheral";
- status = "okay";
-};
-
-&usdhc1 {
- pinctrl-names = "default";
- pinctrl-0 = <&pinctrl_usdhc1>;
- bus-width = <4>;
- keep-power-in-suspend;
- no-1-8-v;
- non-removable;
- vmmc-supply = <®_brcm>;
- status = "okay";
-};
-
-&usdhc3 {
- pinctrl-names = "default", "state_100mhz", "state_200mhz";
- pinctrl-0 = <&pinctrl_usdhc3>;
- pinctrl-1 = <&pinctrl_usdhc3_100mhz>;
- pinctrl-2 = <&pinctrl_usdhc3_200mhz>;
- assigned-clocks = <&clks IMX7D_USDHC3_ROOT_CLK>;
- assigned-clock-rates = <400000000>;
- bus-width = <8>;
- no-1-8-v;
- fsl,tuning-step = <2>;
- non-removable;
- status = "okay";
-};
-
-&video_mux {
- status = "okay";
-};
-
-&wdog1 {
- pinctrl-names = "default";
- pinctrl-0 = <&pinctrl_wdog>;
- fsl,ext-reset-output;
- status = "okay";
-};
-
-&iomuxc {
- pinctrl_brcm_reg: brcmreggrp {
- fsl,pins = <
- MX7D_PAD_SD2_WP__GPIO5_IO10 0x14 /* WL_REG_ON */
- >;
- };
-
- pinctrl_bt_reg: btreggrp {
- fsl,pins = <
- MX7D_PAD_SD2_DATA3__GPIO5_IO17 0x14 /* BT_REG_ON */
- >;
- };
-
- pinctrl_gpio: gpiogrp {
- fsl,pins = <
- MX7D_PAD_ENET1_RGMII_RD1__GPIO7_IO1 0x14
- >;
- };
-
- pinctrl_i2c1: i2c1grp {
- fsl,pins = <
- MX7D_PAD_I2C1_SDA__I2C1_SDA 0x4000007f
- MX7D_PAD_I2C1_SCL__I2C1_SCL 0x4000007f
- >;
- };
-
- pinctrl_i2c2: i2c2grp {
- fsl,pins = <
- MX7D_PAD_I2C2_SDA__I2C2_SDA 0x4000007f
- MX7D_PAD_I2C2_SCL__I2C2_SCL 0x4000007f
- >;
- };
-
- pinctrl_i2c3: i2c3grp {
- fsl,pins = <
- MX7D_PAD_I2C3_SDA__I2C3_SDA 0x4000007f
- MX7D_PAD_I2C3_SCL__I2C3_SCL 0x4000007f
- >;
- };
-
- pinctrl_i2c4: i2c4grp {
- fsl,pins = <
- MX7D_PAD_I2C4_SCL__I2C4_SCL 0x4000007f
- MX7D_PAD_I2C4_SDA__I2C4_SDA 0x4000007f
- >;
- };
-
- pinctrl_ov2680: ov2660grp {
- fsl,pins = <
- MX7D_PAD_LPSR_GPIO1_IO03__GPIO1_IO3 0x14
- >;
- };
-
- pinctrl_sai1: sai1grp {
- fsl,pins = <
- MX7D_PAD_SAI1_RX_DATA__SAI1_RX_DATA0 0x1f
- MX7D_PAD_SAI1_TX_BCLK__SAI1_TX_BCLK 0x1f
- MX7D_PAD_SAI1_TX_SYNC__SAI1_TX_SYNC 0x1f
- MX7D_PAD_SAI1_TX_DATA__SAI1_TX_DATA0 0x30
- >;
- };
-
- pinctrl_sai1_mclk: sai1mclkgrp {
- fsl,pins = <
- MX7D_PAD_SAI1_MCLK__SAI1_MCLK 0x1f
- >;
- };
-
- pinctrl_uart1: uart1grp {
- fsl,pins = <
- MX7D_PAD_UART1_TX_DATA__UART1_DCE_TX 0x79
- MX7D_PAD_UART1_RX_DATA__UART1_DCE_RX 0x79
- >;
- };
-
- pinctrl_uart3: uart3grp {
- fsl,pins = <
- MX7D_PAD_UART3_TX_DATA__UART3_DCE_TX 0x79
- MX7D_PAD_UART3_RX_DATA__UART3_DCE_RX 0x79
- MX7D_PAD_UART3_CTS_B__UART3_DCE_CTS 0x79
- MX7D_PAD_UART3_RTS_B__UART3_DCE_RTS 0x79
- >;
- };
-
- pinctrl_uart6: uart6grp {
- fsl,pins = <
- MX7D_PAD_ECSPI1_MOSI__UART6_DTE_RX 0x79
- MX7D_PAD_ECSPI1_SCLK__UART6_DTE_TX 0x79
- >;
- };
-
- pinctrl_usdhc1: usdhc1grp {
- fsl,pins = <
- MX7D_PAD_SD1_CMD__SD1_CMD 0x59
- MX7D_PAD_SD1_CLK__SD1_CLK 0x19
- MX7D_PAD_SD1_DATA0__SD1_DATA0 0x59
- MX7D_PAD_SD1_DATA1__SD1_DATA1 0x59
- MX7D_PAD_SD1_DATA2__SD1_DATA2 0x59
- MX7D_PAD_SD1_DATA3__SD1_DATA3 0x59
- MX7D_PAD_SD2_RESET_B__GPIO5_IO11 0x14 /* WL_HOST_WAKE */
- >;
- };
-
- pinctrl_usdhc3: usdhc3grp {
- fsl,pins = <
- MX7D_PAD_SD3_CMD__SD3_CMD 0x59
- MX7D_PAD_SD3_CLK__SD3_CLK 0x19
- MX7D_PAD_SD3_DATA0__SD3_DATA0 0x59
- MX7D_PAD_SD3_DATA1__SD3_DATA1 0x59
- MX7D_PAD_SD3_DATA2__SD3_DATA2 0x59
- MX7D_PAD_SD3_DATA3__SD3_DATA3 0x59
- MX7D_PAD_SD3_DATA4__SD3_DATA4 0x59
- MX7D_PAD_SD3_DATA5__SD3_DATA5 0x59
- MX7D_PAD_SD3_DATA6__SD3_DATA6 0x59
- MX7D_PAD_SD3_DATA7__SD3_DATA7 0x59
- MX7D_PAD_SD3_RESET_B__SD3_RESET_B 0x19
- >;
- };
-
- pinctrl_usdhc3_100mhz: usdhc3grp_100mhz {
- fsl,pins = <
- MX7D_PAD_SD3_CMD__SD3_CMD 0x5a
- MX7D_PAD_SD3_CLK__SD3_CLK 0x1a
- MX7D_PAD_SD3_DATA0__SD3_DATA0 0x5a
- MX7D_PAD_SD3_DATA1__SD3_DATA1 0x5a
- MX7D_PAD_SD3_DATA2__SD3_DATA2 0x5a
- MX7D_PAD_SD3_DATA3__SD3_DATA3 0x5a
- MX7D_PAD_SD3_DATA4__SD3_DATA4 0x5a
- MX7D_PAD_SD3_DATA5__SD3_DATA5 0x5a
- MX7D_PAD_SD3_DATA6__SD3_DATA6 0x5a
- MX7D_PAD_SD3_DATA7__SD3_DATA7 0x5a
- MX7D_PAD_SD3_RESET_B__SD3_RESET_B 0x1a
- >;
- };
-
- pinctrl_usdhc3_200mhz: usdhc3grp_200mhz {
- fsl,pins = <
- MX7D_PAD_SD3_CMD__SD3_CMD 0x5b
- MX7D_PAD_SD3_CLK__SD3_CLK 0x1b
- MX7D_PAD_SD3_DATA0__SD3_DATA0 0x5b
- MX7D_PAD_SD3_DATA1__SD3_DATA1 0x5b
- MX7D_PAD_SD3_DATA2__SD3_DATA2 0x5b
- MX7D_PAD_SD3_DATA3__SD3_DATA3 0x5b
- MX7D_PAD_SD3_DATA4__SD3_DATA4 0x5b
- MX7D_PAD_SD3_DATA5__SD3_DATA5 0x5b
- MX7D_PAD_SD3_DATA6__SD3_DATA6 0x5b
- MX7D_PAD_SD3_DATA7__SD3_DATA7 0x5b
- MX7D_PAD_SD3_RESET_B__SD3_RESET_B 0x1b
- >;
- };
-};
-
-&iomuxc_lpsr {
- pinctrl_wdog: wdoggrp {
- fsl,pins = <
- MX7D_PAD_LPSR_GPIO1_IO00__WDOG1_WDOG_B 0x74
- >;
- };
-};
select DM_THERMAL
select MX7D
imply CMD_DM
+ imply OF_UPSTREAM
config TARGET_COLIBRI_IMX7
bool "Support Colibri iMX7S/iMX7D modules"
* Copyright (c) 2015 Google, Inc
+ * Copyright 2024 NXP
*/
#include <command.h>
"Device ID",
};
+static struct udevice *cpu_find_device(unsigned long cpu_id)
+{
+ struct udevice *dev;
+
+ for (uclass_first_device(UCLASS_CPU, &dev); dev;
+ uclass_next_device(&dev)) {
+ if (cpu_id == dev_seq(dev))
+ return dev;
+ }
+
+ return NULL;
+}
+
static int print_cpu_list(bool detail)
{
struct udevice *dev;
return 0;
}
+static int do_cpu_release(struct cmd_tbl *cmdtp, int flag, int argc,
+ char *const argv[])
+{
+ struct udevice *dev;
+ unsigned long cpu_id;
+ unsigned long long boot_addr;
+
+ if (argc != 3)
+ return CMD_RET_USAGE;
+
+ cpu_id = dectoul(argv[1], NULL);
+ dev = cpu_find_device(cpu_id);
+ if (!dev)
+ return CMD_RET_FAILURE;
+
+ boot_addr = simple_strtoull(argv[2], NULL, 16);
+
+ if (cpu_release_core(dev, boot_addr))
+ return CMD_RET_FAILURE;
+
+ return 0;
+}
+
U_BOOT_LONGHELP(cpu,
"list - list available CPUs\n"
- "cpu detail - show CPU detail");
+ "cpu detail - show CPU detail\n"
+ "cpu release <core ID> <addr> - Release CPU <core ID> at <addr>\n"
+ " <core ID>: the sequence number in list subcommand outputs");
U_BOOT_CMD_WITH_SUBCMDS(cpu, "display information about CPUs", cpu_help_text,
U_BOOT_SUBCMD_MKENT(list, 1, 1, do_cpu_list),
- U_BOOT_SUBCMD_MKENT(detail, 1, 0, do_cpu_detail));
+ U_BOOT_SUBCMD_MKENT(detail, 1, 0, do_cpu_detail),
+ U_BOOT_SUBCMD_MKENT(release, 3, 0, do_cpu_release));
if CYCLIC
+config SPL_CYCLIC
+ bool "General-purpose cyclic execution mechanism (SPL)"
+ help
+ This enables a general-purpose cyclic execution infrastructure in SPL,
+ to allow "small" (run-time wise) functions to be executed at
+ a specified frequency. Things like LED blinking or watchdog
+ triggering are examples for such tasks.
+
config CYCLIC_MAX_CPU_TIME_US
int "Sets the max allowed time for a cyclic function in us"
+ default 100000 if SANDBOX # sandbox video is quite slow
default 5000
help
The max allowed time for a cyclic function in us. If a functions
obj-y += dlmalloc.o
obj-$(CONFIG_$(SPL_TPL_)SYS_MALLOC_F) += malloc_simple.o
-obj-$(CONFIG_CYCLIC) += cyclic.o
+obj-$(CONFIG_$(SPL_TPL_)CYCLIC) += cyclic.o
obj-$(CONFIG_$(SPL_TPL_)EVENT) += event.o
obj-$(CONFIG_$(SPL_TPL_)HASH) += hash.o
CONFIG_SYS_PROMPT="u-boot=> "
# CONFIG_CMD_EXPORTENV is not set
# CONFIG_CMD_IMPORTENV is not set
+CONFIG_CMD_ERASEENV=y
# CONFIG_CMD_CRC32 is not set
CONFIG_CMD_EEPROM=y
CONFIG_SYS_I2C_EEPROM_ADDR_LEN=2
CONFIG_USB_GADGET_DOWNLOAD=y
CONFIG_SPL_USB_SDP_SUPPORT=y
CONFIG_IMX_WATCHDOG=y
+CONFIG_CPU=y
+CONFIG_CPU_IMX=y
+CONFIG_CMD_CPU=y
CONFIG_SYSRESET_WATCHDOG=y
CONFIG_DM_THERMAL=y
CONFIG_IMX_WATCHDOG=y
+CONFIG_CPU=y
+CONFIG_CPU_IMX=y
+CONFIG_CMD_CPU=y
CONFIG_USB_GADGET_VENDOR_NUM=0x0525
CONFIG_USB_GADGET_PRODUCT_NUM=0xa4a5
CONFIG_IMX_WATCHDOG=y
+CONFIG_CPU=y
+CONFIG_CPU_IMX=y
+CONFIG_CMD_CPU=y
# CONFIG_CMD_CRC32 is not set
CONFIG_CMD_MEMTEST=y
CONFIG_CMD_CLK=y
+CONFIG_CMD_CPU=y
CONFIG_CMD_DFU=y
CONFIG_CMD_FUSE=y
CONFIG_CMD_GPIO=y
CONFIG_DEFAULT_DEVICE_TREE="freescale/imx8mm-phyboard-polis-rdk"
CONFIG_SPL_TEXT_BASE=0x7E1000
CONFIG_TARGET_PHYCORE_IMX8MM=y
+CONFIG_DM_RESET=y
CONFIG_SYS_MONITOR_LEN=524288
CONFIG_SPL_MMC=y
CONFIG_SPL_SERIAL=y
CONFIG_SPL=y
CONFIG_ENV_OFFSET_REDUND=0x3E0000
CONFIG_SYS_LOAD_ADDR=0x40480000
+CONFIG_PCI=y
CONFIG_FIT=y
CONFIG_FIT_EXTERNAL_OFFSET=0x3000
CONFIG_SPL_LOAD_FIT=y
CONFIG_SYS_PROMPT="u-boot=> "
# CONFIG_CMD_EXPORTENV is not set
# CONFIG_CMD_IMPORTENV is not set
+CONFIG_CMD_ERASEENV=y
# CONFIG_CMD_CRC32 is not set
CONFIG_CMD_EEPROM=y
CONFIG_SYS_I2C_EEPROM_ADDR_LEN=2
CONFIG_CMD_GPIO=y
CONFIG_CMD_I2C=y
CONFIG_CMD_MMC=y
+CONFIG_CMD_PCI=y
CONFIG_CMD_SF_TEST=y
CONFIG_CMD_DHCP=y
CONFIG_CMD_MII=y
CONFIG_PHY_GIGE=y
CONFIG_FEC_MXC=y
CONFIG_MII=y
+CONFIG_NVME_PCI=y
+CONFIG_PCIE_DW_IMX=y
+CONFIG_PHY=y
+CONFIG_PHY_IMX8M_PCIE=y
CONFIG_PINCTRL=y
CONFIG_SPL_PINCTRL=y
CONFIG_PINCTRL_IMX8M=y
-CONFIG_DM_REGULATOR=y
+CONFIG_POWER_DOMAIN=y
+CONFIG_IMX8M_POWER_DOMAIN=y
CONFIG_DM_REGULATOR_FIXED=y
CONFIG_DM_REGULATOR_GPIO=y
CONFIG_DM_SERIAL=y
CONFIG_SPL_WATCHDOG=y
CONFIG_HUSH_PARSER=y
CONFIG_SYS_PROMPT="u-boot=> "
+CONFIG_CMD_ERASEENV=y
# CONFIG_CMD_CRC32 is not set
CONFIG_CMD_EEPROM=y
CONFIG_SYS_I2C_EEPROM_ADDR_LEN=2
CONFIG_ENV_SIZE=0x2000
CONFIG_ENV_OFFSET=0x80000
CONFIG_DM_GPIO=y
-CONFIG_DEFAULT_DEVICE_TREE="imx7s-warp"
+CONFIG_DEFAULT_DEVICE_TREE="nxp/imx/imx7s-warp"
CONFIG_TARGET_WARP7=y
CONFIG_OF_LIBFDT_OVERLAY=y
CONFIG_ARMV7_BOOT_SEC_DEFAULT=y
CONFIG_ENV_SIZE=0x2000
CONFIG_ENV_OFFSET=0xC0000
CONFIG_DM_GPIO=y
-CONFIG_DEFAULT_DEVICE_TREE="imx7s-warp"
+CONFIG_DEFAULT_DEVICE_TREE="nxp/imx/imx7s-warp"
CONFIG_TARGET_WARP7=y
CONFIG_ARMV7_BOOT_SEC_DEFAULT=y
# CONFIG_ARMV7_VIRT is not set
--- /dev/null
+.. SPDX-License-Identifier: GPL-2.0+
+.. Copyright 2024 NXP
+
+.. index::
+ single: cpu (command)
+
+cpu command
+===========
+
+Synopsis
+--------
+
+::
+
+ cpu list
+ cpu detail
+ cpu release <core ID> <addr>
+
+Description
+-----------
+
+The *cpu* command prints information about the CPUs, and release a CPU core
+to a given address to run applications.
+
+
+cpu list
+~~~~~~~~
+
+The 'list' subcommand lists and prints brief information of all the CPU cores,
+the CPU information is provided by vendors' CPU driver.
+
+cpu detail
+~~~~~~~~~~
+
+The 'detail' subcommand prints more details about the CPU cores, including
+CPU ID, core frequency and feature list.
+
+cpu release
+~~~~~~~~~~~
+
+The 'release' subcommand is used to release a CPU core to run a baremetal or
+RTOS applications.
+The parameter <core ID> is the sequence number of the CPU core to release.
+The parameter <addr> is the address to run of the specified core after release.
+
+
+Examples
+--------
+
+cpu list
+~~~~~~~~
+
+This example lists all the CPU cores On i.MX8M Plus EVK:
+::
+
+ u-boot=> cpu list
+ 0: cpu@0 NXP i.MX8MP Rev1.1 A53 at 1200 MHz at 31C
+ 1: cpu@1 NXP i.MX8MP Rev1.1 A53 at 1200 MHz at 30C
+ 2: cpu@2 NXP i.MX8MP Rev1.1 A53 at 1200 MHz at 31C
+ 3: cpu@3 NXP i.MX8MP Rev1.1 A53 at 1200 MHz at 31C
+
+cpu detail
+~~~~~~~~~~
+
+This example prints the details of the CPU cores On i.MX8M Plus EVK:
+::
+
+ u-boot=> cpu detail
+ 0: cpu@0 NXP i.MX8MP Rev1.1 A53 at 1200 MHz at 31C
+ ID = 0, freq = 1.2 GHz: L1 cache, MMU
+ 1: cpu@1 NXP i.MX8MP Rev1.1 A53 at 1200 MHz at 30C
+ ID = 0, freq = 1.2 GHz: L1 cache, MMU
+ 2: cpu@2 NXP i.MX8MP Rev1.1 A53 at 1200 MHz at 31C
+ ID = 0, freq = 1.2 GHz: L1 cache, MMU
+ 3: cpu@3 NXP i.MX8MP Rev1.1 A53 at 1200 MHz at 31C
+ ID = 0, freq = 1.2 GHz: L1 cache, MMU
+
+cpu release
+~~~~~~~~~~~
+
+This example shows release the LAST CPU core to run a RTOS application, on
+i.MX8M Plus EVK:
+::
+
+ u-boot=> load mmc 1:2 c0000000 /hello_world.bin
+ 66008 bytes read in 5 ms (12.6 MiB/s)
+ u-boot=> dcache flush; icache flush
+ u-boot=> cpu release 3 c0000000
+ Released CPU core (mpidr: 0x3) to address 0xc0000000
+
+
+Configuration
+-------------
+
+The cpu command is available if CONFIG_CMD_CPU=y.
+
+Return code
+-----------
+
+The return value $? is set to 0 (true) if the command is successful,
+1 (false) otherwise.
cmd/coninfo
cmd/conitrace
cmd/cp
+ cmd/cpu
cmd/cyclic
cmd/dm
cmd/ebtupdate
bulk_get_err:
err = clk_release_all(bulk->clks, bulk->count);
if (err)
- debug("%s: could release all clocks for %p\n",
+ debug("%s: could not release all clocks for %p\n",
__func__, dev);
return ret;
struct clk *clkp = NULL;
int ret;
- debug("%s(clk=%p)\n", __func__, clk);
+ debug("%s(clk=%p name=%s)\n", __func__, clk, clk->dev->name);
if (!clk_valid(clk))
return 0;
ops = clk_dev_ops(clk->dev);
struct clk *clkp = NULL;
int ret;
- debug("%s(clk=%p)\n", __func__, clk);
+ debug("%s(clk=%p name=%s)\n", __func__, clk, clk->dev->name);
if (!clk_valid(clk))
return 0;
ops = clk_dev_ops(clk->dev);
static const char * const sys_pll2_bypass_sels[] = {"sys_pll2", "sys_pll2_ref_sel", };
static const char * const sys_pll3_bypass_sels[] = {"sys_pll3", "sys_pll3_ref_sel", };
+static const char * const imx8mm_arm_core_sels[] = {"arm_a53_src", "arm_pll_out", };
+
static const char * const imx8mm_a53_sels[] = {"clock-osc-24m", "arm_pll_out", "sys_pll2_500m",
"sys_pll2_1000m", "sys_pll1_800m", "sys_pll1_400m",
"audio_pll1_out", "sys_pll3_out", };
imx_clk_gate4("qspi_root_clk", "qspi", base + 0x42f0, 0));
#endif
+ clk_dm(IMX8MM_CLK_ARM,
+ imx_clk_mux2_flags("arm_core", base + 0x9880, 24, 1,
+ imx8mm_arm_core_sels,
+ ARRAY_SIZE(imx8mm_arm_core_sels),
+ CLK_IS_CRITICAL));
+
return 0;
}
static const char * const sys_pll2_bypass_sels[] = {"sys_pll2", "sys_pll2_ref_sel", };
static const char * const sys_pll3_bypass_sels[] = {"sys_pll3", "sys_pll3_ref_sel", };
+static const char * const imx8mn_arm_core_sels[] = {"arm_a53_src", "arm_pll_out", };
+
static const char * const imx8mn_a53_sels[] = {"clock-osc-24m", "arm_pll_out", "sys_pll2_500m",
"sys_pll2_1000m", "sys_pll1_800m", "sys_pll1_400m",
"audio_pll1_out", "sys_pll3_out", };
imx_clk_gate4("ecspi3_root_clk", "ecspi3", base + 0x4090, 0));
#endif
+ clk_dm(IMX8MN_CLK_ARM,
+ imx_clk_mux2_flags("arm_core", base + 0x9880, 24, 1,
+ imx8mn_arm_core_sels,
+ ARRAY_SIZE(imx8mn_arm_core_sels),
+ CLK_IS_CRITICAL));
+
return 0;
}
static const char * const sys_pll2_bypass_sels[] = {"sys_pll2", "sys_pll2_ref_sel", };
static const char * const sys_pll3_bypass_sels[] = {"sys_pll3", "sys_pll3_ref_sel", };
+static const char * const imx8mp_arm_core_sels[] = {"arm_a53_src", "arm_pll_out", };
+
static const char * const imx8mp_a53_sels[] = {"clock-osc-24m", "arm_pll_out", "sys_pll2_500m",
"sys_pll2_1000m", "sys_pll1_800m", "sys_pll1_400m",
"audio_pll1_out", "sys_pll3_out", };
clk_dm(IMX8MP_CLK_USDHC3_ROOT, imx_clk_gate4("usdhc3_root_clk", "usdhc3", base + 0x45e0, 0));
+ clk_dm(IMX8MP_CLK_ARM,
+ imx_clk_mux2_flags("arm_core", base + 0x9880, 24, 1,
+ imx8mp_arm_core_sels,
+ ARRAY_SIZE(imx8mp_arm_core_sels),
+ CLK_IS_CRITICAL));
+
return 0;
}
/* shared functions */
+static int mtk_clk_get_id(struct clk *clk)
+{
+ struct mtk_clk_priv *priv = dev_get_priv(clk->dev);
+ int id = clk->id;
+
+ /* Remap the clk ID to the one expected by driver */
+ if (priv->tree->id_offs_map)
+ id = priv->tree->id_offs_map[id];
+
+ return id;
+}
+
+static int mtk_gate_enable(void __iomem *base, const struct mtk_gate *gate)
+{
+ u32 bit = BIT(gate->shift);
+
+ switch (gate->flags & CLK_GATE_MASK) {
+ case CLK_GATE_SETCLR:
+ writel(bit, base + gate->regs->clr_ofs);
+ break;
+ case CLK_GATE_SETCLR_INV:
+ writel(bit, base + gate->regs->set_ofs);
+ break;
+ case CLK_GATE_NO_SETCLR:
+ clrsetbits_le32(base + gate->regs->sta_ofs, bit, 0);
+ break;
+ case CLK_GATE_NO_SETCLR_INV:
+ clrsetbits_le32(base + gate->regs->sta_ofs, bit, bit);
+ break;
+
+ default:
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int mtk_gate_disable(void __iomem *base, const struct mtk_gate *gate)
+{
+ u32 bit = BIT(gate->shift);
+
+ switch (gate->flags & CLK_GATE_MASK) {
+ case CLK_GATE_SETCLR:
+ writel(bit, base + gate->regs->set_ofs);
+ break;
+ case CLK_GATE_SETCLR_INV:
+ writel(bit, base + gate->regs->clr_ofs);
+ break;
+ case CLK_GATE_NO_SETCLR:
+ clrsetbits_le32(base + gate->regs->sta_ofs, bit, bit);
+ break;
+ case CLK_GATE_NO_SETCLR_INV:
+ clrsetbits_le32(base + gate->regs->sta_ofs, bit, 0);
+ break;
+
+ default:
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
/*
* In case the rate change propagation to parent clocks is undesirable,
* this function is recursively called to find the parent to calculate
}
static int mtk_clk_mux_set_parent(void __iomem *base, u32 parent,
+ u32 parent_type,
const struct mtk_composite *mux)
{
u32 val, index = 0;
- while (mux->parent[index] != parent)
- if (++index == mux->num_parents)
- return -EINVAL;
+ if (mux->flags & CLK_PARENT_MIXED) {
+ /*
+ * Assume parent_type in clk_tree to be always set with
+ * CLK_PARENT_MIXED implementation. If it's not, assume
+ * not parent clk ID clash is possible.
+ */
+ while (mux->parent_flags[index].id != parent ||
+ (parent_type && (mux->parent_flags[index].flags & CLK_PARENT_MASK) !=
+ parent_type))
+ if (++index == mux->num_parents)
+ return -EINVAL;
+ } else {
+ while (mux->parent[index] != parent)
+ if (++index == mux->num_parents)
+ return -EINVAL;
+ }
if (mux->flags & CLK_MUX_SETCLR_UPD) {
val = (mux->mux_mask << mux->mux_shift);
* for the integer part and the remaining bits (if present) for the
* fractional part. Also they have a 3 bit power-of-two post divider.
*/
-static void mtk_pll_set_rate_regs(struct clk *clk, u32 pcw, int postdiv)
+static void mtk_pll_set_rate_regs(struct mtk_clk_priv *priv, u32 id,
+ u32 pcw, int postdiv)
{
- struct mtk_clk_priv *priv = dev_get_priv(clk->dev);
- const struct mtk_pll_data *pll = &priv->tree->plls[clk->id];
+ const struct mtk_pll_data *pll;
u32 val, chg;
+ pll = &priv->tree->plls[id];
+
/* set postdiv */
val = readl(priv->base + pll->pd_reg);
val &= ~(POSTDIV_MASK << pll->pd_shift);
/**
* mtk_pll_calc_values - calculate good values for a given input frequency.
- * @clk: The clk
+ * @priv: The mtk priv struct
+ * @id: The clk id
* @pcw: The pcw value (output)
* @postdiv: The post divider (output)
* @freq: The desired target frequency
*/
-static void mtk_pll_calc_values(struct clk *clk, u32 *pcw, u32 *postdiv,
- u32 freq)
+static void mtk_pll_calc_values(struct mtk_clk_priv *priv, u32 id,
+ u32 *pcw, u32 *postdiv, u32 freq)
{
- struct mtk_clk_priv *priv = dev_get_priv(clk->dev);
- const struct mtk_pll_data *pll = &priv->tree->plls[clk->id];
- unsigned long fmin = pll->fmin ? pll->fmin : 1000 * MHZ;
+ const struct mtk_pll_data *pll;
+ unsigned long fmin;
u64 _pcw;
int ibits;
u32 val;
+ pll = &priv->tree->plls[id];
+ fmin = pll->fmin ? pll->fmin : 1000 * MHZ;
+
if (freq > pll->fmax)
freq = pll->fmax;
static ulong mtk_apmixedsys_set_rate(struct clk *clk, ulong rate)
{
+ struct mtk_clk_priv *priv = dev_get_priv(clk->dev);
+ int id = mtk_clk_get_id(clk);
u32 pcw = 0;
u32 postdiv;
- mtk_pll_calc_values(clk, &pcw, &postdiv, rate);
- mtk_pll_set_rate_regs(clk, pcw, postdiv);
+ if (priv->tree->gates && id >= priv->tree->gates_offs)
+ return -EINVAL;
+
+ mtk_pll_calc_values(priv, id, &pcw, &postdiv, rate);
+ mtk_pll_set_rate_regs(priv, id, pcw, postdiv);
return 0;
}
static ulong mtk_apmixedsys_get_rate(struct clk *clk)
{
struct mtk_clk_priv *priv = dev_get_priv(clk->dev);
- const struct mtk_pll_data *pll = &priv->tree->plls[clk->id];
+ const struct mtk_pll_data *pll;
+ int id = mtk_clk_get_id(clk);
+ const struct mtk_gate *gate;
u32 postdiv;
u32 pcw;
+ /* GATE handling */
+ if (priv->tree->gates && id >= priv->tree->gates_offs) {
+ gate = &priv->tree->gates[id - priv->tree->gates_offs];
+ return mtk_clk_find_parent_rate(clk, gate->parent, NULL);
+ }
+
+ pll = &priv->tree->plls[id];
+
postdiv = (readl(priv->base + pll->pd_reg) >> pll->pd_shift) &
POSTDIV_MASK;
postdiv = 1 << postdiv;
static int mtk_apmixedsys_enable(struct clk *clk)
{
struct mtk_clk_priv *priv = dev_get_priv(clk->dev);
- const struct mtk_pll_data *pll = &priv->tree->plls[clk->id];
+ const struct mtk_pll_data *pll;
+ int id = mtk_clk_get_id(clk);
+ const struct mtk_gate *gate;
u32 r;
+ /* GATE handling */
+ if (priv->tree->gates && id >= priv->tree->gates_offs) {
+ gate = &priv->tree->gates[id - priv->tree->gates_offs];
+ return mtk_gate_enable(priv->base, gate);
+ }
+
+ pll = &priv->tree->plls[id];
+
r = readl(priv->base + pll->pwr_reg) | CON0_PWR_ON;
writel(r, priv->base + pll->pwr_reg);
udelay(1);
static int mtk_apmixedsys_disable(struct clk *clk)
{
struct mtk_clk_priv *priv = dev_get_priv(clk->dev);
- const struct mtk_pll_data *pll = &priv->tree->plls[clk->id];
+ const struct mtk_pll_data *pll;
+ int id = mtk_clk_get_id(clk);
+ const struct mtk_gate *gate;
u32 r;
+ /* GATE handling */
+ if (priv->tree->gates && id >= priv->tree->gates_offs) {
+ gate = &priv->tree->gates[id - priv->tree->gates_offs];
+ return mtk_gate_disable(priv->base, gate);
+ }
+
+ pll = &priv->tree->plls[id];
+
if (pll->flags & HAVE_RST_BAR) {
r = readl(priv->base + pll->reg + REG_CON0);
r &= ~pll->rst_bar_mask;
return mtk_factor_recalc_rate(fdiv, rate);
}
+static ulong mtk_topckgen_find_parent_rate(struct mtk_clk_priv *priv, struct clk *clk,
+ const int parent, u16 flags)
+{
+ switch (flags & CLK_PARENT_MASK) {
+ case CLK_PARENT_XTAL:
+ return priv->tree->xtal_rate;
+ case CLK_PARENT_APMIXED:
+ return mtk_clk_find_parent_rate(clk, parent, priv->parent);
+ default:
+ return mtk_clk_find_parent_rate(clk, parent, NULL);
+ }
+}
+
static ulong mtk_topckgen_get_mux_rate(struct clk *clk, u32 off)
{
struct mtk_clk_priv *priv = dev_get_priv(clk->dev);
index &= mux->mux_mask << mux->mux_shift;
index = index >> mux->mux_shift;
- if (mux->parent[index] > 0 ||
- (mux->parent[index] == CLK_XTAL &&
- priv->tree->flags & CLK_BYPASS_XTAL)) {
- switch (mux->flags & CLK_PARENT_MASK) {
- case CLK_PARENT_APMIXED:
- return mtk_clk_find_parent_rate(clk, mux->parent[index],
- priv->parent);
- break;
- default:
- return mtk_clk_find_parent_rate(clk, mux->parent[index],
- NULL);
- break;
- }
+ /*
+ * Parents can be either from APMIXED or TOPCKGEN,
+ * inspect the mtk_parent struct to check the source
+ */
+ if (mux->flags & CLK_PARENT_MIXED) {
+ const struct mtk_parent *parent = &mux->parent_flags[index];
+
+ return mtk_topckgen_find_parent_rate(priv, clk, parent->id,
+ parent->flags);
}
- return priv->tree->xtal_rate;
+ if (mux->parent[index] == CLK_XTAL &&
+ !(priv->tree->flags & CLK_BYPASS_XTAL))
+ return priv->tree->xtal_rate;
+
+ return mtk_topckgen_find_parent_rate(priv, clk, mux->parent[index],
+ mux->flags);
+}
+
+static ulong mtk_find_parent_rate(struct mtk_clk_priv *priv, struct clk *clk,
+ const int parent, u16 flags)
+{
+ switch (flags & CLK_PARENT_MASK) {
+ case CLK_PARENT_XTAL:
+ return priv->tree->xtal_rate;
+ /* Assume the second level parent is always APMIXED */
+ case CLK_PARENT_APMIXED:
+ priv = dev_get_priv(priv->parent);
+ fallthrough;
+ case CLK_PARENT_TOPCKGEN:
+ return mtk_clk_find_parent_rate(clk, parent, priv->parent);
+ default:
+ return mtk_clk_find_parent_rate(clk, parent, NULL);
+ }
}
static ulong mtk_infrasys_get_mux_rate(struct clk *clk, u32 off)
index &= mux->mux_mask << mux->mux_shift;
index = index >> mux->mux_shift;
- if (mux->parent[index] > 0 ||
- (mux->parent[index] == CLK_XTAL &&
- priv->tree->flags & CLK_BYPASS_XTAL)) {
- switch (mux->flags & CLK_PARENT_MASK) {
- case CLK_PARENT_TOPCKGEN:
- return mtk_clk_find_parent_rate(clk, mux->parent[index],
- priv->parent);
- break;
- default:
- return mtk_clk_find_parent_rate(clk, mux->parent[index],
- NULL);
- break;
- }
+ /*
+ * Parents can be either from TOPCKGEN or INFRACFG,
+ * inspect the mtk_parent struct to check the source
+ */
+ if (mux->flags & CLK_PARENT_MIXED) {
+ const struct mtk_parent *parent = &mux->parent_flags[index];
+
+ return mtk_find_parent_rate(priv, clk, parent->id, parent->flags);
}
- return 0;
+
+ if (mux->parent[index] == CLK_XTAL &&
+ !(priv->tree->flags & CLK_BYPASS_XTAL))
+ return priv->tree->xtal_rate;
+
+ return mtk_find_parent_rate(priv, clk, mux->parent[index], mux->flags);
}
static ulong mtk_topckgen_get_rate(struct clk *clk)
{
struct mtk_clk_priv *priv = dev_get_priv(clk->dev);
+ int id = mtk_clk_get_id(clk);
- if (clk->id < priv->tree->fdivs_offs)
- return priv->tree->fclks[clk->id].rate;
- else if (clk->id < priv->tree->muxes_offs)
- return mtk_topckgen_get_factor_rate(clk, clk->id -
+ if (id < priv->tree->fdivs_offs)
+ return priv->tree->fclks[id].rate;
+ else if (id < priv->tree->muxes_offs)
+ return mtk_topckgen_get_factor_rate(clk, id -
priv->tree->fdivs_offs);
else
- return mtk_topckgen_get_mux_rate(clk, clk->id -
+ return mtk_topckgen_get_mux_rate(clk, id -
priv->tree->muxes_offs);
}
static ulong mtk_infrasys_get_rate(struct clk *clk)
{
struct mtk_clk_priv *priv = dev_get_priv(clk->dev);
-
+ int id = mtk_clk_get_id(clk);
ulong rate;
- if (clk->id < priv->tree->fdivs_offs) {
- rate = priv->tree->fclks[clk->id].rate;
- } else if (clk->id < priv->tree->muxes_offs) {
- rate = mtk_infrasys_get_factor_rate(clk, clk->id -
+ if (id < priv->tree->fdivs_offs) {
+ rate = priv->tree->fclks[id].rate;
+ } else if (id < priv->tree->muxes_offs) {
+ rate = mtk_infrasys_get_factor_rate(clk, id -
priv->tree->fdivs_offs);
- } else {
- rate = mtk_infrasys_get_mux_rate(clk, clk->id -
+ /* No gates defined or ID is a MUX */
+ } else if (!priv->tree->gates || id < priv->tree->gates_offs) {
+ rate = mtk_infrasys_get_mux_rate(clk, id -
priv->tree->muxes_offs);
+ /* Only valid with muxes + gates implementation */
+ } else {
+ struct udevice *parent = NULL;
+ const struct mtk_gate *gate;
+
+ gate = &priv->tree->gates[id - priv->tree->gates_offs];
+ if (gate->flags & CLK_PARENT_TOPCKGEN)
+ parent = priv->parent;
+ /*
+ * Assume xtal_rate to be declared if some gates have
+ * XTAL as parent
+ */
+ else if (gate->flags & CLK_PARENT_XTAL)
+ return priv->tree->xtal_rate;
+
+ rate = mtk_clk_find_parent_rate(clk, gate->parent, parent);
}
return rate;
{
struct mtk_clk_priv *priv = dev_get_priv(clk->dev);
const struct mtk_composite *mux;
+ int id = mtk_clk_get_id(clk);
u32 val;
- if (clk->id < priv->tree->muxes_offs)
+ if (id < priv->tree->muxes_offs)
return 0;
- mux = &priv->tree->muxes[clk->id - priv->tree->muxes_offs];
+ mux = &priv->tree->muxes[id - priv->tree->muxes_offs];
if (mux->gate_shift < 0)
return 0;
{
struct mtk_clk_priv *priv = dev_get_priv(clk->dev);
const struct mtk_composite *mux;
+ int id = mtk_clk_get_id(clk);
u32 val;
- if (clk->id < priv->tree->muxes_offs)
+ if (id < priv->tree->muxes_offs)
return 0;
- mux = &priv->tree->muxes[clk->id - priv->tree->muxes_offs];
+ mux = &priv->tree->muxes[id - priv->tree->muxes_offs];
if (mux->gate_shift < 0)
return 0;
static int mtk_common_clk_set_parent(struct clk *clk, struct clk *parent)
{
+ struct mtk_clk_priv *parent_priv = dev_get_priv(parent->dev);
struct mtk_clk_priv *priv = dev_get_priv(clk->dev);
+ int id = mtk_clk_get_id(clk);
+ u32 parent_type;
+
+ if (id < priv->tree->muxes_offs)
+ return 0;
- if (clk->id < priv->tree->muxes_offs)
+ if (!parent_priv)
return 0;
- return mtk_clk_mux_set_parent(priv->base, parent->id,
- &priv->tree->muxes[clk->id - priv->tree->muxes_offs]);
+ parent_type = parent_priv->tree->flags & CLK_PARENT_MASK;
+ return mtk_clk_mux_set_parent(priv->base, parent->id, parent_type,
+ &priv->tree->muxes[id - priv->tree->muxes_offs]);
}
/* CG functions */
static int mtk_clk_gate_enable(struct clk *clk)
{
struct mtk_cg_priv *priv = dev_get_priv(clk->dev);
- const struct mtk_gate *gate = &priv->gates[clk->id];
- u32 bit = BIT(gate->shift);
+ int id = mtk_clk_get_id(clk);
+ const struct mtk_gate *gate;
- switch (gate->flags & CLK_GATE_MASK) {
- case CLK_GATE_SETCLR:
- writel(bit, priv->base + gate->regs->clr_ofs);
- break;
- case CLK_GATE_SETCLR_INV:
- writel(bit, priv->base + gate->regs->set_ofs);
- break;
- case CLK_GATE_NO_SETCLR:
- clrsetbits_le32(priv->base + gate->regs->sta_ofs, bit, 0);
- break;
- case CLK_GATE_NO_SETCLR_INV:
- clrsetbits_le32(priv->base + gate->regs->sta_ofs, bit, bit);
- break;
-
- default:
+ if (id < priv->tree->gates_offs)
return -EINVAL;
- }
- return 0;
+ gate = &priv->gates[id - priv->tree->gates_offs];
+ return mtk_gate_enable(priv->base, gate);
}
-static int mtk_clk_gate_disable(struct clk *clk)
+static int mtk_clk_infrasys_enable(struct clk *clk)
{
struct mtk_cg_priv *priv = dev_get_priv(clk->dev);
- const struct mtk_gate *gate = &priv->gates[clk->id];
- u32 bit = BIT(gate->shift);
+ int id = mtk_clk_get_id(clk);
+ const struct mtk_gate *gate;
- switch (gate->flags & CLK_GATE_MASK) {
- case CLK_GATE_SETCLR:
- writel(bit, priv->base + gate->regs->set_ofs);
- break;
- case CLK_GATE_SETCLR_INV:
- writel(bit, priv->base + gate->regs->clr_ofs);
- break;
- case CLK_GATE_NO_SETCLR:
- clrsetbits_le32(priv->base + gate->regs->sta_ofs, bit, bit);
- break;
- case CLK_GATE_NO_SETCLR_INV:
- clrsetbits_le32(priv->base + gate->regs->sta_ofs, bit, 0);
- break;
+ /* MUX handling */
+ if (!priv->tree->gates || id < priv->tree->gates_offs)
+ return mtk_clk_mux_enable(clk);
- default:
+ gate = &priv->tree->gates[id - priv->tree->gates_offs];
+ return mtk_gate_enable(priv->base, gate);
+}
+
+static int mtk_clk_gate_disable(struct clk *clk)
+{
+ struct mtk_cg_priv *priv = dev_get_priv(clk->dev);
+ int id = mtk_clk_get_id(clk);
+ const struct mtk_gate *gate;
+
+ if (id < priv->tree->gates_offs)
return -EINVAL;
- }
- return 0;
+ gate = &priv->gates[id - priv->tree->gates_offs];
+ return mtk_gate_disable(priv->base, gate);
+}
+
+static int mtk_clk_infrasys_disable(struct clk *clk)
+{
+ struct mtk_cg_priv *priv = dev_get_priv(clk->dev);
+ int id = mtk_clk_get_id(clk);
+ const struct mtk_gate *gate;
+
+ /* MUX handling */
+ if (!priv->tree->gates || id < priv->tree->gates_offs)
+ return mtk_clk_mux_disable(clk);
+
+ gate = &priv->tree->gates[id - priv->tree->gates_offs];
+ return mtk_gate_disable(priv->base, gate);
}
static ulong mtk_clk_gate_get_rate(struct clk *clk)
{
struct mtk_cg_priv *priv = dev_get_priv(clk->dev);
- const struct mtk_gate *gate = &priv->gates[clk->id];
+ struct udevice *parent = priv->parent;
+ int id = mtk_clk_get_id(clk);
+ const struct mtk_gate *gate;
+
+ if (id < priv->tree->gates_offs)
+ return -EINVAL;
+
+ gate = &priv->gates[id - priv->tree->gates_offs];
+ /*
+ * With requesting a TOPCKGEN parent, make sure the dev parent
+ * is actually topckgen. This might not be the case for an
+ * infracfg-ao implementation where:
+ * parent = infracfg
+ * parent->parent = topckgen
+ */
+ if (gate->flags & CLK_PARENT_TOPCKGEN &&
+ parent->driver != DM_DRIVER_GET(mtk_clk_topckgen)) {
+ priv = dev_get_priv(parent);
+ parent = priv->parent;
+ /*
+ * Assume xtal_rate to be declared if some gates have
+ * XTAL as parent
+ */
+ } else if (gate->flags & CLK_PARENT_XTAL) {
+ return priv->tree->xtal_rate;
+ }
- return mtk_clk_find_parent_rate(clk, gate->parent, priv->parent);
+ return mtk_clk_find_parent_rate(clk, gate->parent, parent);
}
const struct clk_ops mtk_clk_apmixedsys_ops = {
};
const struct clk_ops mtk_clk_infrasys_ops = {
- .enable = mtk_clk_mux_enable,
- .disable = mtk_clk_mux_disable,
+ .enable = mtk_clk_infrasys_enable,
+ .disable = mtk_clk_infrasys_disable,
.get_rate = mtk_infrasys_get_rate,
.set_parent = mtk_common_clk_set_parent,
};
.get_rate = mtk_clk_gate_get_rate,
};
-int mtk_common_clk_init(struct udevice *dev,
- const struct mtk_clk_tree *tree)
+static int mtk_common_clk_init_drv(struct udevice *dev,
+ const struct mtk_clk_tree *tree,
+ const struct driver *drv)
{
struct mtk_clk_priv *priv = dev_get_priv(dev);
struct udevice *parent;
ret = uclass_get_device_by_phandle(UCLASS_CLK, dev, "clock-parent", &parent);
if (ret || !parent) {
- ret = uclass_get_device_by_driver(UCLASS_CLK,
- DM_DRIVER_GET(mtk_clk_apmixedsys), &parent);
+ ret = uclass_get_device_by_driver(UCLASS_CLK, drv, &parent);
if (ret || !parent)
return -ENOENT;
}
return 0;
}
+int mtk_common_clk_init(struct udevice *dev,
+ const struct mtk_clk_tree *tree)
+{
+ return mtk_common_clk_init_drv(dev, tree,
+ DM_DRIVER_GET(mtk_clk_apmixedsys));
+}
+
+int mtk_common_clk_infrasys_init(struct udevice *dev,
+ const struct mtk_clk_tree *tree)
+{
+ return mtk_common_clk_init_drv(dev, tree,
+ DM_DRIVER_GET(mtk_clk_topckgen));
+}
+
int mtk_common_clk_gate_init(struct udevice *dev,
const struct mtk_clk_tree *tree,
const struct mtk_gate *gates)
/* flags in struct mtk_clk_tree */
-/* clk id == 0 doesn't mean it's xtal clk */
+/* clk id == 0 doesn't mean it's xtal clk
+ * This doesn't apply when CLK_PARENT_MIXED is defined.
+ * With CLK_PARENT_MIXED declare CLK_PARENT_XTAL for the
+ * relevant parent.
+ */
#define CLK_BYPASS_XTAL BIT(0)
#define HAVE_RST_BAR BIT(0)
#define CLK_PARENT_TOPCKGEN BIT(5)
#define CLK_PARENT_INFRASYS BIT(6)
#define CLK_PARENT_XTAL BIT(7)
-#define CLK_PARENT_MASK GENMASK(7, 4)
+/*
+ * For CLK_PARENT_MIXED to correctly work, is required to
+ * define in clk_tree flags the clk type using the alias.
+ */
+#define CLK_PARENT_MIXED BIT(8)
+#define CLK_PARENT_MASK GENMASK(8, 4)
+
+/* alias to reference clk type */
+#define CLK_APMIXED CLK_PARENT_APMIXED
+#define CLK_TOPCKGEN CLK_PARENT_TOPCKGEN
+#define CLK_INFRASYS CLK_PARENT_INFRASYS
#define ETHSYS_HIFSYS_RST_CTRL_OFS 0x34
.flags = _flags, \
}
+/**
+ * struct mtk_parent - clock parent with flags. Needed for MUX that
+ * parent with mixed infracfg and topckgen.
+ *
+ * @id: index of parent clocks
+ * @flags: hardware-specific flags (parent location,
+ * infracfg, topckgen, APMIXED, xtal ...)
+ */
+struct mtk_parent {
+ const int id;
+ u16 flags;
+};
+
+#define PARENT(_id, _flags) { \
+ .id = _id, \
+ .flags = _flags, \
+ }
+
/**
* struct mtk_composite - aggregate clock of mux, divider and gate clocks
*
* @id: index of clocks
* @parent: index of parnet clocks
+ * @parent: index of parnet clocks
+ * @parent_flags: table of parent clocks with flags
* @mux_reg: hardware-specific mux register
* @gate_reg: hardware-specific gate register
* @mux_mask: mask to the mux bit field
*/
struct mtk_composite {
const int id;
- const int *parent;
+ union {
+ const int *parent;
+ const struct mtk_parent *parent_flags;
+ };
u32 mux_reg;
u32 mux_set_reg;
u32 mux_clr_reg;
#define MUX_GATE(_id, _parents, _reg, _shift, _width, _gate) \
MUX_GATE_FLAGS(_id, _parents, _reg, _shift, _width, _gate, 0)
-#define MUX(_id, _parents, _reg, _shift, _width) { \
+#define MUX_MIXED_FLAGS(_id, _parents, _reg, _shift, _width, _flags) { \
+ .id = _id, \
+ .mux_reg = _reg, \
+ .mux_shift = _shift, \
+ .mux_mask = BIT(_width) - 1, \
+ .gate_shift = -1, \
+ .parent_flags = _parents, \
+ .num_parents = ARRAY_SIZE(_parents), \
+ .flags = CLK_PARENT_MIXED | (_flags), \
+ }
+#define MUX_MIXED(_id, _parents, _reg, _shift, _width) \
+ MUX_MIXED_FLAGS(_id, _parents, _reg, _shift, _width, 0)
+
+#define MUX_FLAGS(_id, _parents, _reg, _shift, _width, _flags) { \
.id = _id, \
.mux_reg = _reg, \
.mux_shift = _shift, \
.gate_shift = -1, \
.parent = _parents, \
.num_parents = ARRAY_SIZE(_parents), \
- .flags = 0, \
+ .flags = _flags, \
}
+#define MUX(_id, _parents, _reg, _shift, _width) \
+ MUX_FLAGS(_id, _parents, _reg, _shift, _width, 0)
#define MUX_CLR_SET_UPD_FLAGS(_id, _parents, _mux_ofs, _mux_set_ofs,\
_mux_clr_ofs, _shift, _width, _gate, \
struct mtk_clk_tree {
unsigned long xtal_rate;
unsigned long xtal2_rate;
+ /*
+ * Clock ID offset are remapped with an auxiliary table.
+ * Enable this by defining .id_offs_map.
+ * This is needed for upstream linux kernel <soc>-clk.h that
+ * have mixed clk ID and doesn't have clear distinction between
+ * ID for factor, mux and gates.
+ */
+ const int *id_offs_map; /* optional, table clk.h to driver ID */
const int fdivs_offs;
const int muxes_offs;
+ const int gates_offs;
const struct mtk_pll_data *plls;
const struct mtk_fixed_clk *fclks;
const struct mtk_fixed_factor *fdivs;
const struct mtk_composite *muxes;
+ const struct mtk_gate *gates;
u32 flags;
};
int mtk_common_clk_init(struct udevice *dev,
const struct mtk_clk_tree *tree);
+int mtk_common_clk_infrasys_init(struct udevice *dev,
+ const struct mtk_clk_tree *tree);
int mtk_common_clk_gate_init(struct udevice *dev,
const struct mtk_clk_tree *tree,
const struct mtk_gate *gates);
return ops->get_vendor(dev, buf, size);
}
+int cpu_release_core(const struct udevice *dev, phys_addr_t addr)
+{
+ struct cpu_ops *ops = cpu_get_ops(dev);
+
+ if (!ops->release_core)
+ return -ENOSYS;
+
+ return ops->release_core(dev, addr);
+}
+
U_BOOT_DRIVER(cpu_bus) = {
.name = "cpu_bus",
.id = UCLASS_SIMPLE_BUS,
cpu_current = name;
}
+static int cpu_sandbox_release_core(const struct udevice *dev, phys_addr_t addr)
+{
+ return 0;
+}
+
static int cpu_sandbox_is_current(struct udevice *dev)
{
if (!strcmp(dev->name, cpu_current))
.get_count = cpu_sandbox_get_count,
.get_vendor = cpu_sandbox_get_vendor,
.is_current = cpu_sandbox_is_current,
+ .release_core = cpu_sandbox_release_core,
};
static int cpu_sandbox_bind(struct udevice *dev)
// SPDX-License-Identifier: GPL-2.0+
/*
- * Copyright 2019 NXP
+ * Copyright 2019, 2024 NXP
*/
#include <cpu.h>
#include <dm.h>
#include <thermal.h>
#include <asm/global_data.h>
+#include <asm/ptrace.h>
#include <asm/system.h>
#include <firmware/imx/sci/sci.h>
#include <asm/arch/sys_proto.h>
#include <imx_thermal.h>
#include <linux/bitops.h>
#include <linux/clk-provider.h>
+#include <linux/psci.h>
DECLARE_GLOBAL_DATA_PTR;
static const char *get_imx_type_str(u32 imxtype)
{
switch (imxtype) {
+ case MXC_CPU_IMX8MM:
+ return "8MM";
+ case MXC_CPU_IMX8MN:
+ return "8MN";
+ case MXC_CPU_IMX8MP:
+ return "8MP";
case MXC_CPU_IMX8QXP:
case MXC_CPU_IMX8QXP_A0:
return "8QXP";
ret = snprintf(buf, size, " - invalid sensor data");
}
- snprintf(buf + ret, size - ret, "\n");
-
return 0;
}
{
struct cpu_imx_plat *plat = dev_get_plat(dev);
- info->cpu_freq = plat->freq_mhz * 1000;
+ info->cpu_freq = plat->freq_mhz * 1000000;
info->features = BIT(CPU_FEAT_L1_CACHE) | BIT(CPU_FEAT_MMU);
return 0;
}
return 0;
}
+static int cpu_imx_release_core(const struct udevice *dev, phys_addr_t addr)
+{
+ struct cpu_imx_plat *plat = dev_get_plat(dev);
+ struct pt_regs regs;
+
+ regs.regs[0] = PSCI_0_2_FN64_CPU_ON;
+ regs.regs[1] = plat->mpidr;
+ regs.regs[2] = addr;
+ regs.regs[3] = 0;
+
+ smc_call(®s);
+ if (regs.regs[0]) {
+ printf("Failed to release CPU core (mpidr: 0x%x)\n", plat->mpidr);
+ return -1;
+ }
+
+ printf("Released CPU core (mpidr: 0x%x) to address 0x%llx\n", plat->mpidr, addr);
+
+ return 0;
+}
+
static const struct cpu_ops cpu_imx_ops = {
.get_desc = cpu_imx_get_desc,
.get_info = cpu_imx_get_info,
.get_count = cpu_imx_get_count,
.get_vendor = cpu_imx_get_vendor,
.is_current = cpu_imx_is_current,
+ .release_core = cpu_imx_release_core,
};
static const struct udevice_id cpu_imx_ids[] = {
cpurev = get_cpu_rev();
plat->cpurev = cpurev;
plat->rev = get_imx_rev_str(cpurev & 0xFFF);
- plat->type = get_imx_type_str((cpurev & 0xFF000) >> 12);
+ plat->type = get_imx_type_str((cpurev & 0x1FF000) >> 12);
plat->freq_mhz = imx_get_cpu_rate(dev) / 1000000;
plat->mpidr = dev_read_addr(dev);
if (plat->mpidr == FDT_ADDR_T_NONE) {
#include <asm/arch/clock.h>
#include <asm/mach-imx/sys_proto.h>
#endif
+#include <linux/bitfield.h>
#include <linux/delay.h>
#include <linux/printk.h>
1000000, true);
}
+/* Bitmask common for mdio_read and mdio_write */
+#define EQOS_MDIO_BITFIELD(pa, rda, cr) \
+ FIELD_PREP(EQOS_MAC_MDIO_ADDRESS_PA_MASK, pa) | \
+ FIELD_PREP(EQOS_MAC_MDIO_ADDRESS_RDA_MASK, rda) | \
+ FIELD_PREP(EQOS_MAC_MDIO_ADDRESS_CR_MASK, cr) | \
+ EQOS_MAC_MDIO_ADDRESS_GB
+
+static u32 eqos_mdio_bitfield(struct eqos_priv *eqos, int addr, int devad, int reg)
+{
+ int cr = eqos->config->config_mac_mdio;
+ bool c22 = devad == MDIO_DEVAD_NONE ? true : false;
+
+ if (c22)
+ return EQOS_MDIO_BITFIELD(addr, reg, cr);
+ else
+ return EQOS_MDIO_BITFIELD(addr, devad, cr) |
+ EQOS_MAC_MDIO_ADDRESS_C45E;
+}
+
static int eqos_mdio_read(struct mii_dev *bus, int mdio_addr, int mdio_devad,
int mdio_reg)
{
}
val = readl(&eqos->mac_regs->mdio_address);
- val &= EQOS_MAC_MDIO_ADDRESS_SKAP |
- EQOS_MAC_MDIO_ADDRESS_C45E;
- val |= (mdio_addr << EQOS_MAC_MDIO_ADDRESS_PA_SHIFT) |
- (mdio_reg << EQOS_MAC_MDIO_ADDRESS_RDA_SHIFT) |
- (eqos->config->config_mac_mdio <<
- EQOS_MAC_MDIO_ADDRESS_CR_SHIFT) |
- (EQOS_MAC_MDIO_ADDRESS_GOC_READ <<
- EQOS_MAC_MDIO_ADDRESS_GOC_SHIFT) |
- EQOS_MAC_MDIO_ADDRESS_GB;
+ val &= EQOS_MAC_MDIO_ADDRESS_SKAP;
+
+ val |= eqos_mdio_bitfield(eqos, mdio_addr, mdio_devad, mdio_reg) |
+ FIELD_PREP(EQOS_MAC_MDIO_ADDRESS_GOC_MASK,
+ EQOS_MAC_MDIO_ADDRESS_GOC_READ);
+
+ if (val & EQOS_MAC_MDIO_ADDRESS_C45E) {
+ writel(FIELD_PREP(EQOS_MAC_MDIO_DATA_RA_MASK, mdio_reg),
+ &eqos->mac_regs->mdio_data);
+ }
+
writel(val, &eqos->mac_regs->mdio_address);
udelay(eqos->config->mdio_wait);
int mdio_reg, u16 mdio_val)
{
struct eqos_priv *eqos = bus->priv;
- u32 val;
+ u32 v_addr;
+ u32 v_data;
int ret;
debug("%s(dev=%p, addr=%x, reg=%d, val=%x):\n", __func__, eqos->dev,
return ret;
}
- writel(mdio_val, &eqos->mac_regs->mdio_data);
+ v_addr = readl(&eqos->mac_regs->mdio_address);
+ v_addr &= EQOS_MAC_MDIO_ADDRESS_SKAP;
- val = readl(&eqos->mac_regs->mdio_address);
- val &= EQOS_MAC_MDIO_ADDRESS_SKAP |
- EQOS_MAC_MDIO_ADDRESS_C45E;
- val |= (mdio_addr << EQOS_MAC_MDIO_ADDRESS_PA_SHIFT) |
- (mdio_reg << EQOS_MAC_MDIO_ADDRESS_RDA_SHIFT) |
- (eqos->config->config_mac_mdio <<
- EQOS_MAC_MDIO_ADDRESS_CR_SHIFT) |
- (EQOS_MAC_MDIO_ADDRESS_GOC_WRITE <<
- EQOS_MAC_MDIO_ADDRESS_GOC_SHIFT) |
- EQOS_MAC_MDIO_ADDRESS_GB;
- writel(val, &eqos->mac_regs->mdio_address);
+ v_addr |= eqos_mdio_bitfield(eqos, mdio_addr, mdio_devad, mdio_reg) |
+ FIELD_PREP(EQOS_MAC_MDIO_ADDRESS_GOC_MASK,
+ EQOS_MAC_MDIO_ADDRESS_GOC_WRITE);
+
+ v_data = mdio_val;
+ if (v_addr & EQOS_MAC_MDIO_ADDRESS_C45E)
+ v_data |= FIELD_PREP(EQOS_MAC_MDIO_DATA_RA_MASK, mdio_reg);
+ writel(v_data, &eqos->mac_regs->mdio_data);
+ writel(v_addr, &eqos->mac_regs->mdio_address);
udelay(eqos->config->mdio_wait);
ret = eqos_mdio_wait_idle(eqos);
#define EQOS_MAC_HW_FEATURE3_ASP_SHIFT 28
#define EQOS_MAC_HW_FEATURE3_ASP_MASK 0x3
-#define EQOS_MAC_MDIO_ADDRESS_PA_SHIFT 21
-#define EQOS_MAC_MDIO_ADDRESS_RDA_SHIFT 16
-#define EQOS_MAC_MDIO_ADDRESS_CR_SHIFT 8
+#define EQOS_MAC_MDIO_ADDRESS_PA_MASK GENMASK(25, 21)
+#define EQOS_MAC_MDIO_ADDRESS_RDA_MASK GENMASK(20, 16)
+#define EQOS_MAC_MDIO_ADDRESS_CR_MASK GENMASK(11, 8)
#define EQOS_MAC_MDIO_ADDRESS_CR_100_150 1
#define EQOS_MAC_MDIO_ADDRESS_CR_20_35 2
#define EQOS_MAC_MDIO_ADDRESS_CR_250_300 5
#define EQOS_MAC_MDIO_ADDRESS_SKAP BIT(4)
-#define EQOS_MAC_MDIO_ADDRESS_GOC_SHIFT 2
+#define EQOS_MAC_MDIO_ADDRESS_GOC_MASK GENMASK(3, 2)
#define EQOS_MAC_MDIO_ADDRESS_GOC_READ 3
#define EQOS_MAC_MDIO_ADDRESS_GOC_WRITE 1
#define EQOS_MAC_MDIO_ADDRESS_C45E BIT(1)
#define EQOS_MAC_MDIO_ADDRESS_GB BIT(0)
+#define EQOS_MAC_MDIO_DATA_RA_MASK GENMASK(31, 16)
#define EQOS_MAC_MDIO_DATA_GD_MASK 0xffff
#define EQOS_MTL_REGS_BASE 0xd00
return 0;
os_usleep(100);
- if (IS_ENABLED(CONFIG_VIDEO) && !IS_ENABLED(CONFIG_SPL_BUILD))
- video_sync_all();
avail = membuff_putraw(&priv->buf, 100, false, &data);
if (!avail)
return 1; /* buffer full */
config VIDEO
bool "Enable driver model support for LCD/video"
depends on DM
+ imply CYCLIC
help
This enables driver model for LCD and video devices. These support
a bitmap display of various sizes and depths which can be drawn on
option compiles in the video uclass and routes all LCD/video access
through this.
+ If CYCLIC is enabled (which it is by default), the cyclic subsystem
+ is used to flush pending output to the display periodically, rather
+ than this happening with every chunk of output. This allows for more
+ efficient operation and faster display output.
+
if VIDEO
config VIDEO_FONT_4X6
loads takes over the screen. This, for example, can be used to
keep splash image on screen until grub graphical boot menu starts.
+config VIDEO_SYNC_MS
+ int "Video-sync period in milliseconds for foreground processing"
+ default 300 if SANDBOX
+ default 100
+ help
+ This sets the requested, maximum time before a video sync will take
+ place, in milliseconds. Note that the time between video syncs
+ may be longer than this, since syncs only happen when the video system
+ is used, e.g. by outputting a character to the console.
+
+ It may also be shorter, since the video uclass will automatically
+ force a sync in certain situations.
+
+ Many video-output systems require a sync operation before any output
+ is visible. This may flush the CPU cache or perhaps copy the
+ display contents to a hardware framebuffer. Without this, change to
+ the video may never be displayed.
+
+config VIDEO_SYNC_CYCLIC_MS
+ int "Video-sync period in milliseconds for cyclic processing"
+ depends on CYCLIC
+ default 100 if SANDBOX
+ default 10
+ help
+ This sets the frequency of cyclic video syncs. The cyclic system is
+ used to ensure that when U-Boot is idle, it syncs the video. This
+ improves the responsiveness of the command line to new characters
+ being entered.
+
config PANEL
bool "Enable panel uclass support"
default y
#include <bloblist.h>
#include <console.h>
#include <cpu_func.h>
+#include <cyclic.h>
#include <dm.h>
#include <log.h>
#include <malloc.h>
*/
DECLARE_GLOBAL_DATA_PTR;
+struct cyclic_info;
+
/**
* struct video_uc_priv - Information for the video uclass
*
* available address to use for a device's framebuffer. It starts at
* gd->video_top and works downwards, running out of space when it hits
* gd->video_bottom.
+ * @cyc: handle for cyclic-execution function, or NULL if none
*/
struct video_uc_priv {
ulong video_ptr;
+ bool cyc_active;
+ struct cyclic_info cyc;
};
/** struct vid_rgb - Describes a video colour */
/* Flush video activity to the caches */
int video_sync(struct udevice *vid, bool force)
{
+ struct video_priv *priv = dev_get_uclass_priv(vid);
struct video_ops *ops = video_get_ops(vid);
int ret;
return ret;
}
+ if (CONFIG_IS_ENABLED(CYCLIC) && !force &&
+ get_timer(priv->last_sync) < CONFIG_VIDEO_SYNC_MS)
+ return 0;
+
/*
* flush_dcache_range() is declared in common.h but it seems that some
* architectures do not actually implement it. Is there a way to find
* out whether it exists? For now, ARM is safe.
*/
#if defined(CONFIG_ARM) && !CONFIG_IS_ENABLED(SYS_DCACHE_OFF)
- struct video_priv *priv = dev_get_uclass_priv(vid);
-
if (priv->flush_dcache) {
flush_dcache_range((ulong)priv->fb,
ALIGN((ulong)priv->fb + priv->fb_size,
CONFIG_SYS_CACHELINE_SIZE));
}
#elif defined(CONFIG_VIDEO_SANDBOX_SDL)
- struct video_priv *priv = dev_get_uclass_priv(vid);
- static ulong last_sync;
-
- if (force || get_timer(last_sync) > 100) {
- sandbox_sdl_sync(priv->fb);
- last_sync = get_timer(0);
- }
+ sandbox_sdl_sync(priv->fb);
#endif
+ priv->last_sync = get_timer(0);
+
return 0;
}
return vc_priv->y_charsize;
}
+static void video_idle(struct cyclic_info *cyc)
+{
+ video_sync_all();
+}
+
/* Set up the display ready for use */
static int video_post_probe(struct udevice *dev)
{
struct video_uc_plat *plat = dev_get_uclass_plat(dev);
+ struct video_uc_priv *uc_priv = uclass_get_priv(dev->uclass);
struct video_priv *priv = dev_get_uclass_priv(dev);
char name[30], drv[15], *str;
const char *drv_name = drv;
}
}
+ /* register cyclic as soon as the first video device is probed */
+ if (CONFIG_IS_ENABLED(CYCLIC) && (gd->flags && GD_FLG_RELOC) &&
+ !uc_priv->cyc_active) {
+ uint ms = CONFIG_IF_ENABLED_INT(CYCLIC, VIDEO_SYNC_CYCLIC_MS);
+
+ cyclic_register(&uc_priv->cyc, video_idle, ms * 1000,
+ "video_init");
+ uc_priv->cyc_active = true;
+ }
+
return 0;
};
return 0;
}
+__maybe_unused static int video_destroy(struct uclass *uc)
+{
+ struct video_uc_priv *uc_priv = uclass_get_priv(uc);
+
+ if (uc_priv->cyc_active) {
+ cyclic_unregister(&uc_priv->cyc);
+ uc_priv->cyc_active = false;
+ }
+
+ return 0;
+}
+
UCLASS_DRIVER(video) = {
.id = UCLASS_VIDEO,
.name = "video",
.priv_auto = sizeof(struct video_uc_priv),
.per_device_auto = sizeof(struct video_priv),
.per_device_plat_auto = sizeof(struct video_uc_plat),
+ CONFIG_IS_ENABLED(CYCLIC, (.destroy = video_destroy, ))
};
bool "Enable U-Boot watchdog reset"
depends on !HW_WATCHDOG
select CYCLIC
+ imply SPL_CYCLIC if SPL
help
This option enables U-Boot watchdog support where U-Boot is using
watchdog_reset function to service watchdog device in U-Boot. Enable
config SPL_WDT
bool "Enable driver model for watchdog timer drivers in SPL"
depends on SPL_DM
+ select SPL_CYCLIC if CYCLIC
help
Enable driver model for watchdog timer in SPL.
This is similar to CONFIG_WDT in U-Boot.
*/
struct event_state event_state;
#endif
-#ifdef CONFIG_CYCLIC
+#if CONFIG_IS_ENABLED(CYCLIC)
/**
* @cyclic_list: list of registered cyclic functions
*/
struct clk *clk_get_parent(struct clk *clk);
/**
- * clk_get_parent_rate() - Get parent of current clock rate.
+ * clk_get_parent_rate() - Get rate of current clock's parent.
* @clk: A clock struct that was previously successfully requested by
* clk_request/get_by_*().
*
* if not.
*/
int (*is_current)(struct udevice *dev);
+
+ /**
+ * release_core() - Relase a CPU core to the given address to run application
+ *
+ * @dev: Device to check (UCLASS_CPU)
+ * @addr: Address to relese the CPU core
+ * @return 0 if OK, -ve on error
+ */
+ int (*release_core)(const struct udevice *dev, phys_addr_t addr);
};
#define cpu_get_ops(dev) ((struct cpu_ops *)(dev)->driver->ops)
*/
struct udevice *cpu_get_current_dev(void);
+/**
+ * cpu_release_core() - Relase a CPU core to the given address to run application
+ *
+ * @return 0 if OK, -ve on error
+ */
+int cpu_release_core(const struct udevice *dev, phys_addr_t addr);
#endif
/** Function type for cyclic functions */
typedef void (*cyclic_func_t)(struct cyclic_info *c);
-#if defined(CONFIG_CYCLIC)
+#if CONFIG_IS_ENABLED(CYCLIC)
+
/**
* cyclic_register - Register a new cyclic function
*
{
return 0;
}
-#endif
+#endif /* CYCLIC */
#endif
* the LCD is updated
* @fg_col_idx: Foreground color code (bit 3 = bold, bit 0-2 = color)
* @bg_col_idx: Background color code (bit 3 = bold, bit 0-2 = color)
+ * @last_sync: Monotonic time of last video sync
*/
struct video_priv {
/* Things set up by the driver: */
bool flush_dcache;
u8 fg_col_idx;
u8 bg_col_idx;
+ ulong last_sync;
};
/**
/* Do init that is common to driver model and legacy networking */
void eth_common_init(void);
-/**
- * eth_env_set_enetaddr_by_index() - set the MAC address environment variable
- *
- * This sets up an environment variable with the given MAC address (@enetaddr).
- * The environment variable to be set is defined by <@base_name><@index>addr.
- * If @index is 0 it is omitted. For common Ethernet this means ethaddr,
- * eth1addr, etc.
- *
- * @base_name: Base name for variable, typically "eth"
- * @index: Index of interface being updated (>=0)
- * @enetaddr: Pointer to MAC address to put into the variable
- * Return: 0 if OK, other value on error
- */
-int eth_env_set_enetaddr_by_index(const char *base_name, int index,
- uchar *enetaddr);
-
int eth_mac_skip(int index);
void eth_current_changed(void);
void eth_set_dev(struct udevice *dev);
tftp_prev_block = tftp_cur_block;
tftp_cur_block = (unsigned short)(block + 1);
update_block_number();
- if (ack_ok)
+ if (ack_ok) {
+ if (block == 0 &&
+ tftp_state == STATE_SEND_WRQ){
+ /* connection's first ACK */
+ tftp_state = STATE_DATA;
+ tftp_remote_port = src;
+ }
tftp_send(); /* Send next data block */
+ }
}
}
#endif
ut_assertok(cpu_get_vendor(dev, text, sizeof(text)));
ut_assertok(strcmp(text, "Languid Example Garbage Inc."));
+ ut_assertok(cpu_release_core(dev, 0));
+
return 0;
}