diff options
Diffstat (limited to 'arch')
36 files changed, 2287 insertions, 163 deletions
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index c65cad54a6..09da1b375b 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig @@ -2208,6 +2208,8 @@ source "arch/arm/cpu/armv7/Kconfig" source "arch/arm/cpu/armv8/Kconfig" +source "arch/arm/cpu/armv8/crypto/Kconfig" + source "arch/arm/mach-imx/Kconfig" source "arch/arm/mach-nexell/Kconfig" diff --git a/arch/arm/cpu/armv8/Makefile b/arch/arm/cpu/armv8/Makefile index 85fe0475c8..6e1498b470 100644 --- a/arch/arm/cpu/armv8/Makefile +++ b/arch/arm/cpu/armv8/Makefile @@ -44,3 +44,4 @@ obj-$(CONFIG_TARGET_HIKEY) += hisilicon/ obj-$(CONFIG_ARMV8_PSCI) += psci.o obj-$(CONFIG_TARGET_BCMNS3) += bcmns3/ obj-$(CONFIG_XEN) += xen/ +obj-$(CONFIG_CRYPTO_SHA2_ARM64_CE) += crypto/ diff --git a/arch/arm/cpu/armv8/crypto/Kconfig b/arch/arm/cpu/armv8/crypto/Kconfig new file mode 100644 index 0000000000..379c673343 --- /dev/null +++ b/arch/arm/cpu/armv8/crypto/Kconfig @@ -0,0 +1,6 @@ +if ARM64 + +config CRYPTO_SHA2_ARM64_CE + tristate "SHA-224/SHA-256 digest algorithm (ARMv8 Crypto Extensions)" + +endif diff --git a/arch/arm/cpu/armv8/crypto/Makefile b/arch/arm/cpu/armv8/crypto/Makefile new file mode 100644 index 0000000000..8b23b166ed --- /dev/null +++ b/arch/arm/cpu/armv8/crypto/Makefile @@ -0,0 +1,4 @@ +# SPDX-License-Identifier: GPL-2.0-only + +obj-$(CONFIG_CRYPTO_SHA2_ARM64_CE) += sha2-ce.o +sha2-ce-y := sha2-ce-glue.o sha2-ce-core.o diff --git a/arch/arm/cpu/armv8/crypto/sha2-ce-core.S b/arch/arm/cpu/armv8/crypto/sha2-ce-core.S new file mode 100644 index 0000000000..ad76362dff --- /dev/null +++ b/arch/arm/cpu/armv8/crypto/sha2-ce-core.S @@ -0,0 +1,157 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * sha2-ce-core.S - core SHA-224/SHA-256 transform using v8 Crypto Extensions + * + * Copyright (C) 2014 Linaro Ltd <ard.biesheuvel@linaro.org> + * Copyright 2022 NXP + */ + +#include <linux/linkage.h> +#include <asm/macro.h> + + .text + .arch armv8-a+crypto + + dga .req q20 + dgav .req v20 + dgb .req q21 + dgbv .req v21 + + t0 .req v22 + t1 .req v23 + + dg0q .req q24 + dg0v .req v24 + dg1q .req q25 + dg1v .req v25 + dg2q .req q26 + dg2v .req v26 + + .macro add_only, ev, rc, s0 + mov dg2v.16b, dg0v.16b + .ifeq \ev + add t1.4s, v\s0\().4s, \rc\().4s + sha256h dg0q, dg1q, t0.4s + sha256h2 dg1q, dg2q, t0.4s + .else + .ifnb \s0 + add t0.4s, v\s0\().4s, \rc\().4s + .endif + sha256h dg0q, dg1q, t1.4s + sha256h2 dg1q, dg2q, t1.4s + .endif + .endm + + .macro add_update, ev, rc, s0, s1, s2, s3 + sha256su0 v\s0\().4s, v\s1\().4s + add_only \ev, \rc, \s1 + sha256su1 v\s0\().4s, v\s2\().4s, v\s3\().4s + .endm + + /* + * The SHA-256 round constants + */ + .section ".rodata", "a" + .align 4 +.Lsha2_rcon: + .word 0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5 + .word 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5 + .word 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3 + .word 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174 + .word 0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc + .word 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da + .word 0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7 + .word 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967 + .word 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13 + .word 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85 + .word 0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3 + .word 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070 + .word 0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5 + .word 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3 + .word 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208 + .word 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2 + + /* + * void sha2_ce_transform(struct sha256_ce_state *sst, u8 const *src, + * int blocks) + */ + .text +ENTRY(sha2_ce_transform) + /* load round constants */ + adr_l x8, .Lsha2_rcon + ld1 { v0.4s- v3.4s}, [x8], #64 + ld1 { v4.4s- v7.4s}, [x8], #64 + ld1 { v8.4s-v11.4s}, [x8], #64 + ld1 {v12.4s-v15.4s}, [x8] + + /* load state */ + ld1 {dgav.4s, dgbv.4s}, [x0] + + /* load sha256_ce_state::finalize */ + ldr_l w4, sha256_ce_offsetof_finalize, x4 + ldr w4, [x0, x4] + + /* load input */ +0: ld1 {v16.4s-v19.4s}, [x1], #64 + sub w2, w2, #1 + +CPU_LE( rev32 v16.16b, v16.16b ) +CPU_LE( rev32 v17.16b, v17.16b ) +CPU_LE( rev32 v18.16b, v18.16b ) +CPU_LE( rev32 v19.16b, v19.16b ) + +1: add t0.4s, v16.4s, v0.4s + mov dg0v.16b, dgav.16b + mov dg1v.16b, dgbv.16b + + add_update 0, v1, 16, 17, 18, 19 + add_update 1, v2, 17, 18, 19, 16 + add_update 0, v3, 18, 19, 16, 17 + add_update 1, v4, 19, 16, 17, 18 + + add_update 0, v5, 16, 17, 18, 19 + add_update 1, v6, 17, 18, 19, 16 + add_update 0, v7, 18, 19, 16, 17 + add_update 1, v8, 19, 16, 17, 18 + + add_update 0, v9, 16, 17, 18, 19 + add_update 1, v10, 17, 18, 19, 16 + add_update 0, v11, 18, 19, 16, 17 + add_update 1, v12, 19, 16, 17, 18 + + add_only 0, v13, 17 + add_only 1, v14, 18 + add_only 0, v15, 19 + add_only 1 + + /* update state */ + add dgav.4s, dgav.4s, dg0v.4s + add dgbv.4s, dgbv.4s, dg1v.4s + + /* handled all input blocks? */ + cbz w2, 2f + b 0b + + /* + * Final block: add padding and total bit count. + * Skip if the input size was not a round multiple of the block size, + * the padding is handled by the C code in that case. + */ +2: cbz x4, 3f + ldr_l w4, sha256_ce_offsetof_count, x4 + ldr x4, [x0, x4] + movi v17.2d, #0 + mov x8, #0x80000000 + movi v18.2d, #0 + ror x7, x4, #29 // ror(lsl(x4, 3), 32) + fmov d16, x8 + mov x4, #0 + mov v19.d[0], xzr + mov v19.d[1], x7 + b 1b + + /* store new state */ +3: st1 {dgav.4s, dgbv.4s}, [x0] + mov w0, w2 + ret +ENDPROC(sha2_ce_transform) diff --git a/arch/arm/cpu/armv8/crypto/sha2-ce-glue.c b/arch/arm/cpu/armv8/crypto/sha2-ce-glue.c new file mode 100644 index 0000000000..31e436ef1d --- /dev/null +++ b/arch/arm/cpu/armv8/crypto/sha2-ce-glue.c @@ -0,0 +1,66 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * sha2-ce-glue.c - SHA-256 using ARMv8 Crypto Extensions + * + * Copyright (C) 2014 - 2017 Linaro Ltd <ard.biesheuvel@linaro.org> + * Copyright 2022 NXP + */ + +#include <linux/kernel.h> +#include <linux/linkage.h> +#include <crypto/sha256_base.h> + +struct sha256_ce_state { + struct sha256_state sst; + u32 finalize; +}; + +extern const u32 sha256_ce_offsetof_count; +extern const u32 sha256_ce_offsetof_finalize; + +asmlinkage int sha2_ce_transform(struct sha256_ce_state *sst, u8 const *src, + int blocks); + +static void __sha2_ce_transform(struct sha256_state *sst, u8 const *src, + int blocks) +{ + while (blocks) { + int rem; + + rem = sha2_ce_transform(container_of(sst, struct sha256_ce_state, + sst), src, blocks); + src += (blocks - rem) * SHA256_BLOCK_SIZE; + blocks = rem; + } +} + +const u32 sha256_ce_offsetof_count = offsetof(struct sha256_ce_state, + sst.count); +const u32 sha256_ce_offsetof_finalize = offsetof(struct sha256_ce_state, + finalize); + +static void sha256_ce_update(struct sha256_ce_state *sctx, const u8 *data, + unsigned int len) +{ + sctx->finalize = 0; + sha256_base_do_update(&sctx->sst, data, len, __sha2_ce_transform); +} + +static void sha256_ce_final(struct sha256_ce_state *sctx, u8 *out) +{ + sctx->finalize = 0; + sha256_base_do_finalize(&sctx->sst, __sha2_ce_transform); + sha256_base_finish(&sctx->sst, out); +} + +/* + * Output = SHA-256( input buffer ). + */ +void sha256_ce(const unsigned char *input, unsigned int ilen, unsigned char *output) +{ + struct sha256_ce_state sctx; + + sha256_init(&sctx.sst); + sha256_ce_update(&sctx, input, ilen); + sha256_ce_final(&sctx, output); +} diff --git a/arch/arm/dts/Makefile b/arch/arm/dts/Makefile index f27ff45770..45a79f0201 100644 --- a/arch/arm/dts/Makefile +++ b/arch/arm/dts/Makefile @@ -1005,7 +1005,9 @@ dtb-$(CONFIG_ARCH_IMX8M) += \ imx8mq-kontron-pitx-imx8m.dtb dtb-$(CONFIG_ARCH_IMX9) += \ - imx93-11x11-evk.dtb + imx93-11x11-evk.dtb \ + imx93-9x9-qsb.dtb \ + imx93-9x9-qsb-ontat-wvga-panel.dts dtb-$(CONFIG_ARCH_IMXRT) += imxrt1050-evk.dtb \ imxrt1020-evk.dtb diff --git a/arch/arm/dts/fsl-imx8dxl-ddr3l-evk.dts b/arch/arm/dts/fsl-imx8dxl-ddr3l-evk.dts index 040e52912e..3fe19b9848 100644 --- a/arch/arm/dts/fsl-imx8dxl-ddr3l-evk.dts +++ b/arch/arm/dts/fsl-imx8dxl-ddr3l-evk.dts @@ -100,8 +100,8 @@ SC_P_EMMC0_CLK_CONN_NAND_READY_B 0x0e00004c SC_P_EMMC0_STROBE_CONN_NAND_CLE 0x0e00004c SC_P_EMMC0_RESET_B_CONN_NAND_WP_B 0x0e00004c - SC_P_EMMC0_CMD_CONN_NAND_DQS 0x0e00004c + SC_P_USDHC1_CD_B_CONN_NAND_DQS 0x0e00004c SC_P_USDHC1_RESET_B_CONN_NAND_WE_B 0x0e00004c SC_P_USDHC1_WP_CONN_NAND_ALE 0x0e00004c SC_P_USDHC1_VSELECT_CONN_NAND_RE_B 0x0e00004c diff --git a/arch/arm/dts/imx8mp-evk.dts b/arch/arm/dts/imx8mp-evk.dts index 0df546dfd0..61e8a70196 100644 --- a/arch/arm/dts/imx8mp-evk.dts +++ b/arch/arm/dts/imx8mp-evk.dts @@ -13,7 +13,7 @@ compatible = "fsl,imx8mp-evk", "fsl,imx8mp"; chosen { - bootargs = "console=ttymxc1,115200"; + bootargs = "console=ttymxc1,115200 earlycon=ec_imx6q,0x30890000,115200"; stdout-path = &uart2; }; diff --git a/arch/arm/dts/imx8mp.dtsi b/arch/arm/dts/imx8mp.dtsi index 2876b94b2a..4662d53183 100644 --- a/arch/arm/dts/imx8mp.dtsi +++ b/arch/arm/dts/imx8mp.dtsi @@ -979,7 +979,7 @@ #address-cells = <1>; #size-cells = <0>; compatible = "fsl,imx8mp-fspi-nand"; - reg = <0 0x30bb0000 0 0x10000>, <0 0x08000000 0 0x10000000>; + reg = <0x30bb0000 0x10000>, <0x08000000 0x10000000>; reg-names = "FlexSPI", "FlexSPI-memory"; status = "disabled"; }; diff --git a/arch/arm/dts/imx93-11x11-evk.dts b/arch/arm/dts/imx93-11x11-evk.dts index 38bf2aeb99..c82e5a9c67 100644 --- a/arch/arm/dts/imx93-11x11-evk.dts +++ b/arch/arm/dts/imx93-11x11-evk.dts @@ -458,16 +458,16 @@ &flexspi { pinctrl-names = "default"; pinctrl-0 = <&pinctrl_flexspi>; - status = "disabled"; + status = "okay"; - flash0: flash@0 { + flash0: mt25qu512a@0 { reg = <0>; #address-cells = <1>; #size-cells = <1>; compatible = "jedec,spi-nor"; spi-max-frequency = <80000000>; - spi-tx-bus-width = <1>; - spi-rx-bus-width = <1>; + spi-tx-bus-width = <4>; + spi-rx-bus-width = <4>; }; }; @@ -485,17 +485,11 @@ pinctrl_flexspi: flexspigrp { fsl,pins = < MX93_PAD_SD3_CMD__FLEXSPI1_A_SS0_B 0x42 - MX93_PAD_SD1_DATA3__FLEXSPI1_A_SS1_B 0x42 MX93_PAD_SD3_CLK__FLEXSPI1_A_SCLK 0x42 - MX93_PAD_SD1_STROBE__FLEXSPI1_A_DQS 0x42 MX93_PAD_SD3_DATA0__FLEXSPI1_A_DATA00 0x42 MX93_PAD_SD3_DATA1__FLEXSPI1_A_DATA01 0x42 MX93_PAD_SD3_DATA2__FLEXSPI1_A_DATA02 0x42 MX93_PAD_SD3_DATA3__FLEXSPI1_A_DATA03 0x42 - MX93_PAD_SD1_DATA4__FLEXSPI1_A_DATA04 0x42 - MX93_PAD_SD1_DATA5__FLEXSPI1_A_DATA05 0x42 - MX93_PAD_SD1_DATA6__FLEXSPI1_A_DATA06 0x42 - MX93_PAD_SD1_DATA7__FLEXSPI1_A_DATA07 0x42 >; }; diff --git a/arch/arm/dts/imx93-9x9-qsb-ontat-wvga-panel.dts b/arch/arm/dts/imx93-9x9-qsb-ontat-wvga-panel.dts new file mode 100644 index 0000000000..6eb09ec9e3 --- /dev/null +++ b/arch/arm/dts/imx93-9x9-qsb-ontat-wvga-panel.dts @@ -0,0 +1,65 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR MIT) +/* + * Copyright 2022 NXP + */ + +#include "imx93-9x9-qsb.dts" +#include "imx93-9x9-qsb-u-boot.dtsi" + +/ { + panel { + compatible = "ontat,kd50g21-40nt-a1", "simple-panel"; + enable-gpios = <&pcal6524 22 GPIO_ACTIVE_HIGH>; + + port { + panel_in: endpoint { + remote-endpoint = <&display_out>; + }; + }; + + display-timings { + native-mode = <&timing0>; + timing0: timing0 { + clock-frequency = <30000000>; + hactive = <800>; + vactive = <480>; + hfront-porch = <40>; + hback-porch = <40>; + hsync-len = <48>; + vback-porch = <29>; + vfront-porch = <13>; + vsync-len = <3>; + + vsync-active = <0>; + hsync-active = <0>; + }; + }; + }; +}; + +&lcdif { + status = "okay"; + /*assigned-clock-rates = <150000000>, <30000000>, <400000000>, <133333333>;*/ +}; + +¶llel_disp_fmt { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_lcdif>; + fsl,interface-pix-fmt = "rgb666"; + status = "okay"; + + ports { + port@1 { + reg = <1>; + + display_out: endpoint { + remote-endpoint = <&panel_in>; + }; + }; + }; +}; + +/* pin conflicts */ +&sai3 { + status = "disabled"; +}; diff --git a/arch/arm/dts/imx93-9x9-qsb-u-boot.dtsi b/arch/arm/dts/imx93-9x9-qsb-u-boot.dtsi new file mode 100644 index 0000000000..06935ce1e4 --- /dev/null +++ b/arch/arm/dts/imx93-9x9-qsb-u-boot.dtsi @@ -0,0 +1,178 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright 2022 NXP + */ + +/ { + wdt-reboot { + compatible = "wdt-reboot"; + wdt = <&wdog3>; + u-boot,dm-spl; + }; + + aliases { + usbgadget0 = &usbg1; + }; + + usbg1: usbg1 { + compatible = "fsl,imx27-usb-gadget"; + dr_mode = "peripheral"; + chipidea,usb = <&usbotg1>; + status = "okay"; + }; + + firmware { + optee { + compatible = "linaro,optee-tz"; + method = "smc"; + }; + }; +}; + +&{/soc@0} { + u-boot,dm-pre-reloc; + u-boot,dm-spl; +}; + +&aips1 { + u-boot,dm-spl; + u-boot,dm-pre-reloc; +}; + +&aips2 { + u-boot,dm-spl; +}; + +&aips3 { + u-boot,dm-spl; +}; + +&iomuxc { + u-boot,dm-spl; +}; + +®_usdhc2_vmmc { + u-boot,off-on-delay-us = <20000>; + u-boot,dm-spl; +}; + +&pinctrl_reg_usdhc2_vmmc { + u-boot,dm-spl; +}; + +&pinctrl_uart1 { + u-boot,dm-spl; +}; + +&pinctrl_usdhc2_gpio { + u-boot,dm-spl; +}; + +&pinctrl_usdhc2 { + u-boot,dm-spl; +}; + +&gpio1 { + u-boot,dm-spl; +}; + +&gpio2 { + u-boot,dm-spl; +}; + +&gpio3 { + u-boot,dm-spl; +}; + +&gpio4 { + u-boot,dm-spl; +}; + +&lpuart1 { + u-boot,dm-spl; +}; + +&usdhc1 { + u-boot,dm-spl; +}; + +&usdhc2 { + u-boot,dm-spl; + fsl,signal-voltage-switch-extra-delay-ms = <8>; +}; + +&lpi2c1 { + u-boot,dm-spl; +}; + +&lpi2c2 { + u-boot,dm-spl; +}; + +&lpi2c3 { + u-boot,dm-spl; +}; + +&{/soc@0/bus@44000000/i2c@44350000/pmic@25} { + u-boot,dm-spl; +}; + +&{/soc@0/bus@44000000/i2c@44350000/pmic@25/regulators} { + u-boot,dm-spl; +}; + +&pinctrl_lpi2c1 { + u-boot,dm-spl; +}; + +&pinctrl_lpi2c2 { + u-boot,dm-spl; +}; + +&eqos { + compatible = "fsl,imx-eqos"; +}; + +ðphy1 { + reset-gpios = <&pcal6524 15 GPIO_ACTIVE_LOW>; + reset-assert-us = <15000>; + reset-deassert-us = <100000>; +}; + +&usbotg1 { + status = "okay"; + extcon = <&ptn5110>; +}; + +&s4muap { + u-boot,dm-spl; + status = "okay"; +}; + +&clk { + u-boot,dm-pre-reloc; + u-boot,dm-spl; + /delete-property/ assigned-clocks; + /delete-property/ assigned-clock-rates; +}; + +&osc_32k { + u-boot,dm-pre-reloc; + u-boot,dm-spl; +}; + +&osc_24m { + u-boot,dm-pre-reloc; + u-boot,dm-spl; +}; + +&clk_ext1 { + u-boot,dm-pre-reloc; + u-boot,dm-spl; +}; + +&lcdif { + assigned-clocks = <&clk IMX93_CLK_MEDIA_AXI>, <&clk IMX93_CLK_MEDIA_APB>; + assigned-clock-parents = <&clk IMX93_CLK_SYS_PLL_PFD1>, <&clk IMX93_CLK_SYS_PLL_PFD1_DIV2>; + assigned-clock-rates = <400000000>, <133333334>; +}; diff --git a/arch/arm/dts/imx93-9x9-qsb.dts b/arch/arm/dts/imx93-9x9-qsb.dts new file mode 100644 index 0000000000..accb295c03 --- /dev/null +++ b/arch/arm/dts/imx93-9x9-qsb.dts @@ -0,0 +1,657 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR MIT) +/* + * Copyright 2022 NXP + */ + +/dts-v1/; + +#include <dt-bindings/usb/pd.h> +#include "imx93.dtsi" + +/ { + model = "NXP i.MX93 9x9 Quick Start Board"; + compatible = "fsl,imx93-9x9-qsb", "fsl,imx93"; + + chosen { + stdout-path = &lpuart1; + }; + + reserved-memory { + #address-cells = <2>; + #size-cells = <2>; + ranges; + + vdev0vring0: vdev0vring0@a4000000 { + reg = <0 0xa4000000 0 0x8000>; + no-map; + }; + + vdev0vring1: vdev0vring1@a4008000 { + reg = <0 0xa4008000 0 0x8000>; + no-map; + }; + + vdev1vring0: vdev1vring0@a4000000 { + reg = <0 0xa4010000 0 0x8000>; + no-map; + }; + + vdev1vring1: vdev1vring1@a4018000 { + reg = <0 0xa4018000 0 0x8000>; + no-map; + }; + + rsc_table: rsc_table@2021f000 { + reg = <0 0x2021f000 0 0x1000>; + no-map; + }; + + vdevbuffer: vdevbuffer@a4020000 { + compatible = "shared-dma-pool"; + reg = <0 0xa4020000 0 0x100000>; + no-map; + }; + }; + + cm33: imx93-cm33 { + compatible = "fsl,imx93-cm33"; + mbox-names = "tx", "rx", "rxdb"; + mboxes = <&mu1 0 1 + &mu1 1 1 + &mu1 3 1>; + memory-region = <&vdevbuffer>, <&vdev0vring0>, <&vdev0vring1>, + <&vdev1vring0>, <&vdev1vring1>, <&rsc_table>; + fsl,startup-delay-ms = <500>; + }; + + reg_usdhc2_vmmc: regulator-usdhc2 { + compatible = "regulator-fixed"; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_reg_usdhc2_vmmc>; + regulator-name = "VSD_3V3"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + gpio = <&gpio3 7 GPIO_ACTIVE_HIGH>; + enable-active-high; + }; + + reg_vref_1v8: regulator-adc-vref { + compatible = "regulator-fixed"; + regulator-name = "vref_1v8"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + }; + + usdhc3_pwrseq: usdhc3_pwrseq { + compatible = "mmc-pwrseq-simple"; + reset-gpios = <&pcal6524 20 GPIO_ACTIVE_LOW>; + }; + + reg_audio_pwr: regulator-audio-pwr { + compatible = "regulator-fixed"; + regulator-name = "audio-pwr"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + gpio = <&pcal6524 17 GPIO_ACTIVE_HIGH>; + enable-active-high; + regulator-always-on; + }; + + sound-wm8962 { + compatible = "fsl,imx-audio-wm8962"; + model = "wm8962-audio"; + audio-cpu = <&sai3>; + audio-codec = <&codec>; + hp-det-gpio = <&pcal6524 4 GPIO_ACTIVE_HIGH>; + audio-routing = + "Headphone Jack", "HPOUTL", + "Headphone Jack", "HPOUTR", + "Ext Spk", "SPKOUTL", + "Ext Spk", "SPKOUTR", + "AMIC", "MICBIAS", + "IN3R", "AMIC", + "IN1R", "AMIC"; + }; + + sound-micfil { + compatible = "fsl,imx-audio-card"; + model = "imx-audio-micfil"; + pri-dai-link { + link-name = "micfil hifi"; + format = "i2s"; + cpu { + sound-dai = <&micfil>; + }; + }; + }; + + bt_sco_codec: bt_sco_codec { + #sound-dai-cells = <1>; + compatible = "linux,bt-sco"; + }; + + sound-bt-sco { + compatible = "simple-audio-card"; + simple-audio-card,name = "bt-sco-audio"; + simple-audio-card,format = "dsp_a"; + simple-audio-card,bitclock-inversion; + simple-audio-card,frame-master = <&btcpu>; + simple-audio-card,bitclock-master = <&btcpu>; + + btcpu: simple-audio-card,cpu { + sound-dai = <&sai1>; + dai-tdm-slot-num = <2>; + dai-tdm-slot-width = <16>; + }; + + simple-audio-card,codec { + sound-dai = <&bt_sco_codec 1>; + }; + }; +}; + +&adc1 { + vref-supply = <®_vref_1v8>; + status = "okay"; +}; + +&eqos { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_eqos>; + phy-mode = "rgmii-id"; + phy-handle = <ðphy1>; + status = "okay"; + + mdio { + compatible = "snps,dwmac-mdio"; + #address-cells = <1>; + #size-cells = <0>; + clock-frequency = <5000000>; + + ethphy1: ethernet-phy@1 { + compatible = "ethernet-phy-ieee802.3-c22"; + reg = <1>; + eee-broken-1000t; + rtl821x,aldps-disable; + rtl821x,clkout-disable; + }; + }; +}; + +&flexspi { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_flexspi>; + status = "okay"; + + flash0: mt25qu512a@0 { + reg = <0>; + #address-cells = <1>; + #size-cells = <1>; + compatible = "jedec,spi-nor"; + spi-max-frequency = <80000000>; + spi-tx-bus-width = <4>; + spi-rx-bus-width = <4>; + }; +}; + +&lpi2c1 { + #address-cells = <1>; + #size-cells = <0>; + clock-frequency = <400000>; + pinctrl-names = "default", "sleep"; + pinctrl-0 = <&pinctrl_lpi2c1>; + pinctrl-1 = <&pinctrl_lpi2c1>; + status = "okay"; + + codec: wm8962@1a { + compatible = "wlf,wm8962"; + reg = <0x1a>; + clocks = <&clk IMX93_CLK_SAI3_GATE>; + DCVDD-supply = <®_audio_pwr>; + DBVDD-supply = <®_audio_pwr>; + AVDD-supply = <®_audio_pwr>; + CPVDD-supply = <®_audio_pwr>; + MICVDD-supply = <®_audio_pwr>; + PLLVDD-supply = <®_audio_pwr>; + SPKVDD1-supply = <®_audio_pwr>; + SPKVDD2-supply = <®_audio_pwr>; + gpio-cfg = < + 0x0000 /* 0:Default */ + 0x0000 /* 1:Default */ + 0x0000 /* 2:FN_DMICCLK */ + 0x0000 /* 3:Default */ + 0x0000 /* 4:FN_DMICCDAT */ + 0x0000 /* 5:Default */ + >; + }; + + ptn5110: tcpc@50 { + compatible = "nxp,ptn5110"; + reg = <0x50>; + interrupt-parent = <&gpio3>; + interrupts = <27 IRQ_TYPE_LEVEL_LOW>; + status = "okay"; + + port { + typec1_dr_sw: endpoint { + remote-endpoint = <&usb1_drd_sw>; + }; + }; + + typec1_con: connector { + compatible = "usb-c-connector"; + label = "USB-C"; + power-role = "dual"; + data-role = "dual"; + try-power-role = "sink"; + source-pdos = <PDO_FIXED(5000, 3000, PDO_FIXED_USB_COMM)>; + sink-pdos = <PDO_FIXED(5000, 3000, PDO_FIXED_USB_COMM) + PDO_VAR(5000, 20000, 3000)>; + op-sink-microwatt = <15000000>; + self-powered; + }; + }; +}; + +&lpi2c2 { + #address-cells = <1>; + #size-cells = <0>; + clock-frequency = <400000>; + pinctrl-names = "default", "sleep"; + pinctrl-0 = <&pinctrl_lpi2c2>; + pinctrl-1 = <&pinctrl_lpi2c2>; + status = "okay"; + + pmic@25 { + compatible = "nxp,pca9451a"; + reg = <0x25>; + interrupt-parent = <&pcal6524>; + interrupts = <11 IRQ_TYPE_LEVEL_LOW>; + + regulators { + buck1: BUCK1 { + regulator-name = "BUCK1"; + regulator-min-microvolt = <600000>; + regulator-max-microvolt = <2187500>; + regulator-boot-on; + regulator-always-on; + regulator-ramp-delay = <3125>; + }; + + buck2: BUCK2 { + regulator-name = "BUCK2"; + regulator-min-microvolt = <600000>; + regulator-max-microvolt = <2187500>; + regulator-boot-on; + regulator-always-on; + regulator-ramp-delay = <3125>; + }; + + buck4: BUCK4{ + regulator-name = "BUCK4"; + regulator-min-microvolt = <600000>; + regulator-max-microvolt = <3400000>; + regulator-boot-on; + regulator-always-on; + }; + + buck5: BUCK5{ + regulator-name = "BUCK5"; + regulator-min-microvolt = <600000>; + regulator-max-microvolt = <3400000>; + regulator-boot-on; + regulator-always-on; + }; + + buck6: BUCK6 { + regulator-name = "BUCK6"; + regulator-min-microvolt = <600000>; + regulator-max-microvolt = <3400000>; + regulator-boot-on; + regulator-always-on; + }; + + ldo1: LDO1 { + regulator-name = "LDO1"; + regulator-min-microvolt = <1600000>; + regulator-max-microvolt = <3300000>; + regulator-boot-on; + regulator-always-on; + }; + + ldo2: LDO2 { + regulator-name = "LDO2"; + regulator-min-microvolt = <800000>; + regulator-max-microvolt = <1150000>; + regulator-boot-on; + regulator-always-on; + }; + + ldo3: LDO3 { + regulator-name = "LDO3"; + regulator-min-microvolt = <800000>; + regulator-max-microvolt = <3300000>; + regulator-boot-on; + regulator-always-on; + }; + + ldo4: LDO4 { + regulator-name = "LDO4"; + regulator-min-microvolt = <800000>; + regulator-max-microvolt = <3300000>; + regulator-boot-on; + regulator-always-on; + }; + + ldo5: LDO5 { + regulator-name = "LDO5"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <3300000>; + regulator-boot-on; + regulator-always-on; + }; + }; + }; + + pcal6524: gpio@22 { + compatible = "nxp,pcal6524"; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_pcal6524>; + reg = <0x22>; + gpio-controller; + #gpio-cells = <2>; + interrupt-controller; + #interrupt-cells = <2>; + interrupt-parent = <&gpio3>; + interrupts = <26 IRQ_TYPE_LEVEL_LOW>; + }; +}; + +&lpuart1 { /* console */ + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_uart1>; + status = "okay"; + clocks = <&clk IMX93_CLK_LPUART1_GATE>, <&clk IMX93_CLK_LPUART1_GATE>; + clock-names = "ipg", "per"; +}; + +&lpuart5 { + /* BT */ + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_uart5>; + status = "disabled"; +}; + +&micfil { + #sound-dai-cells = <0>; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_pdm>; + assigned-clocks = <&clk IMX93_CLK_PDM>; + assigned-clock-parents = <&clk IMX93_CLK_AUDIO_PLL>; + assigned-clock-rates = <196608000>; + status = "okay"; +}; + +&mu1 { + status = "okay"; +}; + +&mu2 { + status = "okay"; +}; + +&sai1 { + #sound-dai-cells = <0>; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_sai1>; + assigned-clocks = <&clk IMX93_CLK_SAI1>; + assigned-clock-parents = <&clk IMX93_CLK_AUDIO_PLL>; + assigned-clock-rates = <12288000>; + status = "okay"; +}; + +&sai3 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_sai3>; + assigned-clocks = <&clk IMX93_CLK_SAI3>; + assigned-clock-parents = <&clk IMX93_CLK_AUDIO_PLL>; + assigned-clock-rates = <12288000>; + fsl,sai-mclk-direction-output; + status = "okay"; +}; + +&usbotg1 { + dr_mode = "otg"; + hnp-disable; + srp-disable; + adp-disable; + usb-role-switch; + disable-over-current; + samsung,picophy-pre-emp-curr-control = <3>; + samsung,picophy-dc-vol-level-adjust = <7>; + status = "okay"; + + port { + usb1_drd_sw: endpoint { + remote-endpoint = <&typec1_dr_sw>; + }; + }; +}; + +&usdhc1 { + pinctrl-names = "default", "state_100mhz", "state_200mhz"; + pinctrl-0 = <&pinctrl_usdhc1>; + pinctrl-1 = <&pinctrl_usdhc1>; + pinctrl-2 = <&pinctrl_usdhc1>; + bus-width = <8>; + non-removable; + status = "okay"; +}; + +&usdhc2 { + pinctrl-names = "default", "state_100mhz", "state_200mhz"; + pinctrl-0 = <&pinctrl_usdhc2>, <&pinctrl_usdhc2_gpio>; + pinctrl-1 = <&pinctrl_usdhc2>, <&pinctrl_usdhc2_gpio>; + pinctrl-2 = <&pinctrl_usdhc2>, <&pinctrl_usdhc2_gpio>; + cd-gpios = <&gpio3 00 GPIO_ACTIVE_LOW>; + vmmc-supply = <®_usdhc2_vmmc>; + bus-width = <4>; + status = "okay"; + no-sdio; + no-mmc; +}; + +&usdhc3 { + pinctrl-names = "default", "state_100mhz", "state_200mhz"; + pinctrl-0 = <&pinctrl_usdhc3>; + pinctrl-1 = <&pinctrl_usdhc3>; + pinctrl-2 = <&pinctrl_usdhc3>; + mmc-pwrseq = <&usdhc3_pwrseq>; + pinctrl-assert-gpios = <&pcal6524 13 GPIO_ACTIVE_HIGH>; + bus-width = <4>; + keep-power-in-suspend; + non-removable; + wakeup-source; + fsl,sdio-async-interrupt-enabled; + status = "okay"; + + wifi_wake_host { + compatible = "nxp,wifi-wake-host"; + interrupt-parent = <&pcal6524>; + interrupts = <5 IRQ_TYPE_LEVEL_LOW>; + interrupt-names = "host-wake"; + }; +}; + +&iomuxc { + pinctrl_eqos: eqosgrp { + fsl,pins = < + MX93_PAD_ENET1_MDC__ENET_QOS_MDC 0x57e + MX93_PAD_ENET1_MDIO__ENET_QOS_MDIO 0x57e + MX93_PAD_ENET1_RD0__ENET_QOS_RGMII_RD0 0x57e + MX93_PAD_ENET1_RD1__ENET_QOS_RGMII_RD1 0x57e + MX93_PAD_ENET1_RD2__ENET_QOS_RGMII_RD2 0x57e + MX93_PAD_ENET1_RD3__ENET_QOS_RGMII_RD3 0x57e + MX93_PAD_ENET1_RXC__CCM_ENET_QOS_CLOCK_GENERATE_RX_CLK 0x5fe + MX93_PAD_ENET1_RX_CTL__ENET_QOS_RGMII_RX_CTL 0x57e + MX93_PAD_ENET1_TD0__ENET_QOS_RGMII_TD0 0x57e + MX93_PAD_ENET1_TD1__ENET_QOS_RGMII_TD1 0x57e + MX93_PAD_ENET1_TD2__ENET_QOS_RGMII_TD2 0x57e + MX93_PAD_ENET1_TD3__ENET_QOS_RGMII_TD3 0x57e + MX93_PAD_ENET1_TXC__CCM_ENET_QOS_CLOCK_GENERATE_TX_CLK 0x5fe + MX93_PAD_ENET1_TX_CTL__ENET_QOS_RGMII_TX_CTL 0x57e + >; + }; + + pinctrl_flexspi: flexspigrp { + fsl,pins = < + MX93_PAD_SD3_CMD__FLEXSPI1_A_SS0_B 0x42 + MX93_PAD_SD3_CLK__FLEXSPI1_A_SCLK 0x42 + MX93_PAD_SD3_DATA0__FLEXSPI1_A_DATA00 0x42 + MX93_PAD_SD3_DATA1__FLEXSPI1_A_DATA01 0x42 + MX93_PAD_SD3_DATA2__FLEXSPI1_A_DATA02 0x42 + MX93_PAD_SD3_DATA3__FLEXSPI1_A_DATA03 0x42 + >; + }; + + pinctrl_lpi2c1: lpi2c1grp { + fsl,pins = < + MX93_PAD_I2C1_SCL__LPI2C1_SCL 0x40000b9e + MX93_PAD_I2C1_SDA__LPI2C1_SDA 0x40000b9e + >; + }; + + pinctrl_lpi2c2: lpi2c2grp { + fsl,pins = < + MX93_PAD_I2C2_SCL__LPI2C2_SCL 0x40000b9e + MX93_PAD_I2C2_SDA__LPI2C2_SDA 0x40000b9e + >; + }; + + pinctrl_pcal6524: pcal6524grp { + fsl,pins = < + MX93_PAD_CCM_CLKO1__GPIO3_IO26 0x31e + >; + }; + + pinctrl_uart1: uart1grp { + fsl,pins = < + MX93_PAD_UART1_RXD__LPUART1_RX 0x31e + MX93_PAD_UART1_TXD__LPUART1_TX 0x31e + >; + }; + + pinctrl_uart5: uart5grp { + fsl,pins = < + MX93_PAD_DAP_TDO_TRACESWO__LPUART5_TX 0x31e + MX93_PAD_DAP_TDI__LPUART5_RX 0x31e + MX93_PAD_DAP_TMS_SWDIO__LPUART5_RTS_B 0x31e + MX93_PAD_DAP_TCLK_SWCLK__LPUART5_CTS_B 0x31e + >; + }; + + pinctrl_usdhc1: usdhc1grp { + fsl,pins = < + MX93_PAD_SD1_CLK__USDHC1_CLK 0x17fe + MX93_PAD_SD1_CMD__USDHC1_CMD 0x13fe + MX93_PAD_SD1_DATA0__USDHC1_DATA0 0x13fe + MX93_PAD_SD1_DATA1__USDHC1_DATA1 0x13fe + MX93_PAD_SD1_DATA2__USDHC1_DATA2 0x13fe + MX93_PAD_SD1_DATA3__USDHC1_DATA3 0x13fe + MX93_PAD_SD1_DATA4__USDHC1_DATA4 0x13fe + MX93_PAD_SD1_DATA5__USDHC1_DATA5 0x13fe + MX93_PAD_SD1_DATA6__USDHC1_DATA6 0x13fe + MX93_PAD_SD1_DATA7__USDHC1_DATA7 0x13fe + MX93_PAD_SD1_STROBE__USDHC1_STROBE 0x17fe + >; + }; + + pinctrl_reg_usdhc2_vmmc: regusdhc2vmmcgrp { + fsl,pins = < + MX93_PAD_SD2_RESET_B__GPIO3_IO07 0x31e + >; + }; + + pinctrl_usdhc2_gpio: usdhc2gpiogrp { + fsl,pins = < + MX93_PAD_SD2_CD_B__GPIO3_IO00 0x31e + >; + }; + + pinctrl_usdhc2: usdhc2grp { + fsl,pins = < + MX93_PAD_SD2_CLK__USDHC2_CLK 0x17fe + MX93_PAD_SD2_CMD__USDHC2_CMD 0x13fe + MX93_PAD_SD2_DATA0__USDHC2_DATA0 0x13fe + MX93_PAD_SD2_DATA1__USDHC2_DATA1 0x13fe + MX93_PAD_SD2_DATA2__USDHC2_DATA2 0x13fe + MX93_PAD_SD2_DATA3__USDHC2_DATA3 0x13fe + MX93_PAD_SD2_VSELECT__USDHC2_VSELECT 0x51e + >; + }; + + pinctrl_usdhc3: usdhc3grp { + fsl,pins = < + MX93_PAD_SD3_CLK__USDHC3_CLK 0x17fe + MX93_PAD_SD3_CMD__USDHC3_CMD 0x13fe + MX93_PAD_SD3_DATA0__USDHC3_DATA0 0x13fe + MX93_PAD_SD3_DATA1__USDHC3_DATA1 0x13fe + MX93_PAD_SD3_DATA2__USDHC3_DATA2 0x13fe + MX93_PAD_SD3_DATA3__USDHC3_DATA3 0x13fe + >; + }; + + pinctrl_sai1: sai1grp { + fsl,pins = < + MX93_PAD_SAI1_TXC__SAI1_TX_BCLK 0x31e + MX93_PAD_SAI1_TXFS__SAI1_TX_SYNC 0x31e + MX93_PAD_SAI1_TXD0__SAI1_TX_DATA00 0x31e + MX93_PAD_SAI1_RXD0__SAI1_RX_DATA00 0x31e + >; + }; + + pinctrl_sai3: sai3grp { + fsl,pins = < + MX93_PAD_GPIO_IO26__SAI3_TX_SYNC 0x31e + MX93_PAD_GPIO_IO16__SAI3_TX_BCLK 0x31e + MX93_PAD_GPIO_IO17__SAI3_MCLK 0x31e + MX93_PAD_GPIO_IO19__SAI3_TX_DATA00 0x31e + MX93_PAD_GPIO_IO20__SAI3_RX_DATA00 0x31e + >; + }; + + pinctrl_pdm: pdmgrp { + fsl,pins = < + MX93_PAD_PDM_CLK__PDM_CLK 0x31e + MX93_PAD_PDM_BIT_STREAM0__PDM_BIT_STREAM00 0x31e + MX93_PAD_PDM_BIT_STREAM1__PDM_BIT_STREAM01 0x31e + >; + }; + + pinctrl_lcdif: lcdifgrp { + fsl,pins = < + MX93_PAD_GPIO_IO00__MEDIAMIX_DISP_CLK 0x31e + MX93_PAD_GPIO_IO01__MEDIAMIX_DISP_DE 0x31e + MX93_PAD_GPIO_IO02__MEDIAMIX_DISP_VSYNC 0x31e + MX93_PAD_GPIO_IO03__MEDIAMIX_DISP_HSYNC 0x31e + MX93_PAD_GPIO_IO04__MEDIAMIX_DISP_DATA00 0x31e + MX93_PAD_GPIO_IO05__MEDIAMIX_DISP_DATA01 0x31e + MX93_PAD_GPIO_IO06__MEDIAMIX_DISP_DATA02 0x31e + MX93_PAD_GPIO_IO07__MEDIAMIX_DISP_DATA03 0x31e + MX93_PAD_GPIO_IO08__MEDIAMIX_DISP_DATA04 0x31e + MX93_PAD_GPIO_IO09__MEDIAMIX_DISP_DATA05 0x31e + MX93_PAD_GPIO_IO10__MEDIAMIX_DISP_DATA06 0x31e + MX93_PAD_GPIO_IO11__MEDIAMIX_DISP_DATA07 0x31e + MX93_PAD_GPIO_IO12__MEDIAMIX_DISP_DATA08 0x31e + MX93_PAD_GPIO_IO13__MEDIAMIX_DISP_DATA09 0x31e + MX93_PAD_GPIO_IO14__MEDIAMIX_DISP_DATA10 0x31e + MX93_PAD_GPIO_IO15__MEDIAMIX_DISP_DATA11 0x31e + MX93_PAD_GPIO_IO16__MEDIAMIX_DISP_DATA12 0x31e + MX93_PAD_GPIO_IO17__MEDIAMIX_DISP_DATA13 0x31e + MX93_PAD_GPIO_IO18__MEDIAMIX_DISP_DATA14 0x31e + MX93_PAD_GPIO_IO19__MEDIAMIX_DISP_DATA15 0x31e + MX93_PAD_GPIO_IO20__MEDIAMIX_DISP_DATA16 0x31e + MX93_PAD_GPIO_IO21__MEDIAMIX_DISP_DATA17 0x31e + >; + }; +}; diff --git a/arch/arm/dts/imx93.dtsi b/arch/arm/dts/imx93.dtsi index 59a09b5ec5..be4626d5e7 100644 --- a/arch/arm/dts/imx93.dtsi +++ b/arch/arm/dts/imx93.dtsi @@ -36,6 +36,7 @@ serial5 = &lpuart6; serial6 = &lpuart7; serial7 = &lpuart8; + spi0 = &flexspi; isi0 = &isi_0; i2c0 = &lpi2c1; i2c1 = &lpi2c2; @@ -447,58 +448,20 @@ }; tmu: tmu@44482000 { - compatible = "fsl,imx93-tmu", "fsl,imx8mq-tmu"; - little-endian; + compatible = "fsl,imx93-tmu"; reg = <0x44482000 0x1000>; clocks = <&clk IMX93_CLK_TMC_GATE>; - fsl,tmu-range = <0xb0000 0xa0026 0x80048 0x70061>; - fsl,tmu-calibration = <0x00000000 0x00000023 - 0x00000001 0x00000029 - 0x00000002 0x0000002f - 0x00000003 0x00000035 - 0x00000004 0x0000003d - 0x00000005 0x00000043 - 0x00000006 0x0000004b - 0x00000007 0x00000051 - 0x00000008 0x00000057 - 0x00000009 0x0000005f - 0x0000000a 0x00000067 - 0x0000000b 0x0000006f - - 0x00010000 0x0000001b - 0x00010001 0x00000023 - 0x00010002 0x0000002b - 0x00010003 0x00000033 - 0x00010004 0x0000003b - 0x00010005 0x00000043 - 0x00010006 0x0000004b - 0x00010007 0x00000055 - 0x00010008 0x0000005d - 0x00010009 0x00000067 - 0x0001000a 0x00000070 - - 0x00020000 0x00000017 - 0x00020001 0x00000023 - 0x00020002 0x0000002d - 0x00020003 0x00000037 - 0x00020004 0x00000041 - 0x00020005 0x0000004b - 0x00020006 0x00000057 - 0x00020007 0x00000063 - 0x00020008 0x0000006f - - 0x00030000 0x00000015 - 0x00030001 0x00000021 - 0x00030002 0x0000002d - 0x00030003 0x00000039 - 0x00030004 0x00000045 - 0x00030005 0x00000053 - 0x00030006 0x0000005f - 0x00030007 0x00000071>; + little-endian; + fsl,tmu-calibration = <0x0000000e 0x800000da + 0x00000029 0x800000e9 + 0x00000056 0x80000102 + 0x000000a2 0x8000012a + 0x00000116 0x80000166 + 0x00000195 0x800001a7 + 0x000001b2 0x800001b6>; #thermal-sensor-cells = <0>; - status = "disabled"; }; - + micfil: micfil@44520000 { compatible = "fsl,imx93-micfil"; reg = <0x44520000 0x10000>; @@ -848,9 +811,11 @@ reg = <0x425e0000 0x10000>, <0x28000000 0x10000000>; reg-names = "fspi_base", "fspi_mmap"; interrupts = <GIC_SPI 55 IRQ_TYPE_LEVEL_HIGH>; - clocks = <&clk IMX93_CLK_DUMMY>, - <&clk IMX93_CLK_DUMMY>; + clocks = <&clk IMX93_CLK_FLEXSPI1_GATE>, + <&clk IMX93_CLK_FLEXSPI1_GATE>; clock-names = "fspi", "fspi_en"; + assigned-clock-rates = <80000000>; + assigned-clocks = <&clk IMX93_CLK_FLEXSPI1>; status = "disabled"; }; @@ -1332,6 +1297,25 @@ power-domains = <&media_blk_ctrl IMX93_MEDIABLK_PD_MIPI_DSI>; status = "disabled"; }; + + parallel_disp_fmt: dpi { + compatible = "fsl,imx93-parallel-display-format"; + /* power-domains = <&mediamix>; [Not enable for U-Boot], otherwise driver probe fail */ + status = "disabled"; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + + dpi_to_lcdif: endpoint { + remote-endpoint = <&lcdif_to_dpi>; + }; + }; + }; + }; }; ldb: ldb@4ac10020 { @@ -1447,6 +1431,11 @@ reg = <1>; remote-endpoint = <&ldb_ch0>; }; + + lcdif_to_dpi: endpoint@2 { + reg = <2>; + remote-endpoint = <&dpi_to_lcdif>; + }; }; }; diff --git a/arch/arm/include/asm/arch-imx/cpu.h b/arch/arm/include/asm/arch-imx/cpu.h index f326c90312..36f51e0792 100644 --- a/arch/arm/include/asm/arch-imx/cpu.h +++ b/arch/arm/include/asm/arch-imx/cpu.h @@ -62,6 +62,13 @@ #define MXC_CPU_MX7ULP 0xE1 /* Temporally hard code */ #define MXC_CPU_VF610 0xF6 /* dummy ID */ #define MXC_CPU_IMX93 0xC1 /* dummy ID */ +#define MXC_CPU_IMX9351 0xC2 /* dummy ID */ +#define MXC_CPU_IMX9332 0xC3 /* dummy ID */ +#define MXC_CPU_IMX9331 0xC4 /* dummy ID */ +#define MXC_CPU_IMX9322 0xC5 /* dummy ID */ +#define MXC_CPU_IMX9321 0xC6 /* dummy ID */ +#define MXC_CPU_IMX9312 0xC7 /* dummy ID */ +#define MXC_CPU_IMX9311 0xC8 /* dummy ID */ #define MXC_SOC_MX6 0x60 #define MXC_SOC_MX7 0x70 diff --git a/arch/arm/include/asm/arch-imx8ulp/imx8ulp-pins.h b/arch/arm/include/asm/arch-imx8ulp/imx8ulp-pins.h index 3638f0db53..cdea5d6f3c 100644 --- a/arch/arm/include/asm/arch-imx8ulp/imx8ulp-pins.h +++ b/arch/arm/include/asm/arch-imx8ulp/imx8ulp-pins.h @@ -73,6 +73,6 @@ enum { IMX8ULP_PAD_PTF5__SDHC1_D2 = IOMUX_PAD(0x0114, 0x0114, 0x8, 0x0A6C, 0x2, 0), IMX8ULP_PAD_PTF0__SDHC1_D1 = IOMUX_PAD(0x0100, 0x0100, 0x8, 0x0A68, 0x2, 0), IMX8ULP_PAD_PTF1__SDHC1_D0 = IOMUX_PAD(0x0104, 0x0104, 0x8, 0x0A64, 0x2, 0), - + IMX8ULP_PAD_PTF7__PTF7 = IOMUX_PAD(0x011C, 0x011C, 0x1, 0x0000, 0x0, 0), }; #endif /* __ASM_ARCH_IMX8ULP_PINS_H__ */ diff --git a/arch/arm/include/asm/arch-imx9/clock.h b/arch/arm/include/asm/arch-imx9/clock.h index 5cb762d429..758ee26ff2 100644 --- a/arch/arm/include/asm/arch-imx9/clock.h +++ b/arch/arm/include/asm/arch-imx9/clock.h @@ -217,6 +217,7 @@ u32 mxc_get_clock(enum mxc_clock clk); void dram_pll_init(ulong pll_val); void dram_enable_bypass(ulong clk_val); void dram_disable_bypass(void); +void set_arm_core_max_clk(void); int configure_intpll(enum ccm_clk_src pll, u32 freq); diff --git a/arch/arm/include/asm/arch-imx9/ddr.h b/arch/arm/include/asm/arch-imx9/ddr.h index 83983ed391..af5e6b5764 100644 --- a/arch/arm/include/asm/arch-imx9/ddr.h +++ b/arch/arm/include/asm/arch-imx9/ddr.h @@ -13,11 +13,15 @@ #define DDR_PHY_BASE 0x4E100000 #define DDRMIX_BLK_CTRL_BASE 0x4E010000 +#define REG_DDR_CS0_BNDS (DDR_CTL_BASE + 0x0) +#define REG_DDR_CS1_BNDS (DDR_CTL_BASE + 0x8) #define REG_DDRDSR_2 (DDR_CTL_BASE + 0xB24) #define REG_DDR_TIMING_CFG_0 (DDR_CTL_BASE + 0x104) #define REG_DDR_SDRAM_CFG (DDR_CTL_BASE + 0x110) +#define REG_DDR_SDRAM_CFG2 (DDR_CTL_BASE + 0x114) #define REG_DDR_TIMING_CFG_4 (DDR_CTL_BASE + 0x160) #define REG_DDR_DEBUG_19 (DDR_CTL_BASE + 0xF48) +#define REG_DDR_ERR_EN (DDR_CTL_BASE + 0x1000) #define SRC_BASE_ADDR (0x44460000) #define SRC_DPHY_BASE_ADDR (SRC_BASE_ADDR + 0x1400) diff --git a/arch/arm/include/asm/mach-imx/s400_api.h b/arch/arm/include/asm/mach-imx/s400_api.h index 9e3c8136df..3862c5a39b 100644 --- a/arch/arm/include/asm/mach-imx/s400_api.h +++ b/arch/arm/include/asm/mach-imx/s400_api.h @@ -25,6 +25,7 @@ #define ELE_RET_LIFECYCLE_UP_REQ (0xA0) #define ELE_GET_EVENTS_REQ (0xA2) #define ELE_START_RNG (0xA3) +#define ELE_GENERATE_DEK_BLOB (0xAF) #define ELE_ENABLE_PATCH_REQ (0xC3) #define ELE_RELEASE_RDC_REQ (0xC4) #define ELE_GET_FW_STATUS_REQ (0xC5) @@ -144,5 +145,8 @@ int ahab_get_fw_status(u32 *status, u32 *response); int ahab_release_m33_trout(void); int ahab_get_events(u32 *events, u32 *events_cnt, u32 *response); int ahab_start_rng(void); +int ahab_generate_dek_blob(u32 key_id, u32 src_paddr, u32 dst_paddr, + u32 max_output_size); +int ahab_write_secure_fuse(ulong signed_msg_blk, u32 *response); #endif diff --git a/arch/arm/include/asm/mach-imx/sys_proto.h b/arch/arm/include/asm/mach-imx/sys_proto.h index 57557db715..04505d948c 100644 --- a/arch/arm/include/asm/mach-imx/sys_proto.h +++ b/arch/arm/include/asm/mach-imx/sys_proto.h @@ -84,7 +84,16 @@ struct bd_info; #define is_imx8qxp() (is_cpu_type(MXC_CPU_IMX8QXP)) #define is_imx8dxl() (is_cpu_type(MXC_CPU_IMX8DXL)) -#define is_imx93() (is_cpu_type(MXC_CPU_IMX93)) +#define is_imx93() (is_cpu_type(MXC_CPU_IMX93) || is_cpu_type(MXC_CPU_IMX9331) || \ + is_cpu_type(MXC_CPU_IMX9332) || is_cpu_type(MXC_CPU_IMX9351) || is_cpu_type(MXC_CPU_IMX9322) || \ + is_cpu_type(MXC_CPU_IMX9321) || is_cpu_type(MXC_CPU_IMX9312) || is_cpu_type(MXC_CPU_IMX9311)) +#define is_imx9351() (is_cpu_type(MXC_CPU_IMX9351)) +#define is_imx9332() (is_cpu_type(MXC_CPU_IMX9332)) +#define is_imx9331() (is_cpu_type(MXC_CPU_IMX9331)) +#define is_imx9322() (is_cpu_type(MXC_CPU_IMX9322)) +#define is_imx9321() (is_cpu_type(MXC_CPU_IMX9321)) +#define is_imx9312() (is_cpu_type(MXC_CPU_IMX9312)) +#define is_imx9311() (is_cpu_type(MXC_CPU_IMX9311)) #define is_imxrt1020() (is_cpu_type(MXC_CPU_IMXRT1020)) #define is_imxrt1050() (is_cpu_type(MXC_CPU_IMXRT1050)) diff --git a/arch/arm/include/asm/macro.h b/arch/arm/include/asm/macro.h index ec0171e0e6..4e982892f8 100644 --- a/arch/arm/include/asm/macro.h +++ b/arch/arm/include/asm/macro.h @@ -3,6 +3,7 @@ * include/asm-arm/macro.h * * Copyright (C) 2009 Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com> + * Copyright 2022 NXP */ #ifndef __ASM_ARM_MACRO_H__ @@ -356,6 +357,45 @@ lr .req x30 .endm #endif +/* + * Select code when configured for LE. + */ +#ifdef CONFIG_CPU_BIG_ENDIAN +#define CPU_LE(code...) +#else +#define CPU_LE(code...) code +#endif + +/* + * Pseudo-ops for PC-relative adr/ldr <reg>, <symbol> where + * <symbol> is within the range +/- 4 GB of the PC. + */ + /* + * @dst: destination register (64 bit wide) + * @sym: name of the symbol + */ + .macro adr_l, dst, sym + adrp \dst, \sym + add \dst, \dst, :lo12:\sym + .endm + + /* + * @dst: destination register (32 or 64 bit wide) + * @sym: name of the symbol + * @tmp: optional 64-bit scratch register to be used if <dst> is a + * 32-bit wide register, in which case it cannot be used to hold + * the address + */ + .macro ldr_l, dst, sym, tmp= + .ifb \tmp + adrp \dst, \sym + ldr \dst, [\dst, :lo12:\sym] + .else + adrp \tmp, \sym + ldr \dst, [\tmp, :lo12:\sym] + .endif + .endm + #endif /* CONFIG_ARM64 */ #endif /* __ASSEMBLY__ */ diff --git a/arch/arm/mach-imx/Kconfig b/arch/arm/mach-imx/Kconfig index b51a0464bf..3fe77a5e49 100644 --- a/arch/arm/mach-imx/Kconfig +++ b/arch/arm/mach-imx/Kconfig @@ -117,6 +117,7 @@ config CMD_DEKBLOB select IMX_CAAM_DEK_ENCAP if ARCH_MX6 || ARCH_MX7 || ARCH_MX7ULP select IMX_OPTEE_DEK_ENCAP if ARCH_IMX8M select IMX_SECO_DEK_ENCAP if ARCH_IMX8 + select IMX_ELE_DEK_ENCAP if ARCH_IMX8ULP || ARCH_IMX9 help This enables the 'dek_blob' command which is used with the Freescale secure boot mechanism. This command encapsulates and @@ -145,6 +146,12 @@ config IMX_SECO_DEK_ENCAP This enabled the DEK blob encapsulation with the SECO API. This option is only available on imx8. +config IMX_ELE_DEK_ENCAP + bool "Support the DEK blob encapsulation with ELE" + help + This enabled the DEK blob encapsulation with the ELE API. This option + is only available on imx8ulp and imx9. + config CMD_PRIBLOB bool "Support the set_priblob_bitfield command" depends on HAS_CAAM && IMX_HAB diff --git a/arch/arm/mach-imx/cmd_dek.c b/arch/arm/mach-imx/cmd_dek.c index 701bf516df..9e69f2c505 100644 --- a/arch/arm/mach-imx/cmd_dek.c +++ b/arch/arm/mach-imx/cmd_dek.c @@ -1,6 +1,7 @@ // SPDX-License-Identifier: GPL-2.0+ /* * Copyright 2008-2015 Freescale Semiconductor, Inc. + * Copyright 2022 NXP * * Command for encapsulating DEK blob */ @@ -20,6 +21,11 @@ #include <asm/arch/sci/sci.h> #include <asm/mach-imx/image.h> #endif +#ifdef CONFIG_IMX_ELE_DEK_ENCAP +#include <asm/mach-imx/s400_api.h> +#include <asm/mach-imx/image.h> +#endif + #include <cpu_func.h> /** @@ -284,6 +290,84 @@ error: } #endif /* CONFIG_IMX_SECO_DEK_ENCAP */ +#ifdef CONFIG_IMX_ELE_DEK_ENCAP + +#define DEK_BLOB_HDR_SIZE 8 +#define AHAB_PRIVATE_KEY 0x81 +#define AHAB_DEK_BLOB 0x01 +#define AHAB_ALG_AES 0x03 +#define AHAB_128_AES_KEY 0x10 +#define AHAB_192_AES_KEY 0x18 +#define AHAB_256_AES_KEY 0x20 + +static int blob_encap_dek(u32 src_addr, u32 dst_addr, u32 len) +{ + u8 in_size, out_size; + u8 *src_ptr, *dst_ptr; + struct generate_key_blob_hdr hdr; + + /* Set sizes */ + in_size = sizeof(struct generate_key_blob_hdr) + len / 8; + out_size = BLOB_SIZE(len / 8) + DEK_BLOB_HDR_SIZE; + + /* Get src and dst virtual addresses */ + src_ptr = map_sysmem(src_addr, in_size); + dst_ptr = map_sysmem(dst_addr, out_size); + + /* Check addr input */ + if (!(src_ptr && dst_ptr)) { + debug("src_addr or dst_addr invalid\n"); + return -1; + } + + /* Build key header */ + hdr.version = 0x0; + hdr.length_lsb = in_size; + hdr.length_msb = 0x00; + hdr.tag = AHAB_PRIVATE_KEY; + hdr.flags = AHAB_DEK_BLOB; + hdr.algorithm = AHAB_ALG_AES; + hdr.mode = 0x0; /* Not used by the ELE */ + + switch (len) { + case 128: + hdr.size = AHAB_128_AES_KEY; + break; + case 192: + hdr.size = AHAB_192_AES_KEY; + break; + case 256: + hdr.size = AHAB_256_AES_KEY; + break; + default: + /* Not supported */ + debug("Invalid DEK size. Valid sizes are 128, 192 and 256b\n"); + return -1; + } + + /* Move input key and append blob header */ + memmove((void *)(src_ptr + sizeof(struct generate_key_blob_hdr)), + (void *)src_ptr, len / 8); + memcpy((void *)src_ptr, (void *)&hdr, + sizeof(struct generate_key_blob_hdr)); + + /* Flush the cache */ + flush_dcache_range(src_addr, src_addr + in_size); + flush_dcache_range((ulong)dst_ptr, (ulong)(dst_ptr + + roundup(out_size, ARCH_DMA_MINALIGN))); + + /* Call ELE */ + if (ahab_generate_dek_blob(0x00, src_addr, dst_addr, out_size)) + return -1; + + /* Invalidate output buffer */ + invalidate_dcache_range((ulong)dst_ptr, (ulong)(dst_ptr + + roundup(out_size, ARCH_DMA_MINALIGN))); + + return 0; +} +#endif /* CONFIG_IMX_ELE_DEK_ENCAP */ + /** * do_dek_blob() - Handle the "dek_blob" command-line command * @cmdtp: Command data struct pointer diff --git a/arch/arm/mach-imx/cmd_qspihdr.c b/arch/arm/mach-imx/cmd_qspihdr.c index 6e2758664f..ef4a3cf113 100644 --- a/arch/arm/mach-imx/cmd_qspihdr.c +++ b/arch/arm/mach-imx/cmd_qspihdr.c @@ -235,6 +235,7 @@ static int do_qspihdr_check(int argc, char * const argv[], int flag) unsigned long addr; char *endp; void *tmp; + int ret; #if defined(CONFIG_MX6) || defined(CONFIG_MX7) || defined(CONFIG_ARCH_MX7ULP) int off = QSPI_HDR_OFF + QSPI_HDR_TAG_OFF; @@ -266,7 +267,11 @@ static int do_qspihdr_check(int argc, char * const argv[], int flag) return 1; } } else { - spi_flash_read(flash, off, 4, &buf); + ret = spi_flash_read(flash, off, 4, &buf); + if (ret) { + printf("flash read failed, ret: %d\n", ret); + return -1; + } if (buf == tag) { if (flag & FLAG_VERBOSE) @@ -398,6 +403,7 @@ static int do_qspihdr_dump(int argc, char * const argv[]) char *endp; void *tmp; void *buf; + int ret; #if defined(CONFIG_MX6) || defined(CONFIG_MX7) || defined(CONFIG_ARCH_MX7ULP) int off = QSPI_HDR_OFF; @@ -431,7 +437,11 @@ static int do_qspihdr_dump(int argc, char * const argv[]) return 0; } - spi_flash_read(flash, off, HDR_LEN, buf); + ret = spi_flash_read(flash, off, HDR_LEN, buf); + if (ret) { + printf("flash read failed, ret: %d\n", ret); + return -1; + } hdr_dump(buf); free(buf); diff --git a/arch/arm/mach-imx/ele_ahab.c b/arch/arm/mach-imx/ele_ahab.c index 6daa7a96a0..192f90e6b1 100644 --- a/arch/arm/mach-imx/ele_ahab.c +++ b/arch/arm/mach-imx/ele_ahab.c @@ -568,6 +568,39 @@ static int do_ahab_status(struct cmd_tbl *cmdtp, int flag, int argc, return 0; } +static int do_sec_fuse_prog(struct cmd_tbl *cmdtp, int flag, int argc, + char *const argv[]) +{ + ulong addr; + u32 header, response; + + if (argc < 2) + return CMD_RET_USAGE; + + addr = simple_strtoul(argv[1], NULL, 16); + header = *(u32 *)addr; + + if ((header & 0xff0000ff) != 0x89000000) { + printf("Wrong Signed message block format, header 0x%x\n", header); + return CMD_RET_FAILURE; + } + + header = (header & 0xffff00) >> 8; + + printf("Signed Message block at 0x%lx, size 0x%x\n", addr, header); + flush_dcache_range(addr, addr + header - 1); + + if (ahab_write_secure_fuse(addr, &response)) { + printf("Program secure fuse failed, response 0x%x\n", response); + return CMD_RET_FAILURE; + } + + printf("Program secure fuse completed, response 0x%x\n", response); + + return CMD_RET_SUCCESS; +} + + U_BOOT_CMD(auth_cntr, CONFIG_SYS_MAXARGS, 1, do_authenticate, "autenticate OS container via AHAB", "addr\n" @@ -588,3 +621,9 @@ U_BOOT_CMD(ahab_status, CONFIG_SYS_MAXARGS, 1, do_ahab_status, "display AHAB lifecycle only", "" ); + +U_BOOT_CMD(ahab_sec_fuse_prog, CONFIG_SYS_MAXARGS, 1, do_sec_fuse_prog, + "Program secure fuse via signed message block", + "addr\n" + "addr - Signed message block for secure fuse\n" +); diff --git a/arch/arm/mach-imx/imx8/Kconfig b/arch/arm/mach-imx/imx8/Kconfig index b2b8ade0bd..7abcfeca86 100644 --- a/arch/arm/mach-imx/imx8/Kconfig +++ b/arch/arm/mach-imx/imx8/Kconfig @@ -176,6 +176,7 @@ config TARGET_IMX8DXL_EVK bool "Support i.MX8DXL EVK board" select BOARD_LATE_INIT select IMX8DXL + select CRYPTO_SHA2_ARM64_CE select FSL_CAAM select FSL_BLOB select ARCH_MISC_INIT diff --git a/arch/arm/mach-imx/imx8/ahab.c b/arch/arm/mach-imx/imx8/ahab.c index 3c3c4cdc4f..deb18a3bb2 100644 --- a/arch/arm/mach-imx/imx8/ahab.c +++ b/arch/arm/mach-imx/imx8/ahab.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0+ /* - * Copyright 2018-2019 NXP + * Copyright 2018-2019, 2022 NXP */ #include <common.h> @@ -16,6 +16,7 @@ #include <asm/mach-imx/image.h> #include <console.h> #include <cpu_func.h> +#include <crypto/sha2.h> #include <asm/mach-imx/ahab.h> DECLARE_GLOBAL_DATA_PTR; @@ -25,6 +26,8 @@ DECLARE_GLOBAL_DATA_PTR; #define SECO_LOCAL_SEC_SEC_SECURE_RAM_BASE (0x60000000UL) #define SECO_PT 2U +#define AHAB_HASH_TYPE_MASK 0x00000700 +#define AHAB_HASH_TYPE_SHA256 0 int ahab_auth_cntr_hdr(struct container_hdr *container, u16 length) { @@ -130,6 +133,9 @@ int authenticate_os_container(ulong addr) u16 length; struct boot_img_t *img; unsigned long s, e; +#ifdef CONFIG_CRYPTO_SHA2_ARM64_CE + u8 hash_value[SHA256_DIGEST_SIZE]; +#endif if (addr % 4) { puts("Error: Image's address is not 4 byte aligned\n"); @@ -179,9 +185,23 @@ int authenticate_os_container(ulong addr) flush_dcache_range(s, e); +#ifdef CONFIG_CRYPTO_SHA2_ARM64_CE + if (((img->hab_flags & AHAB_HASH_TYPE_MASK) >> 8) == AHAB_HASH_TYPE_SHA256) { + sha256_ce((void *)img->dst, img->size, hash_value); + err = memcmp(&img->hash, &hash_value, SHA256_DIGEST_SIZE); + if (err) { + printf("img %d hash comparison failed, error %d\n", i, err); + ret = -EIO; + goto exit; + } + } else { +#endif ret = ahab_verify_cntr_image(img, i); if (ret) goto exit; +#ifdef CONFIG_CRYPTO_SHA2_ARM64_CE + } +#endif } exit: diff --git a/arch/arm/mach-imx/imx8m/clock_imx8mm.c b/arch/arm/mach-imx/imx8m/clock_imx8mm.c index d6be307e6e..203c52d1d3 100644 --- a/arch/arm/mach-imx/imx8m/clock_imx8mm.c +++ b/arch/arm/mach-imx/imx8m/clock_imx8mm.c @@ -83,7 +83,6 @@ static int fracpll_configure(enum pll_clocks pll, u32 freq) case ANATOP_DRAM_PLL: setbits_le32(GPC_BASE_ADDR + 0xEC, 1 << 7); setbits_le32(GPC_BASE_ADDR + 0xF8, 1 << 5); - writel(SRC_DDR1_ENABLE_MASK, SRC_BASE_ADDR + 0x1004); pll_base = &ana_pll->dram_pll_gnrl_ctl; break; diff --git a/arch/arm/mach-imx/imx8ulp/cgc.c b/arch/arm/mach-imx/imx8ulp/cgc.c index d3c0e64cd6..b19268c822 100644 --- a/arch/arm/mach-imx/imx8ulp/cgc.c +++ b/arch/arm/mach-imx/imx8ulp/cgc.c @@ -136,42 +136,34 @@ void cgc1_pll3_init(ulong freq) clrbits_le32(&cgc1_regs->pll3div_vco, BIT(7)); clrbits_le32(&cgc1_regs->pll3pfdcfg, 0x3F); - - if (IS_ENABLED(CONFIG_IMX8ULP_LD_MODE)) { - setbits_le32(&cgc1_regs->pll3pfdcfg, 25 << 0); - clrsetbits_le32(&cgc1_regs->nicclk, GENMASK(26, 21), 3 << 21); /* 195M */ - } else if (IS_ENABLED(CONFIG_IMX8ULP_ND_MODE)) { - setbits_le32(&cgc1_regs->pll3pfdcfg, 21 << 0); - clrsetbits_le32(&cgc1_regs->nicclk, GENMASK(26, 21), 1 << 21); /* 231M */ - } else { - setbits_le32(&cgc1_regs->pll3pfdcfg, 30 << 0); /* 324M */ - } - + setbits_le32(&cgc1_regs->pll3pfdcfg, 30 << 0); /* PFD0 324M */ clrbits_le32(&cgc1_regs->pll3pfdcfg, BIT(7)); while (!(readl(&cgc1_regs->pll3pfdcfg) & BIT(6))) ; clrbits_le32(&cgc1_regs->pll3pfdcfg, 0x3F << 8); - setbits_le32(&cgc1_regs->pll3pfdcfg, 25 << 8); + setbits_le32(&cgc1_regs->pll3pfdcfg, 25 << 8); /* PFD1 389M */ clrbits_le32(&cgc1_regs->pll3pfdcfg, BIT(15)); while (!(readl(&cgc1_regs->pll3pfdcfg) & BIT(14))) ; clrbits_le32(&cgc1_regs->pll3pfdcfg, 0x3F << 16); - setbits_le32(&cgc1_regs->pll3pfdcfg, 25 << 16); + setbits_le32(&cgc1_regs->pll3pfdcfg, 30 << 16); /* PFD2 324M */ clrbits_le32(&cgc1_regs->pll3pfdcfg, BIT(23)); while (!(readl(&cgc1_regs->pll3pfdcfg) & BIT(22))) ; clrbits_le32(&cgc1_regs->pll3pfdcfg, 0x3F << 24); - setbits_le32(&cgc1_regs->pll3pfdcfg, 29 << 24); + setbits_le32(&cgc1_regs->pll3pfdcfg, 25 << 24); /* PFD3 389M */ clrbits_le32(&cgc1_regs->pll3pfdcfg, BIT(31)); while (!(readl(&cgc1_regs->pll3pfdcfg) & BIT(30))) ; clrbits_le32(&cgc1_regs->pll3div_pfd0, 0x3f3f3f3f); - clrbits_le32(&cgc1_regs->pll3div_pfd1, 0x3f3f3f3f); - + if (IS_ENABLED(CONFIG_IMX8ULP_LD_MODE) || IS_ENABLED(CONFIG_IMX8ULP_ND_MODE)) + clrsetbits_le32(&cgc1_regs->pll3div_pfd1, 0x3f3f3f3f, 0x03010000); /* Set PFD3 DIV1 to 194M, PFD3 DIV2 to 97M */ + else + clrsetbits_le32(&cgc1_regs->pll3div_pfd1, 0x3f3f3f3f, 0x01000000); /* Set PFD3 DIV1 to 389M, PFD3 DIV2 to 194M */ clrbits_le32(&cgc1_regs->pll3div_pfd0, BIT(7)); clrbits_le32(&cgc1_regs->pll3div_pfd0, BIT(15)); clrbits_le32(&cgc1_regs->pll3div_pfd0, BIT(23)); @@ -182,6 +174,17 @@ void cgc1_pll3_init(ulong freq) clrbits_le32(&cgc1_regs->pll3div_pfd1, BIT(23)); clrbits_le32(&cgc1_regs->pll3div_pfd1, BIT(31)); + /* NIC_AP: + * OD source PLL3 PFD0, 324M + * ND source FRO192, 192M + * LD source FRO192, 96M + */ + if (IS_ENABLED(CONFIG_IMX8ULP_LD_MODE)) { + clrsetbits_le32(&cgc1_regs->nicclk, GENMASK(26, 21), 1 << 21); + } else { + clrbits_le32(&cgc1_regs->nicclk, GENMASK(26, 21)); + } + if (!IS_ENABLED(CONFIG_IMX8ULP_LD_MODE) && !IS_ENABLED(CONFIG_IMX8ULP_ND_MODE)) { clrsetbits_le32(&cgc1_regs->nicclk, GENMASK(29, 28), BIT(28)); /* nicclk select pll3 pfd0 */ while (!(readl(&cgc1_regs->nicclk) & BIT(27))) @@ -221,18 +224,9 @@ void cgc2_pll4_init(bool pll4_reset) /* Enable all 4 PFDs */ setbits_le32(&cgc2_regs->pll4pfdcfg, 18 << 0); /* 528 */ - if (IS_ENABLED(CONFIG_IMX8ULP_LD_MODE)) { - setbits_le32(&cgc2_regs->pll4pfdcfg, 24 << 8); - clrsetbits_le32(&cgc2_regs->niclpavclk, GENMASK(26, 21), 3 << 21); /* 99Mhz for NIC_LPAV */ - } else if (IS_ENABLED(CONFIG_IMX8ULP_ND_MODE)) { - setbits_le32(&cgc2_regs->pll4pfdcfg, 24 << 8); - clrsetbits_le32(&cgc2_regs->niclpavclk, GENMASK(26, 21), 1 << 21); /* 198Mhz for NIC_LPAV */ - } else { - setbits_le32(&cgc2_regs->pll4pfdcfg, 30 << 8); /* 316.8Mhz for NIC_LPAV */ - clrbits_le32(&cgc2_regs->niclpavclk, GENMASK(26, 21)); - } - setbits_le32(&cgc2_regs->pll4pfdcfg, 12 << 16); /* 792 */ - setbits_le32(&cgc2_regs->pll4pfdcfg, 24 << 24); /* 396 */ + setbits_le32(&cgc2_regs->pll4pfdcfg, 30 << 8); /* 316.8Mhz for NIC_LPAV */ + setbits_le32(&cgc2_regs->pll4pfdcfg, 30 << 16); /* 316.8Mhz */ + setbits_le32(&cgc2_regs->pll4pfdcfg, 24 << 24); /* 396Mhz */ clrbits_le32(&cgc2_regs->pll4pfdcfg, BIT(7) | BIT(15) | BIT(23) | BIT(31)); @@ -244,9 +238,22 @@ void cgc2_pll4_init(bool pll4_reset) clrbits_le32(&cgc2_regs->pll4div_pfd0, BIT(7) | BIT(15) | BIT(23) | BIT(31)); clrbits_le32(&cgc2_regs->pll4div_pfd1, BIT(7) | BIT(15) | BIT(23) | BIT(31)); - clrsetbits_le32(&cgc2_regs->niclpavclk, GENMASK(29, 28), BIT(28)); - while (!(readl(&cgc2_regs->niclpavclk) & BIT(27))) - ; + /* NIC_LPAV: + * OD source PLL4 PFD1, 316.8M + * ND source FRO192, 192M + * LD source FRO192, 96M + */ + if (IS_ENABLED(CONFIG_IMX8ULP_LD_MODE)) { + clrsetbits_le32(&cgc2_regs->niclpavclk, GENMASK(26, 21), 1 << 21); + } else { + clrbits_le32(&cgc2_regs->niclpavclk, GENMASK(26, 21)); + } + + if (!IS_ENABLED(CONFIG_IMX8ULP_LD_MODE) && !IS_ENABLED(CONFIG_IMX8ULP_ND_MODE)) { + clrsetbits_le32(&cgc2_regs->niclpavclk, GENMASK(29, 28), BIT(28)); + while (!(readl(&cgc2_regs->niclpavclk) & BIT(27))) + ; + } } void cgc2_pll4_pfd_config(enum cgc_clk pllpfd, u32 pfd) diff --git a/arch/arm/mach-imx/imx8ulp/clock.c b/arch/arm/mach-imx/imx8ulp/clock.c index 2898c8b96c..17dff404fb 100644 --- a/arch/arm/mach-imx/imx8ulp/clock.c +++ b/arch/arm/mach-imx/imx8ulp/clock.c @@ -183,37 +183,20 @@ void clock_init_late(void) */ cgc1_pll3_init(540672000); - if (IS_ENABLED(CONFIG_IMX8ULP_LD_MODE) || IS_ENABLED(CONFIG_IMX8ULP_ND_MODE)) { - pcc_clock_enable(4, SDHC0_PCC4_SLOT, false); - pcc_clock_sel(4, SDHC0_PCC4_SLOT, PLL3_PFD2_DIV2); - pcc_clock_enable(4, SDHC0_PCC4_SLOT, true); - pcc_reset_peripheral(4, SDHC0_PCC4_SLOT, false); - - pcc_clock_enable(4, SDHC1_PCC4_SLOT, false); - pcc_clock_sel(4, SDHC1_PCC4_SLOT, PLL3_PFD2_DIV2); - pcc_clock_enable(4, SDHC1_PCC4_SLOT, true); - pcc_reset_peripheral(4, SDHC1_PCC4_SLOT, false); - - pcc_clock_enable(4, SDHC2_PCC4_SLOT, false); - pcc_clock_sel(4, SDHC2_PCC4_SLOT, PLL3_PFD2_DIV2); - pcc_clock_enable(4, SDHC2_PCC4_SLOT, true); - pcc_reset_peripheral(4, SDHC2_PCC4_SLOT, false); - } else { - pcc_clock_enable(4, SDHC0_PCC4_SLOT, false); - pcc_clock_sel(4, SDHC0_PCC4_SLOT, PLL3_PFD1_DIV2); - pcc_clock_enable(4, SDHC0_PCC4_SLOT, true); - pcc_reset_peripheral(4, SDHC0_PCC4_SLOT, false); - - pcc_clock_enable(4, SDHC1_PCC4_SLOT, false); - pcc_clock_sel(4, SDHC1_PCC4_SLOT, PLL3_PFD2_DIV1); - pcc_clock_enable(4, SDHC1_PCC4_SLOT, true); - pcc_reset_peripheral(4, SDHC1_PCC4_SLOT, false); - - pcc_clock_enable(4, SDHC2_PCC4_SLOT, false); - pcc_clock_sel(4, SDHC2_PCC4_SLOT, PLL3_PFD2_DIV1); - pcc_clock_enable(4, SDHC2_PCC4_SLOT, true); - pcc_reset_peripheral(4, SDHC2_PCC4_SLOT, false); - } + pcc_clock_enable(4, SDHC0_PCC4_SLOT, false); + pcc_clock_sel(4, SDHC0_PCC4_SLOT, PLL3_PFD3_DIV1); /* 389M for OD, 194M for LD/ND*/ + pcc_clock_enable(4, SDHC0_PCC4_SLOT, true); + pcc_reset_peripheral(4, SDHC0_PCC4_SLOT, false); + + pcc_clock_enable(4, SDHC1_PCC4_SLOT, false); + pcc_clock_sel(4, SDHC1_PCC4_SLOT, PLL3_PFD3_DIV2); /* 194M for OD, 97M for LD/ND */ + pcc_clock_enable(4, SDHC1_PCC4_SLOT, true); + pcc_reset_peripheral(4, SDHC1_PCC4_SLOT, false); + + pcc_clock_enable(4, SDHC2_PCC4_SLOT, false); + pcc_clock_sel(4, SDHC2_PCC4_SLOT, PLL3_PFD3_DIV2); /* 194M for OD, 97M for LD/ND*/ + pcc_clock_enable(4, SDHC2_PCC4_SLOT, true); + pcc_reset_peripheral(4, SDHC2_PCC4_SLOT, false); /* enable MU0_MUB clock before access the register of MU0_MUB */ pcc_clock_enable(3, MU0_B_PCC3_SLOT, true); @@ -432,6 +415,8 @@ void reset_lcdclk(void) pcc_reset_peripheral(5, DCNANO_PCC5_SLOT, true); } +/* PLL4 PFD0 max frequency */ +#define PLL4_PFD0_MAX_RATE 600000 /*khz*/ void mxs_set_lcdclk(u32 base_addr, u32 freq_in_khz) { u8 pcd, best_pcd = 0; @@ -450,6 +435,9 @@ void mxs_set_lcdclk(u32 base_addr, u32 freq_in_khz) for (div = 1; div <= 64; div++) { parent_rate = pll4_rate; parent_rate = parent_rate * 18 / pfd; + if (parent_rate > PLL4_PFD0_MAX_RATE) + continue; + parent_rate = parent_rate / div; for (pcd = 0; pcd < 8; pcd++) { diff --git a/arch/arm/mach-imx/imx8ulp/upower/upower_hal.c b/arch/arm/mach-imx/imx8ulp/upower/upower_hal.c index 87152ca818..ee215a4c76 100644 --- a/arch/arm/mach-imx/imx8ulp/upower/upower_hal.c +++ b/arch/arm/mach-imx/imx8ulp/upower/upower_hal.c @@ -14,6 +14,24 @@ #define UPOWER_AP_MU1_ADDR 0x29280000 +#define PS_RTD BIT(0) +#define PS_DSP BIT(1) +#define PS_A35_0 BIT(2) +#define PS_A35_1 BIT(3) +#define PS_L2 BIT(4) +#define PS_FAST_NIC BIT(5) +#define PS_APD_PERIPH BIT(6) +#define PS_GPU3D BIT(7) +#define PS_HIFI4 BIT(8) +#define PS_DDR GENMASK(12, 9) +#define PS_PXP_EPDC BIT(13) +#define PS_MIPI_DSI BIT(14) +#define PS_MIPI_CSI BIT(15) +#define PS_NIC_LPAV BIT(16) +#define PS_FUSION_AO BIT(17) +#define PS_FUSE BIT(18) +#define PS_UPOWER BIT(19) + static struct MU_tag *muptr = (struct MU_tag *)UPOWER_AP_MU1_ADDR; extern void upwr_txrx_isr(void); @@ -124,6 +142,7 @@ int upower_init(void) u32 fw_major, fw_minor, fw_vfixes; u32 soc_id; int status; + upwr_resp_t err_code; uint32_t swton; uint64_t memon; @@ -156,27 +175,92 @@ int upower_init(void) } } while(0); - swton = 0xfff80; + swton = PS_UPOWER | PS_FUSE | PS_FUSION_AO | PS_NIC_LPAV | PS_PXP_EPDC | PS_DDR | + PS_HIFI4 | PS_GPU3D | PS_MIPI_DSI; ret = upwr_pwm_power_on(&swton, NULL /* no memories */, NULL /* no callback */); if (ret) printf("Turn on switches fail %d\n", ret); else - printf("Turn on switches ok\n"); - upower_wait_resp(); - ret = upwr_poll_req_status(UPWR_SG_PWRMGMT, NULL, NULL, &ret_val, 1000); + printf("Turning on switches...\n"); + + upower_wait_resp(); + ret = upwr_poll_req_status(UPWR_SG_PWRMGMT, NULL, &err_code, &ret_val, 1000); if (ret != UPWR_REQ_OK) - printk("Faliure %d\n", ret); + printf("Turn on switches faliure %d, err_code %d, ret_val 0x%x\n", ret, err_code, ret_val); + else + printf("Turn on switches ok\n"); - memon = 0x3FFFFFFFFFFFFCUL; + /* + * Ascending Order -> bit [0:54) + * CA35 Core 0 L1 cache + * CA35 Core 1 L1 cache + * L2 Cache 0 + * L2 Cache 1 + * L2 Cache victim/tag + * CAAM Secure RAM + * DMA1 RAM + * FlexSPI2 FIFO, Buffer + * SRAM0 + * AD ROM + * USB0 TX/RX RAM + * uSDHC0 FIFO RAM + * uSDHC1 FIFO RAM + * uSDHC2 FIFO and USB1 TX/RX RAM + * GIC RAM + * ENET TX FIXO + * Reserved(Brainshift) + * DCNano Tile2Linear and RGB Correction + * DCNano Cursor and FIFO + * EPDC LUT + * EPDC FIFO + * DMA2 RAM + * GPU2D RAM Group 1 + * GPU2D RAM Group 2 + * GPU3D RAM Group 1 + * GPU3D RAM Group 2 + * HIFI4 Caches, IRAM, DRAM + * ISI Buffers + * MIPI-CSI FIFO + * MIPI-DSI FIFO + * PXP Caches, Buffers + * SRAM1 + * Casper RAM + * DMA0 RAM + * FlexCAN RAM + * FlexSPI0 FIFO, Buffer + * FlexSPI1 FIFO, Buffer + * CM33 Cache + * PowerQuad RAM + * ETF RAM + * Sentinel PKC, Data RAM1, Inst RAM0/1 + * Sentinel ROM + * uPower IRAM/DRAM + * uPower ROM + * CM33 ROM + * SSRAM Partition 0 + * SSRAM Partition 1 + * SSRAM Partition 2,3,4 + * SSRAM Partition 5 + * SSRAM Partition 6 + * SSRAM Partition 7_a(128KB) + * SSRAM Partition 7_b(64KB) + * SSRAM Partition 7_c(64KB) + * Sentinel Data RAM0, Inst RAM2 + */ + /* MIPI-CSI FIFO BIT28 not set */ + memon = 0x3FFFFFEFFFFFFCUL; ret = upwr_pwm_power_on(NULL, (const uint32_t *)&memon /* no memories */, NULL /* no callback */); if (ret) printf("Turn on memories fail %d\n", ret); else - printf("Turn on memories ok\n"); - upower_wait_resp(); - ret = upwr_poll_req_status(UPWR_SG_PWRMGMT, NULL, NULL, &ret_val, 1000); + printf("Turning on memories...\n"); + + upower_wait_resp(); + ret = upwr_poll_req_status(UPWR_SG_PWRMGMT, NULL, &err_code, &ret_val, 1000); if (ret != UPWR_REQ_OK) - printk("Faliure %d\n", ret); + printf("Turn on memories faliure %d, err_code %d, ret_val 0x%x\n", ret, err_code, ret_val); + else + printf("Turn on memories ok\n"); mdelay(1); @@ -184,13 +268,14 @@ int upower_init(void) if (ret) printf("Clear DDR retention fail %d\n", ret); else - printf("Clear DDR retention ok\n"); + printf("Clearing DDR retention...\n"); upower_wait_resp(); - - ret = upwr_poll_req_status(UPWR_SG_EXCEPT, NULL, NULL, &ret_val, 1000); + ret = upwr_poll_req_status(UPWR_SG_EXCEPT, NULL, &err_code, &ret_val, 1000); if (ret != UPWR_REQ_OK) - printk("Faliure %d\n", ret); + printf("Clear DDR retention fail %d, err_code %d, ret_val 0x%x\n", ret, err_code, ret_val); + else + printf("Clear DDR retention ok\n"); if (is_soc_rev(CHIP_REV_1_0)) { /* Enable AFBB for AP domain */ @@ -201,12 +286,15 @@ int upower_init(void) if (ret) printf("Enable AFBB for APD bias fail %d\n", ret); else - printf("Enable AFBB for APD bias ok\n"); + printf("Enabling AFBB for APD bias...\n"); upower_wait_resp(); - ret = upwr_poll_req_status(UPWR_SG_PWRMGMT, NULL, NULL, &ret_val, 1000); + ret = upwr_poll_req_status(UPWR_SG_PWRMGMT, NULL, &err_code, &ret_val, 1000); if (ret != UPWR_REQ_OK) - printk("Faliure %d\n", ret); + printf("Enable AFBB fail %d, err_code %d, ret_val 0x%x\n", ret, err_code, ret_val); + else + printf("Enable AFBB for APD bias ok\n"); + } return 0; diff --git a/arch/arm/mach-imx/imx9/Kconfig b/arch/arm/mach-imx/imx9/Kconfig index c709448411..f4fc1ac5ce 100644 --- a/arch/arm/mach-imx/imx9/Kconfig +++ b/arch/arm/mach-imx/imx9/Kconfig @@ -5,6 +5,11 @@ config AHAB_BOOT help This option enables the support for AHAB secure boot. +config IMX9_LOW_DRIVE_MODE + bool "Configure to i.MX9 low drive mode" + help + This option enables the settings for iMX9 low drive mode. + config IMX9 bool select ARCH_EARLY_INIT_R @@ -27,9 +32,15 @@ config TARGET_IMX93_11X11_EVK bool "imx93_11x11_evk" select IMX93 +config TARGET_IMX93_9X9_QSB + bool "imx93_9x9_qsb" + select IMX93 + select IMX9_LPDDR4X + endchoice source "board/freescale/imx93_evk/Kconfig" +source "board/freescale/imx93_qsb/Kconfig" endif diff --git a/arch/arm/mach-imx/imx9/clock.c b/arch/arm/mach-imx/imx9/clock.c index 7dc33941a9..909a770e1c 100644 --- a/arch/arm/mach-imx/imx9/clock.c +++ b/arch/arm/mach-imx/imx9/clock.c @@ -26,6 +26,7 @@ static struct anatop_reg *ana_regs = (struct anatop_reg *)ANATOP_BASE_ADDR; static struct imx_intpll_rate_table imx9_intpll_tbl[] = { INT_PLL_RATE(1800000000U, 1, 150, 2), /* 1.8Ghz */ INT_PLL_RATE(1700000000U, 1, 141, 2), /* 1.7Ghz */ + INT_PLL_RATE(1500000000U, 1, 125, 2), /* 1.5Ghz */ INT_PLL_RATE(1400000000U, 1, 175, 3), /* 1.4Ghz */ INT_PLL_RATE(1000000000U, 1, 166, 4), /* 1000Mhz */ INT_PLL_RATE(900000000U, 1, 150, 4), /* 900Mhz */ @@ -39,6 +40,7 @@ static struct imx_fracpll_rate_table imx9_fracpll_tbl[] = { FRAC_PLL_RATE(445333333U, 1, 167, 9, 0, 1), FRAC_PLL_RATE(466000000U, 1, 155, 8, 1, 3), /* 466Mhz */ FRAC_PLL_RATE(400000000U, 1, 200, 12, 0, 1), /* 400Mhz */ + FRAC_PLL_RATE(300000000U, 1, 150, 12, 0, 1), }; /* return in khz */ @@ -539,6 +541,25 @@ u32 get_arm_core_clk(void) return ccm_clk_root_get_rate(ARM_A55_CLK_ROOT); } +void set_arm_core_max_clk(void) +{ + u32 speed; + + /* Increase ARM clock to max rate according to speed grade */ + speed = get_cpu_speed_grade_hz(); + + ccm_shared_gpr_set(SHARED_GPR_A55_CLK, SHARED_GPR_A55_CLK_SEL_CCM); + configure_intpll(ARM_PLL_CLK, speed); + ccm_shared_gpr_set(SHARED_GPR_A55_CLK, SHARED_GPR_A55_CLK_SEL_PLL); +} + +void set_arm_core_low_drive_clk(void) +{ + ccm_shared_gpr_set(SHARED_GPR_A55_CLK, SHARED_GPR_A55_CLK_SEL_CCM); + configure_intpll(ARM_PLL_CLK, 900000000); + ccm_shared_gpr_set(SHARED_GPR_A55_CLK, SHARED_GPR_A55_CLK_SEL_PLL); +} + unsigned int mxc_get_clock(enum mxc_clock clk) { switch (clk) { @@ -611,21 +632,26 @@ void init_uart_clk(u32 index) void init_clk_usdhc(u32 index) { - /* 400 Mhz */ + u32 div; + if (IS_ENABLED(CONFIG_IMX9_LOW_DRIVE_MODE)) + div = 3; /* 266.67 Mhz */ + else + div = 2; /* 400 Mhz */ + switch (index) { case 0: ccm_lpcg_on(CCGR_USDHC1, 0); - ccm_clk_root_cfg(USDHC1_CLK_ROOT, SYS_PLL_PFD1, 2); + ccm_clk_root_cfg(USDHC1_CLK_ROOT, SYS_PLL_PFD1, div); ccm_lpcg_on(CCGR_USDHC1, 1); break; case 1: ccm_lpcg_on(CCGR_USDHC2, 0); - ccm_clk_root_cfg(USDHC2_CLK_ROOT, SYS_PLL_PFD1, 2); + ccm_clk_root_cfg(USDHC2_CLK_ROOT, SYS_PLL_PFD1, div); ccm_lpcg_on(CCGR_USDHC2, 1); break; case 2: ccm_lpcg_on(CCGR_USDHC3, 0); - ccm_clk_root_cfg(USDHC3_CLK_ROOT, SYS_PLL_PFD1, 2); + ccm_clk_root_cfg(USDHC3_CLK_ROOT, SYS_PLL_PFD1, div); ccm_lpcg_on(CCGR_USDHC3, 1); break; default: @@ -684,7 +710,36 @@ void dram_disable_bypass(void) } #endif -int clock_init(void) +void bus_clock_init_low_drive(void) +{ + /* Set A55 clk to 500M */ + ccm_clk_root_cfg(ARM_A55_CLK_ROOT, SYS_PLL_PFD0, 2); + /* Set A55 periphal to 200M */ + ccm_clk_root_cfg(ARM_A55_PERIPH_CLK_ROOT, SYS_PLL_PFD1, 4); + /* Set A55 mtr bus to 133M */ + ccm_clk_root_cfg(ARM_A55_MTR_BUS_CLK_ROOT, SYS_PLL_PFD1_DIV2, 3); + + /* Sentinel to 133M */ + ccm_clk_root_cfg(SENTINEL_CLK_ROOT, SYS_PLL_PFD1_DIV2, 3); + /* Bus_wakeup to 133M */ + ccm_clk_root_cfg(BUS_WAKEUP_CLK_ROOT, SYS_PLL_PFD1_DIV2, 3); + /* Bus_AON to 133M */ + ccm_clk_root_cfg(BUS_AON_CLK_ROOT, SYS_PLL_PFD1_DIV2, 3); + /* M33 to 133M */ + ccm_clk_root_cfg(M33_CLK_ROOT, SYS_PLL_PFD1_DIV2, 3); + /* WAKEUP_AXI to 200M */ + ccm_clk_root_cfg(WAKEUP_AXI_CLK_ROOT, SYS_PLL_PFD1, 4); + /* SWO TRACE to 133M */ + ccm_clk_root_cfg(SWO_TRACE_CLK_ROOT, SYS_PLL_PFD1_DIV2, 3); + /* M33 systetick to 24M */ + ccm_clk_root_cfg(M33_SYSTICK_CLK_ROOT, OSC_24M_CLK, 1); + /* NIC to 250M */ + ccm_clk_root_cfg(NIC_CLK_ROOT, SYS_PLL_PFD0, 4); + /* NIC_APB to 133M */ + ccm_clk_root_cfg(NIC_APB_CLK_ROOT, SYS_PLL_PFD1_DIV2, 3); +} + +void bus_clock_init(void) { /* Set A55 periphal to 333M */ ccm_clk_root_cfg(ARM_A55_PERIPH_CLK_ROOT, SYS_PLL_PFD0, 3); @@ -703,12 +758,22 @@ int clock_init(void) ccm_clk_root_cfg(WAKEUP_AXI_CLK_ROOT, SYS_PLL_PFD2, 2); /* SWO TRACE to 133M */ ccm_clk_root_cfg(SWO_TRACE_CLK_ROOT, SYS_PLL_PFD1_DIV2, 3); - /* M33 systetick to 133M */ - ccm_clk_root_cfg(M33_SYSTICK_CLK_ROOT, SYS_PLL_PFD1_DIV2, 3); + /* M33 systetick to 24M */ + ccm_clk_root_cfg(M33_SYSTICK_CLK_ROOT, OSC_24M_CLK, 1); /* NIC to 400M */ ccm_clk_root_cfg(NIC_CLK_ROOT, SYS_PLL_PFD1, 2); /* NIC_APB to 133M */ ccm_clk_root_cfg(NIC_APB_CLK_ROOT, SYS_PLL_PFD1_DIV2, 3); +} + +int clock_init(void) +{ + if (IS_ENABLED(CONFIG_IMX9_LOW_DRIVE_MODE)){ + bus_clock_init_low_drive(); + set_arm_core_low_drive_clk(); + } else { + bus_clock_init(); + } /* allow for non-secure access */ int i; diff --git a/arch/arm/mach-imx/imx9/soc.c b/arch/arm/mach-imx/imx9/soc.c index 66200dbe3c..02edced9aa 100644 --- a/arch/arm/mach-imx/imx9/soc.c +++ b/arch/arm/mach-imx/imx9/soc.c @@ -32,6 +32,10 @@ #include <asm/mach-imx/optee.h> #include <linux/delay.h> #include <fuse.h> +#include <imx_thermal.h> +#include <thermal.h> +#include <imx_sip.h> +#include <linux/arm-smccc.h> DECLARE_GLOBAL_DATA_PTR; @@ -153,6 +157,56 @@ int board_usb_gadget_port_auto(void) } #endif +u32 get_cpu_speed_grade_hz(void) +{ + u32 speed, max_speed; + u32 grade; + u32 val = readl((ulong)FSB_BASE_ADDR + 0x8000 + (19 << 2)); + val >>= 6; + val &= 0xf; + + speed = 2300000000 - val * 100000000; + + if (is_imx93()) { + grade = get_cpu_temp_grade(NULL, NULL); + if (grade == TEMP_INDUSTRIAL) + max_speed = 1500000000; + else + max_speed = 1700000000; + + /* In case the fuse of speed grade not programmed */ + if (speed > max_speed) + speed = max_speed; + } + + return speed; +} + +u32 get_cpu_temp_grade(int *minc, int *maxc) +{ + u32 val = readl((ulong)FSB_BASE_ADDR + 0x8000 + (19 << 2)); + + val >>= 4; + val &= 0x3; + + if (minc && maxc) { + if (val == TEMP_AUTOMOTIVE) { + *minc = -40; + *maxc = 125; + } else if (val == TEMP_INDUSTRIAL) { + *minc = -40; + *maxc = 105; + } else if (val == TEMP_EXTCOMMERCIAL) { + *minc = -20; + *maxc = 105; + } else { + *minc = 0; + *maxc = 95; + } + } + return val; +} + static void set_cpu_info(struct sentinel_get_info_data *info) { gd->arch.soc_rev = info->soc; @@ -160,10 +214,33 @@ static void set_cpu_info(struct sentinel_get_info_data *info) memcpy((void *)&gd->arch.uid, &info->uid, 4 * sizeof(u32)); } +static u32 get_cpu_variant_type(u32 type) +{ + /* word 19 */ + u32 val = readl((ulong)FSB_BASE_ADDR + 0x8000 + (19 << 2)); + u32 val2 = readl((ulong)FSB_BASE_ADDR + 0x8000 + (20 << 2)); + bool npu_disable = !!(val & BIT(13)); + bool core1_disable = !!(val & BIT(15)); + u32 pack_9x9_fused = BIT(4) | BIT(17) | BIT(19) | BIT(24); + + if ((val2 & pack_9x9_fused) == pack_9x9_fused) + type = MXC_CPU_IMX9322; + + if (npu_disable && core1_disable) + return type + 3; + else if (npu_disable) + return type + 2; + else if (core1_disable) + return type + 1; + + return type; +} + u32 get_cpu_rev(void) { u32 rev = (gd->arch.soc_rev >> 24) - 0xa0; - return (MXC_CPU_IMX93 << 12) | (CHIP_REV_1_0 + rev); + return (get_cpu_variant_type(MXC_CPU_IMX93) << 12) | + (CHIP_REV_1_0 + rev); } #define UNLOCK_WORD 0xD928C520 /* unlock word */ @@ -262,13 +339,161 @@ static struct mm_region imx93_mem_map[] = { struct mm_region *mem_map = imx93_mem_map; +static unsigned int imx9_find_dram_entry_in_mem_map(void) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(imx93_mem_map); i++) + if (imx93_mem_map[i].phys == CONFIG_SYS_SDRAM_BASE) + return i; + + hang(); /* Entry not found, this must never happen. */ +} + +void enable_caches(void) +{ + /* If OPTEE runs, remove OPTEE memory from MMU table to avoid speculative prefetch + * If OPTEE does not run, still update the MMU table according to dram banks structure + * to set correct dram size from board_phys_sdram_size + */ + int i = 0; + /* + * please make sure that entry initial value matches + * imx93_mem_map for DRAM1 + */ + int entry = imx9_find_dram_entry_in_mem_map(); + u64 attrs = imx93_mem_map[entry].attrs; + + while (i < CONFIG_NR_DRAM_BANKS && + entry < ARRAY_SIZE(imx93_mem_map)) { + if (gd->bd->bi_dram[i].start == 0) + break; + imx93_mem_map[entry].phys = gd->bd->bi_dram[i].start; + imx93_mem_map[entry].virt = gd->bd->bi_dram[i].start; + imx93_mem_map[entry].size = gd->bd->bi_dram[i].size; + imx93_mem_map[entry].attrs = attrs; + debug("Added memory mapping (%d): %llx %llx\n", entry, + imx93_mem_map[entry].phys, imx93_mem_map[entry].size); + i++; entry++; + } + + icache_enable(); + dcache_enable(); +} + +__weak int board_phys_sdram_size(phys_size_t *size) +{ + if (!size) + return -EINVAL; + + *size = PHYS_SDRAM_SIZE; + +#ifdef PHYS_SDRAM_2_SIZE + *size += PHYS_SDRAM_2_SIZE; +#endif + return 0; +} + int dram_init(void) { - gd->ram_size = PHYS_SDRAM_SIZE; + phys_size_t sdram_size; + int ret; + + ret = board_phys_sdram_size(&sdram_size); + if (ret) + return ret; + + /* rom_pointer[1] contains the size of TEE occupies */ + if (rom_pointer[1]) + gd->ram_size = sdram_size - rom_pointer[1]; + else + gd->ram_size = sdram_size; + + return 0; +} + +int dram_init_banksize(void) +{ + int bank = 0; + int ret; + phys_size_t sdram_size; + phys_size_t sdram_b1_size, sdram_b2_size; + + ret = board_phys_sdram_size(&sdram_size); + if (ret) + return ret; + + /* Bank 1 can't cross over 4GB space */ + if (sdram_size > 0x80000000) { + sdram_b1_size = 0x80000000; + sdram_b2_size = sdram_size - 0x80000000; + } else { + sdram_b1_size = sdram_size; + sdram_b2_size = 0; + } + + gd->bd->bi_dram[bank].start = PHYS_SDRAM; + if (rom_pointer[1]) { + phys_addr_t optee_start = (phys_addr_t)rom_pointer[0]; + phys_size_t optee_size = (size_t)rom_pointer[1]; + + gd->bd->bi_dram[bank].size = optee_start - gd->bd->bi_dram[bank].start; + if ((optee_start + optee_size) < (PHYS_SDRAM + sdram_b1_size)) { + if (++bank >= CONFIG_NR_DRAM_BANKS) { + puts("CONFIG_NR_DRAM_BANKS is not enough\n"); + return -1; + } + + gd->bd->bi_dram[bank].start = optee_start + optee_size; + gd->bd->bi_dram[bank].size = PHYS_SDRAM + + sdram_b1_size - gd->bd->bi_dram[bank].start; + } + } else { + gd->bd->bi_dram[bank].size = sdram_b1_size; + } + + if (sdram_b2_size) { + if (++bank >= CONFIG_NR_DRAM_BANKS) { + puts("CONFIG_NR_DRAM_BANKS is not enough for SDRAM_2\n"); + return -1; + } + gd->bd->bi_dram[bank].start = 0x100000000UL; + gd->bd->bi_dram[bank].size = sdram_b2_size; + } return 0; } +phys_size_t get_effective_memsize(void) +{ + int ret; + phys_size_t sdram_size; + phys_size_t sdram_b1_size; + ret = board_phys_sdram_size(&sdram_size); + if (!ret) { + /* Bank 1 can't cross over 4GB space */ + if (sdram_size > 0x80000000) { + sdram_b1_size = 0x80000000; + } else { + sdram_b1_size = sdram_size; + } + + if (rom_pointer[1]) { + /* We will relocate u-boot to Top of dram1. Tee position has two cases: + * 1. At the top of dram1, Then return the size removed optee size. + * 2. In the middle of dram1, return the size of dram1. + */ + if ((rom_pointer[0] + rom_pointer[1]) == (PHYS_SDRAM + sdram_b1_size)) + return ((phys_addr_t)rom_pointer[0] - PHYS_SDRAM); + } + + return sdram_b1_size; + } else { + return PHYS_SDRAM_SIZE; + } +} + + void imx_get_mac_from_fuse(int dev_id, unsigned char *mac) { u32 val[2] = {}; @@ -315,26 +540,370 @@ err: printf("%s: fuse read err: %d\n", __func__, ret); } +const char *get_imx_type(u32 imxtype) +{ + switch (imxtype) { + case MXC_CPU_IMX93: + return "93(52)";/* iMX93 Dual core with NPU */ + case MXC_CPU_IMX9351: + return "93(51)";/* iMX93 Single core with NPU */ + case MXC_CPU_IMX9332: + return "93(32)";/* iMX93 Dual core without NPU */ + case MXC_CPU_IMX9331: + return "93(31)";/* iMX93 Single core without NPU */ + case MXC_CPU_IMX9322: + return "93(22)";/* iMX93 9x9 Dual core */ + case MXC_CPU_IMX9321: + return "93(21)";/* iMX93 9x9 Single core */ + case MXC_CPU_IMX9312: + return "93(12)";/* iMX93 9x9 Dual core without NPU */ + case MXC_CPU_IMX9311: + return "93(11)";/* iMX93 9x9 Single core without NPU */ + default: + return "??"; + } +} + +#define SRC_SRSR_RESET_CAUSE_NUM 16 +const char *reset_cause[SRC_SRSR_RESET_CAUSE_NUM] = { + "POR ", + "JTAG ", + "IPP USER ", + "WDOG1 ", + "WDOG2 ", + "WDOG3 ", + "WDOG4 ", + "WDOG5 ", + "TEMPSENSE ", + "CSU ", + "JTAG_SW ", + "M33_REQ ", + "M33_LOCKUP " + "UNK ", + "UNK ", + "UNK ", +}; + +static void save_reset_cause(void) +{ + struct src_general_regs *src = (struct src_general_regs *)SRC_GLOBAL_RBASE; + u32 srsr = readl(&src->srsr); + writel(srsr, &src->srsr); /* clear srsr in sec mode */ + + /* Save value to GPR1 to pass to nonsecure */ + writel(srsr, &src->gpr[0]); +} + +static const char *get_reset_cause(u32 *srsr_ret) +{ + struct src_general_regs *src = (struct src_general_regs *)SRC_GLOBAL_RBASE; + u32 srsr; + u32 i; + + srsr = readl(&src->gpr[0]); + if (srsr_ret) + *srsr_ret = srsr; + + for (i = SRC_SRSR_RESET_CAUSE_NUM; i > 0; i--) { + if (srsr & (1 << (i - 1))) + return reset_cause[i - 1]; + } + + return "unknown reset"; +} + int print_cpuinfo(void) { - u32 cpurev; + u32 cpurev, max_freq; + int minc, maxc; + u32 ssrs_ret; cpurev = get_cpu_rev(); - printf("CPU: i.MX93 rev%d.%d at %d MHz\n", - (cpurev & 0x000F0) >> 4, (cpurev & 0x0000F) >> 0, - mxc_get_clock(MXC_ARM_CLK) / 1000000); + printf("CPU: i.MX%s rev%d.%d", + get_imx_type((cpurev & 0x1FF000) >> 12), + (cpurev & 0x000F0) >> 4, (cpurev & 0x0000F) >> 0); + + max_freq = get_cpu_speed_grade_hz(); + if (!max_freq || max_freq == mxc_get_clock(MXC_ARM_CLK)) { + printf(" at %dMHz\n", mxc_get_clock(MXC_ARM_CLK) / 1000000); + } else { + printf(" %d MHz (running at %d MHz)\n", max_freq / 1000000, + mxc_get_clock(MXC_ARM_CLK) / 1000000); + } + + puts("CPU: "); + switch (get_cpu_temp_grade(&minc, &maxc)) { + case TEMP_AUTOMOTIVE: + puts("Automotive temperature grade "); + break; + case TEMP_INDUSTRIAL: + puts("Industrial temperature grade "); + break; + case TEMP_EXTCOMMERCIAL: + puts("Extended Consumer temperature grade "); + break; + default: + puts("Consumer temperature grade "); + break; + } + printf("(%dC to %dC)", minc, maxc); + +#if defined(CONFIG_IMX_TMU) + struct udevice *udev; + int ret, temp; + + ret = uclass_get_device_by_name(UCLASS_THERMAL, "cpu-thermal", &udev); + if (!ret) { + ret = thermal_get_temp(udev, &temp); + + if (!ret) + printf(" at %dC", temp); + else + debug(" - invalid sensor data\n"); + } else { + debug(" - invalid sensor device\n"); + } +#endif + puts("\n"); + + printf("Reset cause: %s", get_reset_cause(&ssrs_ret)); + printf("(0x%x)\n", ssrs_ret); return 0; } +void build_info(void) +{ + u32 fw_version, sha1, res, status; + int ret; + + printf("\nBuildInfo:\n"); + + ret = ahab_get_fw_status(&status, &res); + if (ret) { + printf(" - ELE firmware status failed %d, 0x%x\n", ret, res); + } else if ((status & 0xff) == 1) { + ret = ahab_get_fw_version(&fw_version, &sha1, &res); + if (ret) { + printf(" - ELE firmware version failed %d, 0x%x\n", ret, res); + } else { + printf(" - ELE firmware version %u.%u.%u-%x", + (fw_version & (0x00ff0000)) >> 16, + (fw_version & (0x0000ff00)) >> 8, + (fw_version & (0x000000ff)), sha1); + ((fw_version & (0x80000000)) >> 31) == 1 ? puts("-dirty\n") : puts("\n"); + } + } else { + printf(" - ELE firmware not included\n"); + } + puts("\n"); +} + int arch_misc_init(void) { + build_info(); + return 0; +} + +static int delete_fdt_nodes(void *blob, const char *const nodes_path[], int size_array) +{ + int i = 0; + int rc; + int nodeoff; + + for (i = 0; i < size_array; i++) { + nodeoff = fdt_path_offset(blob, nodes_path[i]); + if (nodeoff < 0) + continue; /* Not found, skip it */ + + debug("Found %s node\n", nodes_path[i]); + + rc = fdt_del_node(blob, nodeoff); + if (rc < 0) { + printf("Unable to delete node %s, err=%s\n", + nodes_path[i], fdt_strerror(rc)); + } else { + printf("Delete node %s\n", nodes_path[i]); + } + } + + return 0; +} + +static int disable_npu_nodes(void *blob) +{ + static const char * const nodes_path_npu[] = { + "/ethosu", + "/reserved-memory/ethosu_region@C0000000" + }; + + return delete_fdt_nodes(blob, nodes_path_npu, ARRAY_SIZE(nodes_path_npu)); +} + +static void disable_thermal_cpu_nodes(void *blob, u32 disabled_cores) +{ + static const char * const thermal_path[] = { + "/thermal-zones/cpu-thermal/cooling-maps/map0" + }; + + int nodeoff, cnt, i, ret, j; + u32 cooling_dev[6]; + + for (i = 0; i < ARRAY_SIZE(thermal_path); i++) { + nodeoff = fdt_path_offset(blob, thermal_path[i]); + if (nodeoff < 0) + continue; /* Not found, skip it */ + + cnt = fdtdec_get_int_array_count(blob, nodeoff, "cooling-device", cooling_dev, 6); + if (cnt < 0) + continue; + + if (cnt != 6) + printf("Warning: %s, cooling-device count %d\n", thermal_path[i], cnt); + + for (j = 0; j < cnt; j++) + cooling_dev[j] = cpu_to_fdt32(cooling_dev[j]); + + ret = fdt_setprop(blob, nodeoff, "cooling-device", &cooling_dev, + sizeof(u32) * (6 - disabled_cores * 3)); + if (ret < 0) { + printf("Warning: %s, cooling-device setprop failed %d\n", + thermal_path[i], ret); + continue; + } + + printf("Update node %s, cooling-device prop\n", thermal_path[i]); + } +} + +static int disable_cpu_nodes(void *blob, u32 disabled_cores) +{ + u32 i = 0; + int rc; + int nodeoff; + char nodes_path[32]; + + for (i = 1; i <= disabled_cores; i++) { + + sprintf(nodes_path, "/cpus/cpu@%u00", i); + + nodeoff = fdt_path_offset(blob, nodes_path); + if (nodeoff < 0) + continue; /* Not found, skip it */ + + debug("Found %s node\n", nodes_path); + + rc = fdt_del_node(blob, nodeoff); + if (rc < 0) { + printf("Unable to delete node %s, err=%s\n", + nodes_path, fdt_strerror(rc)); + } else { + printf("Delete node %s\n", nodes_path); + } + } + + disable_thermal_cpu_nodes(blob, disabled_cores); + return 0; } +struct low_drive_freq_entry { + const char *node_path; + u32 clk; + u32 new_rate; +}; + +static int low_drive_fdt_fix_clock(void *fdt, int node_off, u32 clk_index, u32 new_rate) +{ +#define MAX_ASSIGNED_CLKS 8 + int cnt, j; + u32 assignedclks[MAX_ASSIGNED_CLKS]; /* max 8 clocks*/ + + cnt = fdtdec_get_int_array_count(fdt, node_off, "assigned-clock-rates", + assignedclks, MAX_ASSIGNED_CLKS); + if (cnt > 0) { + if (cnt <= clk_index) + return -ENOENT; + + if (assignedclks[clk_index] <= new_rate) + return 0; + + assignedclks[clk_index] = new_rate; + for (j = 0; j < cnt; j++) + assignedclks[j] = cpu_to_fdt32(assignedclks[j]); + + return fdt_setprop(fdt, node_off, "assigned-clock-rates", &assignedclks, cnt * sizeof(u32)); + } + + return -ENOENT; +} + +static int low_drive_freq_update(void *blob) +{ + int nodeoff, ret; + int i; + + /* Update kernel dtb clocks for low drive mode */ + struct low_drive_freq_entry table[] = { + {"/soc@0/lcd-controller@4ae30000", 2, 200000000}, + {"/soc@0/bus@42800000/camera/isi@4ae40000", 0, 200000000}, + {"/soc@0/bus@42800000/mmc@42850000", 0, 266666667}, + {"/soc@0/bus@42800000/mmc@42860000", 0, 266666667}, + {"/soc@0/bus@42800000/mmc@428b0000", 0, 266666667}, + }; + + for (i = 0; i < ARRAY_SIZE(table); i++) { + nodeoff = fdt_path_offset(blob, table[i].node_path); + if (nodeoff >= 0) { + ret = low_drive_fdt_fix_clock(blob, nodeoff, table[i].clk, table[i].new_rate); + if (!ret) + printf("%s freq updated\n", table[i].node_path); + } + } + + return 0; +} + +#ifdef CONFIG_OF_BOARD_FIXUP +#ifndef CONFIG_SPL_BUILD +int board_fix_fdt(void *fdt) +{ + /* Update u-boot dtb clocks for low drive mode */ + if (IS_ENABLED(CONFIG_IMX9_LOW_DRIVE_MODE)){ + int nodeoff; + int i; + + struct low_drive_freq_entry table[] = { + {"/soc@0/lcd-controller@4ae30000", 0, 200000000}, + {"/soc@0/bus@42800000/mmc@42850000", 0, 266666667}, + {"/soc@0/bus@42800000/mmc@42860000", 0, 266666667}, + {"/soc@0/bus@42800000/mmc@428b0000", 0, 266666667}, + }; + + for (i = 0; i < ARRAY_SIZE(table); i++) { + nodeoff = fdt_path_offset(fdt, table[i].node_path); + if (nodeoff >= 0) + low_drive_fdt_fix_clock(fdt, nodeoff, table[i].clk, table[i].new_rate); + } + } + + return 0; +} +#endif +#endif + int ft_system_setup(void *blob, struct bd_info *bd) { + if (is_imx9351() || is_imx9331() || is_imx9321() || is_imx9311()) + disable_cpu_nodes(blob, 1); + + if (is_imx9332() || is_imx9331() || is_imx9312() || is_imx9311()) + disable_npu_nodes(blob); + + if (IS_ENABLED(CONFIG_IMX9_LOW_DRIVE_MODE)) + low_drive_freq_update(blob); + return ft_add_optee_node(blob, bd); } @@ -358,6 +927,9 @@ int arch_cpu_init(void) clock_init(); trdc_early_init(); + + /* Save SRC SRSR to GPR1 and clear it */ + save_reset_cause(); } return 0; diff --git a/arch/arm/mach-imx/mx6/module_fuse.c b/arch/arm/mach-imx/mx6/module_fuse.c index c24d8279ed..a171e7b54d 100644 --- a/arch/arm/mach-imx/mx6/module_fuse.c +++ b/arch/arm/mach-imx/mx6/module_fuse.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0+ /* - * Copyright 2019 NXP + * Copyright 2019, 2022 NXP */ #include <common.h> @@ -10,6 +10,11 @@ #include <asm/arch/imx-regs.h> #include <asm/mach-imx/module_fuse.h> #include <linux/errno.h> +#include <command.h> +#include <hexdump.h> +#include <dm.h> +#include <malloc.h> +#include <rng.h> static struct fuse_entry_desc mx6_fuse_descs[] = { #if defined(CONFIG_MX6ULL) @@ -300,6 +305,48 @@ add_status: } } + if (IS_ENABLED(CONFIG_FSL_DCP_RNG)) { + /*Random number generation through RNG driver*/ + struct udevice *dev; + void *buf; + char keys[2][16] = {"otp_crypto_key", "otp_unique_key"}; + int ret = 0; + int nodeoff = fdt_node_offset_by_compatible(blob, -1, "fsl,imx28-dcp"); + + if (nodeoff < 0) { + printf("node to update the SoC serial number is not found.\n"); + return nodeoff; + } + rc = uclass_get_device(UCLASS_RNG, 0, &dev); + if (rc || !dev) { + printf("No RNG device\n"); + return rc; + } + + buf = malloc(16); + if (!buf) { + printf("Out of memory\n"); + return -ENOMEM; + } + + for (int i = 0; i < 2; i++) { + ret = dm_rng_read(dev, buf, 16); + if (ret) { + printf("Reading RNG failed\n"); + goto err; + } + + ret = fdt_setprop(blob, nodeoff, keys[i], buf, 16); + if (ret < 0) { + printf("WARNING: could not set %s key handle %s.\n", keys[i], fdt_strerror(ret)); + goto err; + } + } +err: + free(buf); + return ret; + } + return 0; } #endif |