From af37c0ffb45543d76d9c46a379b983d884192462 Mon Sep 17 00:00:00 2001 From: coolsnowwolf Date: Mon, 30 Sep 2024 21:16:06 +0800 Subject: [PATCH] atf-rockchip: update rk3568 support --- .../arm-trusted-firmware-rockchip/Makefile | 6 +- .../001-feat-rk3568-support-SCMI-for.patch | 1477 +++++++++++++++++ ...1-feat-rk3588-enable-crypto-function.patch | 140 -- 3 files changed, 1480 insertions(+), 143 deletions(-) create mode 100644 package/boot/arm-trusted-firmware-rockchip/patches/001-feat-rk3568-support-SCMI-for.patch delete mode 100644 package/boot/arm-trusted-firmware-rockchip/patches/001-feat-rk3588-enable-crypto-function.patch diff --git a/package/boot/arm-trusted-firmware-rockchip/Makefile b/package/boot/arm-trusted-firmware-rockchip/Makefile index 4c850b3e4..40ee3e08a 100644 --- a/package/boot/arm-trusted-firmware-rockchip/Makefile +++ b/package/boot/arm-trusted-firmware-rockchip/Makefile @@ -10,9 +10,9 @@ PKG_RELEASE:=1 PKG_SOURCE_PROTO:=git PKG_SOURCE_URL=https://github.com/ARM-software/arm-trusted-firmware -PKG_SOURCE_DATE:=2024-09-09 -PKG_SOURCE_VERSION:=0631d68d85881d4b8ffa571f49eb8b767c005f6a -PKG_MIRROR_HASH:=6e8a83c6ee64faab46e1531948180199fa70194bb2ffec4d4a521c2b2d136cf3 +PKG_SOURCE_DATE:=2024-09-21 +PKG_SOURCE_VERSION:=2975ad055bd6e1ea3fc4179e8b785266785f0398 +PKG_MIRROR_HASH:=6cf6e03b43b3d791153dc93f067c8e078f438923cd0781be047a722342c24fe8 PKG_MAINTAINER:=Tobias Maedel diff --git a/package/boot/arm-trusted-firmware-rockchip/patches/001-feat-rk3568-support-SCMI-for.patch b/package/boot/arm-trusted-firmware-rockchip/patches/001-feat-rk3568-support-SCMI-for.patch new file mode 100644 index 000000000..c1867e451 --- /dev/null +++ b/package/boot/arm-trusted-firmware-rockchip/patches/001-feat-rk3568-support-SCMI-for.patch @@ -0,0 +1,1477 @@ +From da1c5f6534eb6e125c25d517435022140c5696a7 Mon Sep 17 00:00:00 2001 +From: Shengfei Xu +Date: Sun, 29 Sep 2024 09:40:03 +0800 +Subject: [PATCH] feat(rk3568): support SCMI for clock/reset domain + +rockchip scmi clock controls clocks which only available in secure mode. + +Change-Id: Ide3a8dac72512ce79331592c3cbb86577de7df70 +Signed-off-by: Shengfei Xu +--- + plat/rockchip/rk3568/drivers/otp/otp.c | 368 +++++++++ + plat/rockchip/rk3568/drivers/otp/otp.h | 77 ++ + plat/rockchip/rk3568/drivers/pmu/pmu.c | 3 + + .../rockchip/rk3568/drivers/scmi/rk3568_clk.c | 753 ++++++++++++++++++ + .../rockchip/rk3568/drivers/scmi/rk3568_clk.h | 70 ++ + plat/rockchip/rk3568/drivers/soc/soc.c | 6 + + plat/rockchip/rk3568/plat_sip_calls.c | 13 +- + plat/rockchip/rk3568/platform.mk | 14 + + plat/rockchip/rk3568/rk3568_def.h | 18 +- + 9 files changed, 1317 insertions(+), 5 deletions(-) + create mode 100644 plat/rockchip/rk3568/drivers/otp/otp.c + create mode 100644 plat/rockchip/rk3568/drivers/otp/otp.h + create mode 100644 plat/rockchip/rk3568/drivers/scmi/rk3568_clk.c + create mode 100644 plat/rockchip/rk3568/drivers/scmi/rk3568_clk.h + +--- /dev/null ++++ b/plat/rockchip/rk3568/drivers/otp/otp.c +@@ -0,0 +1,368 @@ ++/* ++ * Copyright (c) 2024, Rockchip Electronics Co., Ltd. All rights reserved.. ++ * ++ * SPDX-License-Identifier: BSD-3-Clause ++ */ ++ ++#include ++#include ++#include ++#include ++ ++#include ++#include ++#include ++#include ++ ++/* default SBPI_READ mode */ ++#define OTP_USER_READ 0 ++#define USEC_PER_SEC 1000000 ++ ++enum clk_type { ++ PCLK_PHY = 0, ++ PCLK_NS, ++ PCLK_S, ++ CLK_NS_USER, ++ CLK_NS_SBPI, ++ CLK_S_USER, ++ CLK_S_SBPI ++}; ++ ++static uint8_t otp_ns_ecc_flag[OTP_NS_BYTE_SIZE / 2]; ++ ++static uint32_t enable_otp_clk(int clk) ++{ ++ uint32_t reg = 0; ++ ++ switch (clk) { ++ case CLK_NS_USER: ++ reg = mmio_read_32(CRU_BASE + CRU_CLKGATES_CON(26)); ++ if (reg & CLK_NS_OTP_USER_EN) ++ mmio_write_32(CRU_BASE + CRU_CLKGATES_CON(26), ++ CLK_NS_OTP_USER_EN << WRITE_MASK); ++ ++ break; ++ case CLK_NS_SBPI: ++ reg = mmio_read_32(CRU_BASE + CRU_CLKGATES_CON(26)); ++ if (reg & CLK_NS_OTP_SBPI_EN) ++ mmio_write_32(CRU_BASE + CRU_CLKGATES_CON(26), ++ CLK_NS_OTP_SBPI_EN << WRITE_MASK); ++ ++ break; ++ case PCLK_NS: ++ reg = mmio_read_32(CRU_BASE + CRU_CLKGATES_CON(26)); ++ if (reg & PCLK_NS_OTP_EN) ++ mmio_write_32(CRU_BASE + CRU_CLKGATES_CON(26), ++ PCLK_NS_OTP_EN << WRITE_MASK); ++ ++ break; ++ case PCLK_PHY: ++ reg = mmio_read_32(CRU_BASE + CRU_CLKGATES_CON(34)); ++ if (reg & PCLK_PHY_OTP_EN) ++ mmio_write_32(CRU_BASE + CRU_CLKGATES_CON(34), ++ PCLK_PHY_OTP_EN << WRITE_MASK); ++ ++ break; ++ case CLK_S_USER: ++ reg = mmio_read_32(SCRU_BASE + SCRU_GATE_CON01); ++ if (reg & CLK_S_OTP_USER_EN) ++ mmio_write_32(SCRU_BASE + SCRU_GATE_CON01, ++ CLK_S_OTP_USER_EN << WRITE_MASK); ++ ++ break; ++ case CLK_S_SBPI: ++ reg = mmio_read_32(SCRU_BASE + SCRU_GATE_CON01); ++ if (reg & CLK_S_OTP_SBPI_EN) ++ mmio_write_32(SCRU_BASE + SCRU_GATE_CON01, ++ CLK_S_OTP_SBPI_EN << WRITE_MASK); ++ ++ break; ++ case PCLK_S: ++ reg = mmio_read_32(SCRU_BASE + SCRU_GATE_CON01); ++ if (reg & PCLK_S_OTP_EN) ++ mmio_write_32(SCRU_BASE + SCRU_GATE_CON01, ++ PCLK_S_OTP_EN << WRITE_MASK); ++ ++ break; ++ default: ++ break; ++ } ++ ++ return reg; ++} ++ ++static void restore_otp_clk(int clk, uint32_t reg) ++{ ++ switch (clk) { ++ case CLK_NS_USER: ++ if (reg & CLK_NS_OTP_USER_EN) ++ mmio_write_32(CRU_BASE + CRU_CLKGATES_CON(26), ++ (CLK_NS_OTP_USER_EN << WRITE_MASK) | reg); ++ break; ++ case CLK_NS_SBPI: ++ if (reg & CLK_NS_OTP_SBPI_EN) ++ mmio_write_32(CRU_BASE + CRU_CLKGATES_CON(26), ++ (CLK_NS_OTP_SBPI_EN << WRITE_MASK) | reg); ++ break; ++ case PCLK_NS: ++ if (reg & PCLK_NS_OTP_EN) ++ mmio_write_32(CRU_BASE + CRU_CLKGATES_CON(26), ++ (PCLK_NS_OTP_EN << WRITE_MASK) | reg); ++ break; ++ case PCLK_PHY: ++ if (reg & PCLK_PHY_OTP_EN) ++ mmio_write_32(CRU_BASE + CRU_CLKGATES_CON(34), ++ (PCLK_PHY_OTP_EN << WRITE_MASK) | reg); ++ break; ++ case CLK_S_USER: ++ if (reg & CLK_S_OTP_USER_EN) ++ mmio_write_32(SCRU_BASE + SCRU_GATE_CON01, ++ (CLK_S_OTP_USER_EN << WRITE_MASK) | reg); ++ break; ++ case CLK_S_SBPI: ++ if (reg & CLK_S_OTP_SBPI_EN) ++ mmio_write_32(SCRU_BASE + SCRU_GATE_CON01, ++ (CLK_S_OTP_SBPI_EN << WRITE_MASK) | reg); ++ break; ++ case PCLK_S: ++ if (reg & PCLK_S_OTP_EN) ++ mmio_write_32(SCRU_BASE + SCRU_GATE_CON01, ++ (PCLK_S_OTP_EN << WRITE_MASK) | reg); ++ break; ++ default: ++ return; ++ } ++} ++ ++static int check_sbpi_done_int(uint32_t otp_base) ++{ ++ /* wait max 10ms */ ++ uint32_t timeout = 10000; ++ ++ while (1) { ++ /* check sbpi DONE INT */ ++ if (((mmio_read_32(otp_base + REG_OTPC_INT_STATUS) >> 1) & 0x01) == 0x01) { ++ mmio_write_32(otp_base + REG_OTPC_INT_STATUS, ++ 0xffff0002); /* clear sbpi DONE INT */ ++ break; ++ } ++ ++ if (timeout == 0) { ++ WARN("---OTP---Check sbpi int done TIMEOUT"); ++ return -1; ++ } ++ ++ timeout--; ++ udelay(1); ++ } ++ ++ return 0; ++} ++ ++static uint32_t otp_select(uint32_t addr) ++{ ++ uint32_t otp_base = 0; ++ ++ if (addr < 0x1c0) { /* 0-447 otp0 S */ ++ otp_base = OTP_S_BASE; ++ mmio_write_32(SGRF_BASE + SGRF_SOC_CON2, ++ (SGRF_CON_OTP_SECURE << WRITE_MASK) | SGRF_CON_OTP_SECURE); /* secure */ ++ } else if (addr >= 0x1c0 && addr < 0x200) { /* 448-511 otp0 NS */ ++ otp_base = OTP_NS_BASE; ++ mmio_write_32(SGRF_BASE + SGRF_SOC_CON2, ++ SGRF_CON_OTP_SECURE << WRITE_MASK); /* non secure */ ++ } ++ ++ return otp_base; ++} ++ ++static int rk_otp_ecc_enable(uint32_t otp_base, bool enable) ++{ ++ mmio_write_32(otp_base + REG_OTPC_SBPI_CTRL, ++ BITS_WITH_WMASK(0x2, 0xffu, SBPI_DEV_ID_SHIFT)); /* device id */ ++ ++ mmio_write_32(otp_base + REG_OTPC_SBPI_CMD_VALID_PRE, ++ 0xffff0001); /* sbpi valid number */ ++ mmio_write_32(otp_base + REG_OTPC_SBPI_CMD_BASE + 0x00, 0xfa); /* sbpi cmd */ ++ ++ if (enable) ++ mmio_write_32(otp_base + REG_OTPC_SBPI_CMD_BASE + 0x04, ++ 0x00); /* sbpi cmd enable ecc*/ ++ else ++ mmio_write_32(otp_base + REG_OTPC_SBPI_CMD_BASE + 0x04, ++ 0x09); /* sbpi cmd disable ecc*/ ++ ++ mmio_write_32(otp_base + REG_OTPC_SBPI_CTRL, ++ (SBPI_ENABLE << WRITE_MASK) | SBPI_ENABLE); /* sbpi enable */ ++ ++ if (check_sbpi_done_int(otp_base)) ++ return -1; ++ ++ return 0; ++} ++ ++static int rk_otp_sbpi_read(uint32_t addr, uint16_t *read_data, bool is_need_ecc) ++{ ++ uint32_t otp_base = 0; ++ uint32_t otp_qp; ++ ++ otp_base = otp_select(addr); ++ ++ mmio_write_32(CRU_BASE + CRU_SOFTRSTS_CON(28), ++ (OTP_PHY_SRSTN << WRITE_MASK) | OTP_PHY_SRSTN); /* reset otp phy */ ++ udelay(2); ++ mmio_write_32(CRU_BASE + CRU_SOFTRSTS_CON(28), ++ OTP_PHY_SRSTN << WRITE_MASK); ++ udelay(1); ++ ++ mmio_write_32(SGRF_BASE + SGRF_SOC_CON2, ++ (SGRF_CON_OTP_CKE << WRITE_MASK) | SGRF_CON_OTP_CKE); /* CKE = 1 */ ++ udelay(2); ++ mmio_write_32(otp_base + REG_OTPC_USER_CTRL, USER_DCTRL << WRITE_MASK); ++ udelay(2); ++ ++ rk_otp_ecc_enable(otp_base, is_need_ecc); ++ ++ mmio_write_32(otp_base + REG_OTPC_SBPI_CTRL, ++ (SBPI_CS_AUTO << WRITE_MASK) | SBPI_CS_AUTO); /* cs auto */ ++ mmio_write_32(otp_base + REG_OTPC_SBPI_CS_VALID_PRE, ++ 0xffff0000); /* cs valid number */ ++ ++ mmio_write_32(otp_base + REG_OTPC_SBPI_CTRL, ++ BITS_WITH_WMASK(0x2, 0xffu, SBPI_DEV_ID_SHIFT)); /* device id */ ++ ++ mmio_write_32(otp_base + REG_OTPC_SBPI_CMD_VALID_PRE, ++ 0xffff0002); /* sbpi valid number */ ++ mmio_write_32(otp_base + REG_OTPC_SBPI_CMD_BASE + 0x00, ++ 0xfc); /* sbpi cmd */ ++ mmio_write_32(otp_base + REG_OTPC_SBPI_CMD_BASE + 0x04, ++ addr & 0xff); /* sbpi cmd 3c addr */ ++ mmio_write_32(otp_base + REG_OTPC_SBPI_CMD_BASE + 0x08, ++ (addr >> 8) & 0xff); /* sbpi cmd 3d addr */ ++ mmio_write_32(otp_base + REG_OTPC_SBPI_CTRL, ++ (SBPI_ENABLE << WRITE_MASK) | SBPI_ENABLE); /* sbpi enable */ ++ ++ if (check_sbpi_done_int(otp_base)) ++ return -1; ++ ++ mmio_write_32(otp_base + REG_OTPC_SBPI_CMD_VALID_PRE, 0xffff0007); /* sbpi valid number */ ++ mmio_write_32(otp_base + REG_OTPC_SBPI_CMD_BASE + 0x00, 0x00); /* sbpi cmd */ ++ mmio_write_32(otp_base + REG_OTPC_SBPI_CMD_BASE + 0x04, 0x00); /* sbpi cmd */ ++ mmio_write_32(otp_base + REG_OTPC_SBPI_CMD_BASE + 0x08, 0x40); /* sbpi cmd */ ++ mmio_write_32(otp_base + REG_OTPC_SBPI_CMD_BASE + 0x0C, 0x40); /* sbpi cmd */ ++ mmio_write_32(otp_base + REG_OTPC_SBPI_CMD_BASE + 0x10, 0x00); /* sbpi cmd */ ++ mmio_write_32(otp_base + REG_OTPC_SBPI_CMD_BASE + 0x14, 0x02); /* sbpi cmd */ ++ mmio_write_32(otp_base + REG_OTPC_SBPI_CMD_BASE + 0x18, 0x80); /* sbpi cmd */ ++ mmio_write_32(otp_base + REG_OTPC_SBPI_CMD_BASE + 0x1c, 0x81); /* sbpi cmd */ ++ mmio_write_32(otp_base + REG_OTPC_SBPI_CTRL, ++ (SBPI_ENABLE << WRITE_MASK) | SBPI_ENABLE); /* sbpi enable */ ++ ++ if (check_sbpi_done_int(otp_base)) ++ return -1; ++ ++ if (is_need_ecc) { ++ otp_qp = mmio_read_32(otp_base + REG_OTPC_USER_QP); ++ VERBOSE("otp_addr:0x%x, otp_qp:0x%x\n", addr, otp_qp); ++ if (((otp_qp & 0xc0) == 0xc0) || (otp_qp & 0x20)) { ++ otp_ns_ecc_flag[addr - OTP_S_BYTE_SIZE / 2] = 1; ++ ERROR("ecc otp_addr:0x%x, otp_qp failed 0x%x\n", addr, otp_qp); ++ } ++ } ++ ++ *read_data = ++ (uint16_t)mmio_read_32(otp_base + REG_OTPC_SBPI_READ_DATA_BASE + 0x20); ++ *read_data += ++ (uint16_t)(mmio_read_32(otp_base + REG_OTPC_SBPI_READ_DATA_BASE + 0x24) << 8); ++ ++ mmio_write_32(otp_base + REG_OTPC_SBPI_CMD_VALID_PRE, 0xffff0001); ++ mmio_write_32(otp_base + REG_OTPC_SBPI_CMD_BASE + 0x00, 0xa0); ++ mmio_write_32(otp_base + REG_OTPC_SBPI_CMD_BASE + 0x04, 0x0); ++ mmio_write_32(otp_base + REG_OTPC_SBPI_CTRL, ++ (SBPI_ENABLE << WRITE_MASK) | SBPI_ENABLE); ++ ++ if (check_sbpi_done_int(otp_base)) ++ return -1; ++ ++ mmio_write_32(otp_base + REG_OTPC_INT_STATUS, 0xffff0003); /* clear sbpi INT */ ++ ++ mmio_write_32(SGRF_BASE + SGRF_SOC_CON2, ++ SGRF_CON_OTP_SECURE << WRITE_MASK); /* non secure */ ++ ++ return 0; ++} ++ ++int rk_otp_read(uint32_t byte_addr, uint32_t byte_len, uint16_t *buf, bool is_need_ecc) ++{ ++ int ret = 0; ++ uint32_t i = 0; ++ uint32_t clk_ns_user = 0, clk_ns_sbpi = 0, pclk_ns = 0, pclk_phy = 0; ++ uint32_t clk_s_user = 0, clk_s_sbpi = 0, pclk_s = 0; ++ uint32_t addr, length; ++ ++ /* ++ * RK3568 platform OTP R&W by halfword ++ * Address and Length must be an integral multiple of 2 ++ */ ++ if ((byte_addr % 2) != 0 || (byte_len % 2) != 0) { ++ ERROR("byte addr and byte length must be even numbers!"); ++ return -1; ++ } ++ ++ addr = byte_addr / 2; ++ length = byte_len / 2; ++ ++ if (addr >= OTP_MAX_SIZE || length <= 0 || length > OTP_MAX_SIZE || !buf) ++ return -1; ++ ++ if ((addr + length) > OTP_MAX_SIZE) ++ return -1; ++ ++ if (addr < OTP_S_SIZE && (addr + length) > OTP_S_SIZE) { ++ ERROR("Both read secure and non secure otp are not supported!"); ++ return -1; ++ } ++ ++ /* enable otp clk if clk is disabled */ ++ pclk_phy = enable_otp_clk(PCLK_PHY); ++ if (addr < 0x1C0) { /* 0-447 otp0 S */ ++ pclk_s = enable_otp_clk(PCLK_S); ++ clk_s_sbpi = enable_otp_clk(CLK_S_SBPI); ++ clk_s_user = enable_otp_clk(CLK_S_USER); ++ } else if (addr >= 0x1C0 && addr < 0x200) { /* 448-511 otp0 NS */ ++ pclk_ns = enable_otp_clk(PCLK_NS); ++ clk_ns_sbpi = enable_otp_clk(CLK_NS_SBPI); ++ clk_ns_user = enable_otp_clk(CLK_NS_USER); ++ } ++ ++ for (i = 0; i < length; i++) { ++ ++ ret = rk_otp_sbpi_read(addr + i, buf + i, is_need_ecc); ++ if (ret) { ++ ERROR("---OTP---sbpi read otp failed! addr: 0x%x", addr + i); ++ goto out; ++ } ++ } ++ ++out: ++ /* restore otp clk state */ ++ restore_otp_clk(PCLK_PHY, pclk_phy); ++ if (addr < 0x1C0) { /* 0-447 otp0 S */ ++ restore_otp_clk(PCLK_S, pclk_s); ++ restore_otp_clk(CLK_S_SBPI, clk_s_sbpi); ++ restore_otp_clk(CLK_S_USER, clk_s_user); ++ } else if (addr >= 0x1C0 && addr < 0x200) { /* 448-511 otp0 NS */ ++ restore_otp_clk(PCLK_NS, pclk_ns); ++ restore_otp_clk(CLK_NS_SBPI, clk_ns_sbpi); ++ restore_otp_clk(CLK_NS_USER, clk_ns_user); ++ } ++ ++ return ret; ++} ++ ++int rk_otp_ns_ecc_flag(uint32_t addr) ++{ ++ if (addr >= OTP_NS_BYTE_SIZE) ++ return 0; ++ ++ return otp_ns_ecc_flag[addr / 2]; ++} +--- /dev/null ++++ b/plat/rockchip/rk3568/drivers/otp/otp.h +@@ -0,0 +1,77 @@ ++/* ++ * Copyright (c) 2024, Rockchip Electronics Co., Ltd. All rights reserved. ++ * ++ * SPDX-License-Identifier: BSD-3-Clause ++ */ ++ ++#ifndef RK_OTP_H ++#define RK_OTP_H ++ ++#define WRITE_MASK (16) ++ ++#define OTP_MAX_SIZE 512 ++#define OTP_MAX_BYTE_SIZE (OTP_MAX_SIZE * 2) ++#define OTP_S_SIZE 448 ++#define OTP_S_BYTE_SIZE (OTP_S_SIZE * 2) ++#define OTP_NS_SIZE 64 ++#define OTP_NS_BYTE_SIZE (OTP_NS_SIZE * 2) ++#define OTP_PROG_MASK 0 ++#define OTP_PROG_MASK_NUM 32 ++#define OTP_READ_MASK 0x0100 ++#define OTP_READ_MASK_NUM 32 ++#define IS_READ_MASK 0 ++#define IS_WRITE_MASK 1 ++#define IS_DISBALE_MASK 0 ++#define IS_ENABLE_MASK 1 ++#define OTP_MASK_BYPASS 0x200 ++ ++/* CRU controller register */ ++#define CLK_NS_OTP_USER_EN (1 << 11) ++#define CLK_NS_OTP_SBPI_EN (1 << 10) ++#define PCLK_NS_OTP_EN (1 << 9) ++#define PCLK_PHY_OTP_EN (1 << 13) ++#define OTP_PHY_SRSTN (1u << 15) ++ ++/* SCRU controller register */ ++#define CLK_S_OTP_USER_EN (1 << 7) ++#define CLK_S_OTP_SBPI_EN (1 << 6) ++#define PCLK_S_OTP_EN (1 << 5) ++ ++/* SGRF controller register */ ++#define SGRF_CON_OTP_CKE (1 << 2) ++#define SGRF_CON_OTP_SECURE (1 << 1) ++ ++/* OTP controller register */ ++#define REG_OTPC_SBPI_CTRL (0x0020) ++#define SBPI_DEV_ID_SHIFT (8) ++#define SBPI_DEV_ID_MASK (0xFF) ++#define SBPI_CS_DEASSERT (1 << 3) ++#define SBPI_CS_AUTO (1 << 2) ++#define SBPI_SP (1 << 1) ++#define SBPI_ENABLE (1 << 0) ++#define REG_OTPC_SBPI_CMD_VALID_PRE (0x0024) ++#define REG_OTPC_SBPI_CS_VALID_PRE (0x0028) ++#define REG_OTPC_SBPI_STATUS (0x002C) ++#define REG_OTPC_USER_CTRL (0x0100) ++#define USER_PD (1 << 1) ++#define USER_DCTRL (1 << 0) ++#define REG_OTPC_USER_ADDR (0x0104) ++#define REG_OTPC_USER_ENABLE (0x0108) ++#define USER_ENABLE (1 << 0) ++#define REG_OTPC_USER_STATUS (0x0110) ++#define REG_OTPC_USER_QP (0x0120) ++#define REG_OTPC_USER_Q (0x0124) ++#define REG_OTPC_USER_QSR (0x0128) ++#define REG_OTPC_USER_QRR (0x012C) ++#define REG_OTPC_SBPI_CMD_BASE (0x1000) ++#define REG_OTPC_SBPI_READ_DATA_BASE (0x2000) ++#define REG_OTPC_INT_CON (0x0300) ++#define REG_OTPC_INT_STATUS (0x0304) ++ ++#define REG_KEY_READER_CONFIG 0x00 ++#define OTP_KEY_ACCESS_START (1 << 0) ++ ++int rk_otp_read(uint32_t addr, uint32_t length, ++ uint16_t *buf, bool is_need_ecc); ++int rk_otp_ns_ecc_flag(uint32_t addr); ++#endif /* RK_OTP_H */ +--- a/plat/rockchip/rk3568/drivers/pmu/pmu.c ++++ b/plat/rockchip/rk3568/drivers/pmu/pmu.c +@@ -20,6 +20,7 @@ + + #include + #include ++#include + #include + + /* +@@ -386,6 +387,7 @@ int rockchip_soc_cores_pwr_dm_resume(voi + + int rockchip_soc_sys_pwr_dm_suspend(void) + { ++ pvtplls_suspend(); + psram_sleep_cfg->pm_flag = 0; + flush_dcache_range((uintptr_t)&(psram_sleep_cfg->pm_flag), + sizeof(uint32_t)); +@@ -396,6 +398,7 @@ int rockchip_soc_sys_pwr_dm_suspend(void + + int rockchip_soc_sys_pwr_dm_resume(void) + { ++ pvtplls_resume(); + pmu_reinit(); + plat_rockchip_gic_cpuif_enable(); + psram_sleep_cfg->pm_flag = PM_WARM_BOOT_BIT; +--- /dev/null ++++ b/plat/rockchip/rk3568/drivers/scmi/rk3568_clk.c +@@ -0,0 +1,753 @@ ++/* ++ * Copyright (c) 2024, Rockchip Electronics Co., Ltd. All rights reserved. ++ * ++ * SPDX-License-Identifier: BSD-3-Clause ++ */ ++ ++#include ++ ++#include ++#include ++ ++#include ++#include ++#include ++#include ++ ++enum pll_type_sel { ++ PLL_SEL_AUTO, /* all plls (normal pll or pvtpll) */ ++ PLL_SEL_PVT, ++ PLL_SEL_NOR, ++ PLL_SEL_AUTO_NOR /* all normal plls (apll/gpll/npll) */ ++}; ++ ++#define DIV_ROUND_UP(n, d) (((n) + (d) - 1) / (d)) ++ ++#define RK3568_CPU_PVTPLL_CON0 0x10 ++#define RK3568_GPU_PVTPLL_CON0 0x700 ++#define RK3568_NPU_PVTPLL_CON0 0x740 ++ ++#define GPLL_RATE 1188000000 ++#define MAX_RATE_TABLE 16 ++ ++#define CLKDIV_5BITS_SHF0(div) BITS_WITH_WMASK(div, 0x1f, 0) ++#define CLKDIV_5BITS_SHF8(div) BITS_WITH_WMASK(div, 0x1f, 8) ++ ++#define CLKDIV_4BITS_SHF0(div) BITS_WITH_WMASK(div, 0xf, 0) ++#define CLKDIV_2BITS_SHF4(div) BITS_WITH_WMASK(div, 0x3, 4) ++ ++/* core_i: from gpll or apll */ ++#define CLK_CORE_I_SEL_APLL WMSK_BIT(6) ++#define CLK_CORE_I_SEL_GPLL BIT_WITH_WMSK(6) ++ ++/* clk_core: ++ * from normal pll(core_i: gpll or apll) path or direct pass from apll ++ */ ++#define CLK_CORE_SEL_CORE_I WMSK_BIT(7) ++#define CLK_CORE_SEL_APLL BIT_WITH_WMSK(7) ++ ++/* cpu clk: form clk_core or pvtpll */ ++#define CLK_CORE_NDFT_CLK_CORE WMSK_BIT(15) ++#define CLK_CORE_NDFT_CLK_PVTPLL BIT_WITH_WMSK(15) ++ ++/* clk_core_ndft path */ ++#define CLK_CORE_PATH_NOR_GPLL (CLK_CORE_I_SEL_GPLL | CLK_CORE_SEL_CORE_I) ++#define CLK_CORE_PATH_NOR_APLL (CLK_CORE_I_SEL_APLL | CLK_CORE_SEL_CORE_I) ++#define CLK_CORE_PATH_DIR_APLL (CLK_CORE_SEL_APLL) /* from apll directly*/ ++ ++/* cpu clk path */ ++#define CPU_CLK_PATH_NOR_GPLL (CLK_CORE_PATH_NOR_GPLL | \ ++ CLK_CORE_NDFT_CLK_CORE) ++#define CPU_CLK_PATH_NOR_APLL (CLK_CORE_PATH_NOR_APLL | \ ++ CLK_CORE_NDFT_CLK_CORE) ++#define CPU_CLK_PATH_DIR_APLL (CLK_CORE_PATH_DIR_APLL | \ ++ CLK_CORE_NDFT_CLK_CORE) ++#define CPU_CLK_PATH_PVTPLL CLK_CORE_NDFT_CLK_PVTPLL ++ ++/* dsu clk path */ ++#define SCLK_PATH_NOR_APLL (BITS_WITH_WMASK(0, 0x3, 8) | WMSK_BIT(15)) ++#define SCLK_PATH_NOR_GPLL (BITS_WITH_WMASK(0x1, 0x3, 8) | WMSK_BIT(15)) ++#define SCLK_PATH_NOR_NPLL BITS_WITH_WMASK(0x2, 0x3, 8) | WMSK_BIT(15) ++#define SCLK_PATH_DIR_NPLL BIT_WITH_WMSK(15) ++ ++/* npu clk path */ ++#define CLK_NPU_SRC_NPLL WMSK_BIT(6) ++#define CLK_NPU_SRC_GPLL BIT_WITH_WMSK(6) ++ ++#define CLK_NPU_NP5_SRC_NPLL WMSK_BIT(7) ++#define CLK_NPU_NP5_SRC_GPLL BIT_WITH_WMSK(7) ++ ++#define NPU_PRE_CLK_SEL_PLL_SRC WMSK_BIT(8) ++#define NPU_PRE_CLK_SEL_NP5 BIT_WITH_WMSK(8) ++ ++#define CLK_NPU_MUX_PLL_SRC WMSK_BIT(15) ++#define CLK_NPU_MUX_PVTPLL BIT_WITH_WMSK(15) ++ ++#define NPU_PRE_CLK_PATH_NPLL (CLK_NPU_SRC_NPLL | NPU_PRE_CLK_SEL_PLL_SRC) ++#define NPU_PRE_CLK_PATH_GPLL (CLK_NPU_SRC_GPLL | NPU_PRE_CLK_SEL_PLL_SRC) ++#define NPU_PRE_CLK_PATH_NP5_NPLL (CLK_NPU_NP5_SRC_NPLL | \ ++ NPU_PRE_CLK_SEL_NP5) ++#define NPU_PRE_CLK_PATH_NP5_GPLL (CLK_NPU_NP5_SRC_GPLL | \ ++ NPU_PRE_CLK_SEL_NP5) ++ ++#define NPU_CLK_PATH_NOR_NPLL (NPU_PRE_CLK_PATH_NPLL | CLK_NPU_MUX_PLL_SRC) ++#define NPU_CLK_PATH_NOR_GPLL (NPU_PRE_CLK_PATH_GPLL | CLK_NPU_MUX_PLL_SRC) ++#define NPU_CLK_PATH_NP5_NPLL (NPU_PRE_CLK_PATH_NP5_NPLL | \ ++ CLK_NPU_MUX_PLL_SRC) ++#define NPU_CLK_PATH_NP5_GPLL (NPU_PRE_CLK_PATH_NP5_GPLL | \ ++ CLK_NPU_MUX_PLL_SRC) ++#define NPU_CLK_PATH_PVTPLL CLK_NPU_MUX_PVTPLL ++ ++/* gpu clk path */ ++#define GPU_CLK_PATH_NOR_MPLL (WMSK_BIT(11) | BITS_WITH_WMASK(0, 0x3, 6)) ++#define GPU_CLK_PATH_NOR_GPLL (WMSK_BIT(11) | BITS_WITH_WMASK(0x1, 0x3, 6)) ++#define GPU_CLK_PATH_NOR_CPLL (WMSK_BIT(11) | BITS_WITH_WMASK(0x2, 0x3, 6)) ++#define GPU_CLK_PATH_NOR_NPLL (WMSK_BIT(11) | BITS_WITH_WMASK(0x3, 0x3, 6)) ++#define GPU_CLK_PATH_PVTPLL BIT_WITH_WMSK(11) ++ ++#define PVTPLL_NEED(type, length) (((type) == PLL_SEL_PVT || \ ++ (type) == PLL_SEL_AUTO) && \ ++ (length)) ++ ++#define RK3568_CPU_OPP_INFO_OFFSET (OTP_S_BYTE_SIZE + 54) ++#define RK3568_GPU_OPP_INFO_OFFSET (OTP_S_BYTE_SIZE + 60) ++#define RK3568_NPU_OPP_INFO_OFFSET (OTP_S_BYTE_SIZE + 66) ++ ++struct sys_clk_info_t { ++ unsigned long cpu_rate; ++ unsigned long gpu_rate; ++ unsigned long npu_rate; ++}; ++ ++struct otp_opp_info { ++ uint16_t min_freq; ++ uint16_t max_freq; ++ uint8_t volt; ++ uint8_t length; ++} __packed __aligned(2); ++ ++struct pvtpll_table { ++ unsigned int rate; ++ uint32_t refdiv; ++ uint32_t fbdiv; ++ uint32_t postdiv1; ++ uint32_t postdiv2; ++ uint32_t dsmpd; ++ uint32_t frac; ++ uint32_t length; ++}; ++ ++#define ROCKCHIP_CPU_PVTPLL(_rate, _refdiv, _fbdiv, _postdiv1, _postdiv2, _dsmpd, _frac, _length ) \ ++{ \ ++ .rate = _rate##U, \ ++ .refdiv = _refdiv, \ ++ .fbdiv = _fbdiv, \ ++ .postdiv1 = _postdiv1, \ ++ .postdiv2 = _postdiv2, \ ++ .dsmpd = _dsmpd, \ ++ .frac = _frac, \ ++ .length = _length, \ ++} ++ ++#define ROCKCHIP_GPU_PVTPLL(_rate, _length) \ ++{ \ ++ .rate = _rate##U, \ ++ .length = _length, \ ++} ++ ++static struct pvtpll_table rk3568_cpu_pvtpll_table[] = { ++ ROCKCHIP_CPU_PVTPLL(1992000000, 1, 83, 1, 1, 1, 0, 0x33), ++ ROCKCHIP_CPU_PVTPLL(1800000000, 1, 75, 1, 1, 1, 0, 0x33), ++ ROCKCHIP_CPU_PVTPLL(1608000000, 1, 67, 1, 1, 1, 0, 0x3b), ++ ROCKCHIP_CPU_PVTPLL(1416000000, 1, 118, 2, 1, 1, 0, 0x43), ++ ROCKCHIP_CPU_PVTPLL(1200000000, 1, 100, 2, 1, 1, 0, 0x53), ++ ROCKCHIP_CPU_PVTPLL(1104000000, 1, 92, 2, 1, 1, 0, 0x53), ++ ROCKCHIP_CPU_PVTPLL(1008000000, 1, 84, 2, 1, 1, 0, 0x5b), ++ ROCKCHIP_CPU_PVTPLL(816000000, 1, 68, 2, 1, 1, 0, 0), ++ ROCKCHIP_CPU_PVTPLL(600000000, 1, 100, 4, 1, 1, 0, 0), ++ ROCKCHIP_CPU_PVTPLL(408000000, 1, 68, 2, 2, 1, 0, 0), ++ ROCKCHIP_CPU_PVTPLL(312000000, 1, 78, 6, 1, 1, 0, 0), ++ ROCKCHIP_CPU_PVTPLL(216000000, 1, 72, 4, 2, 1, 0, 0), ++ { /* sentinel */ }, ++}; ++ ++static struct pvtpll_table rk3568_gpu_pvtpll_table[] = { ++ /* rate_hz, length */ ++ ROCKCHIP_GPU_PVTPLL(800000000, 0x1db), ++ ROCKCHIP_GPU_PVTPLL(700000000, 0x1db), ++ ROCKCHIP_GPU_PVTPLL(600000000, 0x1db), ++ ROCKCHIP_GPU_PVTPLL(400000000, 0), ++ ROCKCHIP_GPU_PVTPLL(300000000, 0), ++ ROCKCHIP_GPU_PVTPLL(200000000, 0), ++ { /* sentinel */ }, ++}; ++ ++static struct pvtpll_table rk3568_npu_pvtpll_table[] = { ++ /* rate_hz, length */ ++ ROCKCHIP_GPU_PVTPLL(1000000000, 0xd3), ++ ROCKCHIP_GPU_PVTPLL(900000000, 0xd3), ++ ROCKCHIP_GPU_PVTPLL(800000000, 0xd3), ++ ROCKCHIP_GPU_PVTPLL(700000000, 0xdb), ++ ROCKCHIP_GPU_PVTPLL(600000000, 0xfb), ++ ROCKCHIP_GPU_PVTPLL(400000000, 0), ++ ROCKCHIP_GPU_PVTPLL(300000000, 0), ++ ROCKCHIP_GPU_PVTPLL(200000000, 0), ++ { /* sentinel */ }, ++}; ++ ++static unsigned long rk3568_cpu_rates[] = { ++ 216000000, 312000000, 408000000, 816000000, ++ 1008000000, 1200000000, 1416000000, 1608000000, ++ 1800000000, 1992000000 ++}; ++ ++static unsigned long rk3568_gpu_rates[] = { ++ 100000000, 200000000, 300000000, 400000000, ++ 500000000, 600000000, 700000000, 800000000, ++ 900000000, 1000000000, 1100000000, 1200000000 ++}; ++ ++static struct sys_clk_info_t sys_clk_info; ++ ++static bool check_otp_ecc_ok(uint32_t addr) ++{ ++ int i; ++ ++ for (i = 0; i < sizeof(struct otp_opp_info); i++) { ++ if (rk_otp_ns_ecc_flag(addr + i)) ++ return false; ++ } ++ ++ return true; ++} ++ ++static void rk3568_adjust_pvtpll_table(struct pvtpll_table *pvtpll, ++ unsigned int count, ++ uint16_t min_freq, ++ uint16_t max_freq, ++ uint8_t length) ++{ ++ uint16_t freq; ++ uint8_t cur_length; ++ int i; ++ ++ if (length > 31) ++ return; ++ ++ for (i = 0; i < count; i++) { ++ if (!pvtpll[i].length) ++ continue; ++ cur_length = (pvtpll[i].length >> 3) & 0x1f; ++ ++ /* ++ * Max value of length is 31, so adjust length to ++ * make sure (cur_length + length) <= 31. ++ */ ++ if ((cur_length + length) > 31) ++ length = 31 - cur_length; ++ freq = pvtpll[i].rate / 1000000; ++ if ((freq >= min_freq) && (freq <= max_freq)) ++ pvtpll[i].length += (length << 3); ++ } ++} ++ ++static unsigned int ++rockchip_get_pvtpll_length(struct pvtpll_table *table, int count, ++ unsigned long rate) ++{ ++ int i; ++ ++ for (i = 0; i < count; i++) { ++ if (rate == table[i].rate) ++ return table[i].length; ++ } ++ return 0; ++} ++ ++static struct pvtpll_table *rkclk_get_pll_config(unsigned int freq_hz) ++{ ++ unsigned int rate_count = ARRAY_SIZE(rk3568_cpu_pvtpll_table); ++ int i; ++ ++ for (i = 0; i < rate_count; i++) { ++ if (freq_hz == rk3568_cpu_pvtpll_table[i].rate) ++ return &rk3568_cpu_pvtpll_table[i]; ++ } ++ return NULL; ++} ++ ++static int rk3568_apll_set_rate(unsigned long rate, enum pll_type_sel type) ++{ ++ struct pvtpll_table *div; ++ int delay = 2400; ++ ++ div = rkclk_get_pll_config(rate); ++ if (div == NULL) ++ return SCMI_INVALID_PARAMETERS; ++ ++ if (PVTPLL_NEED(type, div->length)) { ++ /* set pvtpll length */ ++ mmio_write_32(CPUGRF_BASE + RK3568_CPU_PVTPLL_CON0, ++ 0xffff0000); ++ udelay(1); ++ mmio_write_32(CPUGRF_BASE + RK3568_CPU_PVTPLL_CON0, ++ 0xffff0000 | div->length); ++ udelay(1); ++ /* set core mux pvtpll */ ++ mmio_write_32(CRU_BASE + RK3568_CLK_SEL(0), ++ CPU_CLK_PATH_PVTPLL); ++ } ++ ++ /* pll enter slow mode */ ++ mmio_write_32(CRU_BASE + 0xc0, ++ (RK3568_PLL_MODE_MASK << ++ (16 + RK3568_PLL_MODE_SHIFT)) | ++ (RK3568_PLL_MODE_SLOWMODE << RK3568_PLL_MODE_SHIFT)); ++ /* update pll values */ ++ mmio_write_32(CRU_BASE + RK3568_PLLCON(0), ++ (RK3568_PLLCON0_FBDIV_MASK << ++ (16 + RK3568_PLLCON0_FBDIV_SHIFT)) | ++ (div->fbdiv << RK3568_PLLCON0_FBDIV_SHIFT)); ++ mmio_write_32(CRU_BASE + RK3568_PLLCON(0), ++ (RK3568_PLLCON0_POSTDIV1_MASK << ++ (16 + RK3568_PLLCON0_POSTDIV1_SHIFT)) | ++ (div->postdiv1 << RK3568_PLLCON0_POSTDIV1_SHIFT)); ++ mmio_write_32(CRU_BASE + RK3568_PLLCON(1), ++ (RK3568_PLLCON1_REFDIV_MASK << ++ (16 + RK3568_PLLCON1_REFDIV_SHIFT)) | ++ (div->refdiv << RK3568_PLLCON1_REFDIV_SHIFT)); ++ mmio_write_32(CRU_BASE + RK3568_PLLCON(1), ++ (RK3568_PLLCON1_POSTDIV2_MASK << ++ (16 + RK3568_PLLCON1_POSTDIV2_SHIFT)) | ++ (div->postdiv2 << RK3568_PLLCON1_POSTDIV2_SHIFT)); ++ mmio_write_32(CRU_BASE + RK3568_PLLCON(1), ++ (RK3568_PLLCON1_DSMPD_MASK << ++ (16 + RK3568_PLLCON1_DSMPD_SHIFT)) | ++ (div->dsmpd << RK3568_PLLCON1_DSMPD_SHIFT)); ++ ++ /* wait for the pll to lock */ ++ while (delay > 0) { ++ if (mmio_read_32(CRU_BASE + RK3568_PLLCON(1)) & ++ RK3568_PLLCON1_LOCK_STATUS) ++ break; ++ udelay(1); ++ delay--; ++ } ++ if (delay == 0) ++ INFO("%s:ERROR: PLL WAIT LOCK FAILED\n", __func__); ++ ++ /* pll enter normal mode */ ++ mmio_write_32(CRU_BASE + 0xc0, ++ (RK3568_PLL_MODE_MASK << (16 + RK3568_PLL_MODE_SHIFT)) | ++ (RK3568_PLL_MODE_NORMAL << RK3568_PLL_MODE_SHIFT)); ++ ++ return 0; ++} ++ ++static unsigned long rk3568_apll_get_rate(void) ++{ ++ unsigned int fbdiv, postdiv1, refdiv, postdiv2; ++ uint64_t rate64 = 24000000; ++ int mode; ++ ++ mode = (mmio_read_32(CRU_BASE + 0xc0) >> RK3568_PLL_MODE_SHIFT) & ++ RK3568_PLL_MODE_MASK; ++ ++ if (mode == RK3568_PLL_MODE_SLOWMODE) ++ return rate64; ++ ++ fbdiv = (mmio_read_32(CRU_BASE + RK3568_PLLCON(0)) >> ++ RK3568_PLLCON0_FBDIV_SHIFT) & ++ RK3568_PLLCON0_FBDIV_MASK; ++ postdiv1 = (mmio_read_32(CRU_BASE + RK3568_PLLCON(0)) >> ++ RK3568_PLLCON0_POSTDIV1_SHIFT) & ++ RK3568_PLLCON0_POSTDIV1_MASK; ++ refdiv = (mmio_read_32(CRU_BASE + RK3568_PLLCON(1)) >> ++ RK3568_PLLCON1_REFDIV_SHIFT) & ++ RK3568_PLLCON1_REFDIV_MASK; ++ postdiv2 = (mmio_read_32(CRU_BASE + RK3568_PLLCON(1)) >> ++ RK3568_PLLCON1_POSTDIV2_SHIFT) & ++ RK3568_PLLCON1_POSTDIV2_MASK; ++ ++ rate64 *= fbdiv; ++ rate64 = rate64 / refdiv; ++ rate64 = rate64 / postdiv1; ++ rate64 = rate64 / postdiv2; ++ ++ return (unsigned long)rate64; ++} ++ ++static int clk_cpu_set_rate(unsigned long rate, enum pll_type_sel type) ++{ ++ int div = 0, ret = 0; ++ ++ if (!rate) ++ return SCMI_INVALID_PARAMETERS; ++ ++ /* set clk core div to 3 */ ++ mmio_write_32(CRU_BASE + RK3568_CLK_SEL(0), ++ CLKDIV_5BITS_SHF8(2) | CLKDIV_5BITS_SHF0(2)); ++ mmio_write_32(CRU_BASE + RK3568_CLK_SEL(1), ++ CLKDIV_5BITS_SHF8(2) | CLKDIV_5BITS_SHF0(2)); ++ /* set atcore/gicclk div */ ++ mmio_write_32(CRU_BASE + RK3568_CLK_SEL(3), ++ CLKDIV_5BITS_SHF8(7) | CLKDIV_5BITS_SHF0(7)); ++ /* set pclk/periph div */ ++ mmio_write_32(CRU_BASE + RK3568_CLK_SEL(4), ++ CLKDIV_5BITS_SHF8(9) | CLKDIV_5BITS_SHF0(9)); ++ ++ /* set dsu div to 4 */ ++ mmio_write_32(CRU_BASE + RK3568_CLK_SEL(2), CLKDIV_4BITS_SHF0(3)); ++ ++ /* set core mux gpll */ ++ mmio_write_32(CRU_BASE + RK3568_CLK_SEL(0), CPU_CLK_PATH_NOR_GPLL); ++ /* set dsu mux gpll */ ++ mmio_write_32(CRU_BASE + RK3568_CLK_SEL(2), SCLK_PATH_NOR_GPLL); ++ ++ /* set apll */ ++ ret = rk3568_apll_set_rate(rate, type); ++ if (ret < 0) ++ return ret; ++ ++ /* set t core mux apll */ ++ mmio_write_32(CRU_BASE + RK3568_CLK_SEL(0), CLK_CORE_PATH_DIR_APLL); ++ ++ div = DIV_ROUND_UP(rate, 300000000); ++ div = div - 1; ++ /* set atcore/gicclk div */ ++ mmio_write_32(CRU_BASE + RK3568_CLK_SEL(3), ++ CLKDIV_5BITS_SHF8(div) | CLKDIV_5BITS_SHF0(div)); ++ /* set pclk/periph div */ ++ div = DIV_ROUND_UP(rate, 300000000); ++ div = div - 1; ++ mmio_write_32(CRU_BASE + RK3568_CLK_SEL(4), ++ CLKDIV_5BITS_SHF8(div) | CLKDIV_5BITS_SHF0(div)); ++ ++ if (rate >= 1608000000) { ++ /* set dsu mux npll */ ++ mmio_write_32(CRU_BASE + RK3568_CLK_SEL(2), ++ SCLK_PATH_DIR_NPLL); ++ /* set dsu div to 1 */ ++ mmio_write_32(CRU_BASE + RK3568_CLK_SEL(2), ++ CLKDIV_4BITS_SHF0(0)); ++ } else { ++ /* set dsu mux apll */ ++ mmio_write_32(CRU_BASE + RK3568_CLK_SEL(2), ++ SCLK_PATH_NOR_APLL); ++ /* set dsu div to 2 */ ++ mmio_write_32(CRU_BASE + RK3568_CLK_SEL(2), ++ CLKDIV_4BITS_SHF0(1)); ++ } ++ ++ /* set clk core div to 1 */ ++ mmio_write_32(CRU_BASE + RK3568_CLK_SEL(0), ++ CLKDIV_5BITS_SHF8(0) | CLKDIV_5BITS_SHF0(0)); ++ mmio_write_32(CRU_BASE + RK3568_CLK_SEL(1), ++ CLKDIV_5BITS_SHF8(0) | CLKDIV_5BITS_SHF0(0)); ++ return ret; ++} ++ ++static int clk_scmi_cpu_set_rate(struct rk_scmi_clock *clock, unsigned long rate) ++{ ++ int ret; ++ ++ ret = clk_cpu_set_rate(rate, PLL_SEL_AUTO); ++ ++ if (!ret) ++ sys_clk_info.cpu_rate = rate; ++ ++ return ret; ++} ++ ++static unsigned long clk_scmi_cpu_get_rate(struct rk_scmi_clock *clock) ++{ ++ return rk3568_apll_get_rate(); ++} ++ ++static int clk_scmi_cpu_set_status(struct rk_scmi_clock *clock, bool status) ++{ ++ return 0; ++} ++ ++static unsigned long clk_scmi_gpu_get_rate(struct rk_scmi_clock *clock) ++{ ++ int div; ++ ++ if (mmio_read_32(CRU_BASE + RK3568_CLK_SEL(6)) & 0x0800) { ++ return 0; ++ } else { ++ div = mmio_read_32(CRU_BASE + RK3568_CLK_SEL(6)); ++ div = div & 0x000f; ++ return GPLL_RATE / (div + 1); ++ } ++} ++ ++static int clk_gpu_set_rate(unsigned long rate, enum pll_type_sel type) ++{ ++ unsigned int length; ++ int div; ++ ++ if (!rate) ++ return SCMI_INVALID_PARAMETERS; ++ ++ /* set gpu div 6 */ ++ mmio_write_32(CRU_BASE + RK3568_CLK_SEL(6), CLKDIV_4BITS_SHF0(5)); ++ /* set gpu mux gpll */ ++ mmio_write_32(CRU_BASE + RK3568_CLK_SEL(6), GPU_CLK_PATH_NOR_GPLL); ++ ++ /* set pvtpll ring */ ++ length = rockchip_get_pvtpll_length(rk3568_gpu_pvtpll_table, ++ ARRAY_SIZE(rk3568_gpu_pvtpll_table), ++ rate); ++ if (PVTPLL_NEED(type, length)) { ++ mmio_write_32(GRF_BASE + RK3568_GPU_PVTPLL_CON0, ++ 0xffff0000); ++ udelay(1); ++ mmio_write_32(GRF_BASE + RK3568_GPU_PVTPLL_CON0, ++ 0xffff0000 | length); ++ udelay(1); ++ /* set gpu mux pvtpll */ ++ mmio_write_32(CRU_BASE + RK3568_CLK_SEL(6), ++ GPU_CLK_PATH_PVTPLL); ++ } ++ ++ div = DIV_ROUND_UP(GPLL_RATE, rate); ++ /* set gpu div */ ++ mmio_write_32(CRU_BASE + RK3568_CLK_SEL(6), CLKDIV_4BITS_SHF0((div - 1))); ++ ++ return 0; ++} ++ ++static int clk_scmi_gpu_set_rate(struct rk_scmi_clock *clock, unsigned long rate) ++{ ++ int ret; ++ ++ ret = clk_gpu_set_rate(rate, PLL_SEL_AUTO); ++ ++ if (!ret) ++ sys_clk_info.gpu_rate = rate; ++ return ret; ++} ++ ++static int clk_scmi_gpu_set_status(struct rk_scmi_clock *clock, bool status) ++{ ++ return 0; ++} ++ ++static unsigned long clk_scmi_npu_get_rate(struct rk_scmi_clock *clock) ++{ ++ int div; ++ ++ if (mmio_read_32(CRU_BASE + RK3568_CLK_SEL(7)) & 0x8000) { ++ return 0; ++ } else { ++ div = mmio_read_32(CRU_BASE + RK3568_CLK_SEL(7)); ++ div = div & 0x000f; ++ return GPLL_RATE / (div + 1); ++ } ++} ++ ++static int clk_npu_set_rate(unsigned long rate, enum pll_type_sel type) ++{ ++ unsigned int length; ++ int div; ++ ++ if (!rate) ++ return SCMI_INVALID_PARAMETERS; ++ ++ /* set npu div 6 */ ++ mmio_write_32(CRU_BASE + RK3568_CLK_SEL(7), ++ CLKDIV_2BITS_SHF4(2) | CLKDIV_4BITS_SHF0(5)); ++ /* set npu mux gpll */ ++ mmio_write_32(CRU_BASE + RK3568_CLK_SEL(7), ++ NPU_CLK_PATH_NOR_GPLL | CLK_NPU_NP5_SRC_GPLL); ++ ++ /* set pvtpll ring */ ++ length = rockchip_get_pvtpll_length(rk3568_npu_pvtpll_table, ++ ARRAY_SIZE(rk3568_npu_pvtpll_table), ++ rate); ++ if (PVTPLL_NEED(type, length)) { ++ mmio_write_32(GRF_BASE + RK3568_NPU_PVTPLL_CON0, ++ 0xffff0000); ++ udelay(1); ++ mmio_write_32(GRF_BASE + RK3568_NPU_PVTPLL_CON0, ++ 0xffff0000 | length); ++ udelay(1); ++ /* set npu mux pvtpll */ ++ mmio_write_32(CRU_BASE + RK3568_CLK_SEL(7), ++ NPU_CLK_PATH_PVTPLL); ++ } else { ++ div = DIV_ROUND_UP(GPLL_RATE, rate); ++ /* set gpu div */ ++ mmio_write_32(CRU_BASE + RK3568_CLK_SEL(7), ++ CLKDIV_4BITS_SHF0((div - 1))); ++ } ++ ++ return 0; ++} ++ ++static int clk_scmi_npu_set_rate(struct rk_scmi_clock *clock, unsigned long rate) ++{ ++ int ret; ++ ++ ret = clk_npu_set_rate(rate, PLL_SEL_AUTO); ++ ++ if (!ret) ++ sys_clk_info.npu_rate = rate; ++ ++ return ret; ++} ++ ++static int clk_scmi_npu_set_status(struct rk_scmi_clock *clock, bool status) ++{ ++ return 0; ++} ++ ++static const struct rk_clk_ops clk_scmi_cpu_ops = { ++ .get_rate = clk_scmi_cpu_get_rate, ++ .set_rate = clk_scmi_cpu_set_rate, ++ .set_status = clk_scmi_cpu_set_status, ++}; ++ ++static const struct rk_clk_ops clk_scmi_gpu_ops = { ++ .get_rate = clk_scmi_gpu_get_rate, ++ .set_rate = clk_scmi_gpu_set_rate, ++ .set_status = clk_scmi_gpu_set_status, ++}; ++ ++static const struct rk_clk_ops clk_scmi_npu_ops = { ++ .get_rate = clk_scmi_npu_get_rate, ++ .set_rate = clk_scmi_npu_set_rate, ++ .set_status = clk_scmi_npu_set_status, ++}; ++ ++struct rk_scmi_clock clock_table[] = { ++ { ++ .id = 0, ++ .name = "clk_scmi_cpu", ++ .clk_ops = &clk_scmi_cpu_ops, ++ .rate_table = rk3568_cpu_rates, ++ .rate_cnt = ARRAY_SIZE(rk3568_cpu_rates), ++ }, ++ { ++ .id = 1, ++ .name = "clk_scmi_gpu", ++ .clk_ops = &clk_scmi_gpu_ops, ++ .rate_table = rk3568_gpu_rates, ++ .rate_cnt = ARRAY_SIZE(rk3568_gpu_rates), ++ }, ++ { ++ .id = 2, ++ .name = "clk_scmi_npu", ++ .clk_ops = &clk_scmi_npu_ops, ++ .rate_table = rk3568_gpu_rates, ++ .rate_cnt = ARRAY_SIZE(rk3568_gpu_rates), ++ }, ++}; ++ ++size_t rockchip_scmi_clock_count(unsigned int agent_id __unused) ++{ ++ return ARRAY_SIZE(clock_table); ++} ++ ++rk_scmi_clock_t *rockchip_scmi_get_clock(uint32_t agent_id __unused, ++ uint32_t clock_id) ++{ ++ if (clock_id < ARRAY_SIZE(clock_table)) ++ return &clock_table[clock_id]; ++ ++ return NULL; ++} ++ ++void pvtplls_suspend(void) ++{ ++ clk_gpu_set_rate(100000000, PLL_SEL_NOR); ++ clk_npu_set_rate(100000000, PLL_SEL_NOR); ++ clk_cpu_set_rate(408000000, PLL_SEL_NOR); ++} ++ ++void pvtplls_resume(void) ++{ ++ clk_cpu_set_rate(sys_clk_info.cpu_rate, PLL_SEL_AUTO); ++ clk_gpu_set_rate(sys_clk_info.gpu_rate, PLL_SEL_AUTO); ++ clk_npu_set_rate(sys_clk_info.npu_rate, PLL_SEL_AUTO); ++} ++ ++void sys_reset_pvtplls_prepare(void) ++{ ++ clk_gpu_set_rate(100000000, PLL_SEL_NOR); ++ clk_npu_set_rate(100000000, PLL_SEL_NOR); ++ clk_cpu_set_rate(408000000, PLL_SEL_NOR); ++} ++ ++void rockchip_clock_init(void) ++{ ++ struct otp_opp_info cpu_opp_info, gpu_opp_info, npu_opp_info; ++ int ret; ++ ++ ret = rk_otp_read(RK3568_CPU_OPP_INFO_OFFSET, ++ sizeof(cpu_opp_info), ++ (uint16_t *)&cpu_opp_info, ++ true); ++ if (ret || !check_otp_ecc_ok(RK3568_CPU_OPP_INFO_OFFSET)) { ++ INFO("get cpu_opp_info fail, use default config!\n"); ++ cpu_opp_info.min_freq = 1008; ++ cpu_opp_info.max_freq = 1992; ++ cpu_opp_info.volt = 50; ++ cpu_opp_info.length = 4; ++ } ++ if (cpu_opp_info.length) { ++ INFO("adjust cpu pvtpll: min=%uM, max=%uM, length=%u\n", ++ cpu_opp_info.min_freq, cpu_opp_info.max_freq, cpu_opp_info.length); ++ ++ rk3568_adjust_pvtpll_table(rk3568_cpu_pvtpll_table, ++ ARRAY_SIZE(rk3568_cpu_pvtpll_table), ++ cpu_opp_info.min_freq, ++ cpu_opp_info.max_freq, ++ cpu_opp_info.length); ++ } ++ ++ ret = rk_otp_read(RK3568_GPU_OPP_INFO_OFFSET, ++ sizeof(gpu_opp_info), ++ (uint16_t *)&gpu_opp_info, ++ true); ++ if (ret || !check_otp_ecc_ok(RK3568_GPU_OPP_INFO_OFFSET)) { ++ INFO("get gpu_opp_info fail, use default config!\n"); ++ gpu_opp_info.min_freq = 600; ++ gpu_opp_info.max_freq = 800; ++ gpu_opp_info.volt = 50; ++ gpu_opp_info.length = 6; ++ } ++ if (gpu_opp_info.length) { ++ INFO("adjust gpu pvtpll: min=%uM, max=%uM, length=%u\n", ++ gpu_opp_info.min_freq, gpu_opp_info.max_freq, gpu_opp_info.length); ++ ++ rk3568_adjust_pvtpll_table(rk3568_gpu_pvtpll_table, ++ ARRAY_SIZE(rk3568_gpu_pvtpll_table), ++ gpu_opp_info.min_freq, ++ gpu_opp_info.max_freq, ++ gpu_opp_info.length); ++ } ++ ++ ret = rk_otp_read(RK3568_NPU_OPP_INFO_OFFSET, ++ sizeof(npu_opp_info), ++ (uint16_t *)&npu_opp_info, ++ true); ++ if (ret || !check_otp_ecc_ok(RK3568_NPU_OPP_INFO_OFFSET)) { ++ INFO("get npu_opp_info fail, use default config!\n"); ++ npu_opp_info.min_freq = 600; ++ npu_opp_info.max_freq = 1000; ++ npu_opp_info.volt = 50; ++ npu_opp_info.length = 6; ++ } ++ if (npu_opp_info.length) { ++ INFO("adjust npu pvtpll: min=%uM, max=%uM, length=%u\n", ++ npu_opp_info.min_freq, npu_opp_info.max_freq, npu_opp_info.length); ++ ++ rk3568_adjust_pvtpll_table(rk3568_npu_pvtpll_table, ++ ARRAY_SIZE(rk3568_npu_pvtpll_table), ++ npu_opp_info.min_freq, ++ npu_opp_info.max_freq, ++ npu_opp_info.length); ++ } ++} +--- /dev/null ++++ b/plat/rockchip/rk3568/drivers/scmi/rk3568_clk.h +@@ -0,0 +1,70 @@ ++/* ++ * Copyright (c) 2024, Rockchip Electronics Co., Ltd. All rights reserved. ++ * ++ * SPDX-License-Identifier: BSD-3-Clause ++ */ ++ ++#ifndef __CLOCK_H__ ++#define __CLOCK_H__ ++ ++#define CRU_CLKGATE_CON0 0x300 ++#define CRU_CLKGATES_CON(i) (CRU_CLKGATE_CON0 + (i) * 4) ++ ++#define SCRU_GATE_CON00 0x0180 ++#define SCRU_GATE_CON01 0x0184 ++#define SCRU_GATE_CON02 0x0188 ++ ++#define SGRF_SOC_CON2 0x0008 ++ ++#define MPLL_HZ (800 * MHz) ++#define MPLL_REFDIV 3 ++#define MPLL_FBDIV 200 ++#define MPLL_POSTDIV1 2 ++#define MPLL_POSTDIV2 1 ++#define MPLL_DSMPD 1 ++#define MPLL_FRAC 0 ++ ++#define PPLL_HZ (200 * MHz) ++#define GPLL_HZ (1188 * MHz) ++#define ACLK_SECURE_FLASH_S_HZ (297 * MHz) ++#define HCLK_SECURE_FLASH_S_HZ (148500000) ++#define PCLK_SECURE_FLASH_S_HZ (99 * MHz) ++#define PCLK_TOP_S_HZ (99 * MHz) ++#define HCLK_VO_S_HZ (99 * MHz) ++#define PCLK_DDR_HZ (99 * MHz) ++#define PCLK_PDPMU_S_HZ (100 * MHz) ++#define HCLK_PDPMU_S_HZ (100 * MHz) ++ ++#define RK3568_PLL_MODE_CON 0x20 ++#define RK3568_PLL_MODE_SHIFT 0 ++#define RK3568_PLL_MODE_MASK (0x3 << RK3568_PLL_MODE_SHIFT) ++#define RK3568_PLL_MODE_SLOWMODE 0 ++#define RK3568_PLL_MODE_NORMAL 1 ++#define RK3568_PLLCON(i) (i * 0x4) ++#define RK3568_PLLCON0_FBDIV_MASK 0xfff ++#define RK3568_PLLCON0_FBDIV_SHIFT 0 ++#define RK3568_PLLCON0_POSTDIV1_MASK 0x7 ++#define RK3568_PLLCON0_POSTDIV1_SHIFT 12 ++#define RK3568_PLLCON1_REFDIV_MASK 0x3f ++#define RK3568_PLLCON1_REFDIV_SHIFT 0 ++#define RK3568_PLLCON1_POSTDIV2_MASK 0x7 ++#define RK3568_PLLCON1_POSTDIV2_SHIFT 6 ++#define RK3568_PLLCON1_LOCK_STATUS (1 << 10) ++#define RK3568_PLLCON1_DSMPD_MASK 0x1 ++#define RK3568_PLLCON1_DSMPD_SHIFT 12 ++#define RK3568_PLLCON1_PWRDOWN (1 << 13) ++ ++#define RK3568_CLK_SEL(x) ((x) * 0x4 + 0x100) ++#define RK3568_PMUCLK_SEL(x) ((x) * 0x4 + 0x100) ++ ++#define PMUCRU_MODE_CON00 0x0080 ++#define PMUCRU_PMUCLKSEL_CON00 0x0100 ++#define PMUCRU_PMUCLKSEL_CON03 0x010c ++#define PMUCRU_PMUGATE_CON01 0x0184 ++#define PMUCRU_CLKGATES_CON(i) (0x180 + (i) * 4) ++#define PMUCRU_CLKGATES_CON_CNT 3 ++ ++void pvtplls_suspend(void); ++void pvtplls_resume(void); ++void rockchip_clock_init(void); ++#endif +--- a/plat/rockchip/rk3568/drivers/soc/soc.c ++++ b/plat/rockchip/rk3568/drivers/soc/soc.c +@@ -9,6 +9,8 @@ + #include + #include + ++#include ++#include + #include + + const mmap_region_t plat_rk_mmap[] = { +@@ -16,6 +18,8 @@ const mmap_region_t plat_rk_mmap[] = { + MT_DEVICE | MT_RW | MT_SECURE), + MAP_REGION_FLAT(PMUSRAM_BASE, PMUSRAM_SIZE, + MT_MEMORY | MT_RW | MT_SECURE), ++ MAP_REGION_FLAT(DDR_SHARE_MEM, DDR_SHARE_SIZE, ++ MT_DEVICE | MT_RW | MT_NS), + + { 0 } + }; +@@ -94,9 +98,11 @@ void __dead2 rockchip_soc_soft_reset(voi + + void plat_rockchip_soc_init(void) + { ++ rockchip_clock_init(); + secure_timer_init(); + sgrf_init(); + rockchip_system_reset_init(); ++ rockchip_init_scmi_server(); + NOTICE("BL31: Rockchip release version: v%d.%d\n", + MAJOR_VERSION, MINOR_VERSION); + } +--- a/plat/rockchip/rk3568/plat_sip_calls.c ++++ b/plat/rockchip/rk3568/plat_sip_calls.c +@@ -9,8 +9,7 @@ + + #include + #include +-#include +-#include ++#include + + #include + #include +@@ -24,6 +23,12 @@ uintptr_t rockchip_plat_sip_handler(uint + void *handle, + u_register_t flags) + { +- ERROR("%s: unhandled SMC (0x%x)\n", __func__, smc_fid); +- SMC_RET1(handle, SMC_UNK); ++ switch (smc_fid) { ++ case RK_SIP_SCMI_AGENT0: ++ scmi_smt_fastcall_smc_entry(0); ++ SMC_RET1(handle, 0); ++ default: ++ ERROR("%s: unhandled SMC (0x%x)\n", __func__, smc_fid); ++ SMC_RET1(handle, SMC_UNK); ++ } + } +--- a/plat/rockchip/rk3568/platform.mk ++++ b/plat/rockchip/rk3568/platform.mk +@@ -34,14 +34,18 @@ PLAT_INCLUDES := -Iinclude/bl31 \ + -Iinclude/services \ + -Iinclude/plat/common/ \ + -Idrivers/arm/gic/v3/ \ ++ -Idrivers/scmi-msg/ \ + -I${RK_PLAT_COMMON}/ \ + -I${RK_PLAT_COMMON}/pmusram/ \ + -I${RK_PLAT_COMMON}/include/ \ + -I${RK_PLAT_COMMON}/drivers/pmu/ \ + -I${RK_PLAT_COMMON}/drivers/parameter/ \ ++ -I${RK_PLAT_COMMON}/scmi/ \ + -I${RK_PLAT_SOC}/ \ ++ -I${RK_PLAT_SOC}/drivers/otp/ \ + -I${RK_PLAT_SOC}/drivers/pmu/ \ + -I${RK_PLAT_SOC}/drivers/soc/ \ ++ -I${RK_PLAT_SOC}/drivers/scmi/ \ + -I${RK_PLAT_SOC}/include/ + + RK_GIC_SOURCES := ${GICV3_SOURCES} \ +@@ -64,6 +68,11 @@ BL31_SOURCES += ${RK_GIC_SOURCES} \ + drivers/ti/uart/aarch64/16550_console.S \ + drivers/delay_timer/delay_timer.c \ + drivers/delay_timer/generic_delay_timer.c \ ++ drivers/scmi-msg/base.c \ ++ drivers/scmi-msg/clock.c \ ++ drivers/scmi-msg/entry.c \ ++ drivers/scmi-msg/reset_domain.c \ ++ drivers/scmi-msg/smt.c \ + $(LIBFDT_SRCS) \ + ${RK_PLAT_COMMON}/aarch64/plat_helpers.S \ + ${RK_PLAT_COMMON}/bl31_plat_setup.c \ +@@ -74,6 +83,11 @@ BL31_SOURCES += ${RK_GIC_SOURCES} \ + ${RK_PLAT_COMMON}/pmusram/cpus_on_fixed_addr.S \ + ${RK_PLAT_COMMON}/drivers/parameter/ddr_parameter.c \ + ${RK_PLAT_COMMON}/aarch64/platform_common.c \ ++ ${RK_PLAT_COMMON}/scmi/scmi.c \ ++ ${RK_PLAT_COMMON}/scmi/scmi_clock.c \ ++ ${RK_PLAT_COMMON}/scmi/scmi_rstd.c \ ++ ${RK_PLAT_SOC}/drivers/scmi/rk3568_clk.c \ ++ ${RK_PLAT_SOC}/drivers/otp/otp.c \ + ${RK_PLAT_SOC}/drivers/soc/soc.c \ + ${RK_PLAT_SOC}/drivers/pmu/pmu.c \ + ${RK_PLAT_SOC}/plat_sip_calls.c +--- a/plat/rockchip/rk3568/rk3568_def.h ++++ b/plat/rockchip/rk3568/rk3568_def.h +@@ -52,6 +52,8 @@ + #define PMUSRAM_RSIZE SIZE_K(8) + + #define DDRSGRF_BASE 0xfe200000 ++#define OTP_NS_BASE 0xfe38c000 ++#define OTP_S_BASE 0xfe3a0000 + #define UART1_BASE 0xfe650000 + #define UART2_BASE 0xfe660000 + #define GPIO1_BASE 0xfe740000 +@@ -59,6 +61,8 @@ + #define GPIO3_BASE 0xfe760000 + #define GPIO4_BASE 0xfe770000 + ++#define OTP_PHY_BASE 0xfe880000 ++ + #define REMAP_BASE 0xffff0000 + #define REMAP_SIZE SIZE_K(64) + /************************************************************************** +@@ -97,8 +101,20 @@ + #define RK_IRQ_SEC_SGI_6 14 + #define RK_IRQ_SEC_SGI_7 15 + +-#define SHARE_MEM_BASE 0x100000/* [1MB, 1MB+60K]*/ ++/************************************************************************** ++ * share mem region allocation: 1M~2M ++ **************************************************************************/ ++#define DDR_SHARE_MEM SIZE_K(1024) ++#define DDR_SHARE_SIZE SIZE_K(64) ++ ++#define SHARE_MEM_BASE 0x100000/* [1MB, 1MB+60K] */ + #define SHARE_MEM_PAGE_NUM 15 + #define SHARE_MEM_SIZE SIZE_K(SHARE_MEM_PAGE_NUM * 4) + ++#define SCMI_SHARE_MEM_BASE (SHARE_MEM_BASE + SHARE_MEM_SIZE) ++#define SCMI_SHARE_MEM_SIZE SIZE_K(4) ++ ++#define SMT_BUFFER_BASE SCMI_SHARE_MEM_BASE ++#define SMT_BUFFER0_BASE SMT_BUFFER_BASE ++ + #endif /* __PLAT_DEF_H__ */ diff --git a/package/boot/arm-trusted-firmware-rockchip/patches/001-feat-rk3588-enable-crypto-function.patch b/package/boot/arm-trusted-firmware-rockchip/patches/001-feat-rk3588-enable-crypto-function.patch deleted file mode 100644 index e075583fa..000000000 --- a/package/boot/arm-trusted-firmware-rockchip/patches/001-feat-rk3588-enable-crypto-function.patch +++ /dev/null @@ -1,140 +0,0 @@ -From 35cb9811b8cc2099ce11e2c86d9da6786c28a6c6 Mon Sep 17 00:00:00 2001 -From: XiaoDong Huang -Date: Mon, 17 Jun 2024 10:55:27 +0800 -Subject: [PATCH] feat(rk3588): enable crypto function - -The CPU crypto is not default on when power up, need to enable it by -software. - -Signed-off-by: XiaoDong Huang -Change-Id: Ifee2eab55d9c13cef5f15926fb80016845e2a66d ---- - bl31/aarch64/bl31_entrypoint.S | 9 +++ - plat/rockchip/rk3588/drivers/pmu/pmu.c | 79 ++++++++++++++++++++++++++ - plat/rockchip/rk3588/platform.mk | 1 + - 3 files changed, 89 insertions(+) - ---- a/bl31/aarch64/bl31_entrypoint.S -+++ b/bl31/aarch64/bl31_entrypoint.S -@@ -16,6 +16,11 @@ - .globl bl31_entrypoint - .globl bl31_warm_entrypoint - -+#ifdef PLAT_RK_BL31_ENTRYPOINT -+ .globl plat_rockchip_bl31_entrypoint -+ .globl plat_rockchip_bl31_entrypoint_set_sp -+#endif -+ - /* ----------------------------------------------------- - * bl31_entrypoint() is the cold boot entrypoint, - * executed only by the primary cpu. -@@ -23,6 +28,10 @@ - */ - - func bl31_entrypoint -+#ifdef PLAT_RK_BL31_ENTRYPOINT -+ bl plat_rockchip_bl31_entrypoint_set_sp -+ bl plat_rockchip_bl31_entrypoint -+#endif - /* --------------------------------------------------------------- - * Stash the previous bootloader arguments x0 - x3 for later use. - * --------------------------------------------------------------- ---- a/plat/rockchip/rk3588/drivers/pmu/pmu.c -+++ b/plat/rockchip/rk3588/drivers/pmu/pmu.c -@@ -136,6 +136,22 @@ static __pmusramfunc void dsu_restore_ea - - static __pmusramfunc void ddr_resume(void) - { -+ /* check the crypto function had been enabled or not */ -+ if (mmio_read_32(DSUSGRF_BASE + DSU_SGRF_SOC_CON(4)) & BIT(4)) { -+ /* enable the crypto function */ -+ mmio_write_32(DSUSGRF_BASE + DSU_SGRF_SOC_CON(4), BITS_WITH_WMASK(0, 0x1, 4)); -+ dsb(); -+ isb(); -+ -+ __asm__ volatile ("mov x0, #3\n" -+ "dsb sy\n" -+ "msr rmr_el3, x0\n" -+ "1:\n" -+ "isb\n" -+ "wfi\n" -+ "b 1b\n"); -+ } -+ - dsu_restore_early(); - } - -@@ -1437,3 +1453,66 @@ void plat_rockchip_pmu_init(void) - - pm_reg_rgns_init(); - } -+ -+void bl31_entrypoint(void); -+ -+static uint64_t boot_cpu_save[4]; -+ -+void plat_rockchip_bl31_entrypoint_set_sp(uint64_t reg0, uint64_t reg1, -+ uint64_t reg2, uint64_t reg3) -+{ -+ __asm__ volatile("mov x10, %0\n" : : "r" (reg0) : ); -+ -+ reg0 = PSRAM_SP_TOP; -+ __asm__ volatile("mov sp, %0\n" : : "r" (reg0) : ); -+ -+ __asm__ volatile("mov %0, x10\n" : "=r" (reg0) : :); -+} -+ -+void plat_rockchip_bl31_entrypoint(uint64_t reg0, uint64_t reg1, -+ uint64_t reg2, uint64_t reg3) -+{ -+ uint32_t tmp = mmio_read_32(DSUSGRF_BASE + DSU_SGRF_SOC_CON(4)); -+ -+ /* check the crypto function had been enabled or not */ -+ if (tmp & BIT(4)) { -+ /* save x0~x3 */ -+ boot_cpu_save[0] = reg0; -+ boot_cpu_save[1] = reg1; -+ boot_cpu_save[2] = reg2; -+ boot_cpu_save[3] = reg3; -+ -+ /* enable the crypto function */ -+ mmio_write_32(DSUSGRF_BASE + DSU_SGRF_SOC_CON(4), BITS_WITH_WMASK(0, 0x1, 4)); -+ -+ /* remap pmusram to 0xffff0000 */ -+ mmio_write_32(PMU0SGRF_BASE + PMU0_SGRF_SOC_CON(2), 0x00030001); -+ dsb(); -+ psram_sleep_cfg->pm_flag = PM_WARM_BOOT_BIT; -+ cpuson_flags[0] = PMU_CPU_HOTPLUG; -+ cpuson_entry_point[0] = (uintptr_t)bl31_entrypoint; -+ dsb(); -+ -+ /* to enable the crypto function, must reset the core0 */ -+ __asm__ volatile ("mov x0, #3\n" -+ "dsb sy\n" -+ "msr rmr_el3, x0\n" -+ "1:\n" -+ "isb\n" -+ "wfi\n" -+ "b 1b\n"); -+ } else { -+ /* remap bootrom to 0xffff0000 */ -+ mmio_write_32(PMU0SGRF_BASE + PMU0_SGRF_SOC_CON(2), 0x00030000); -+ -+ /* -+ * the crypto function has been enabled, -+ * restore the x0~x3. -+ */ -+ __asm__ volatile ("ldr x0, [%0]\n" -+ "ldr x1, [%0 , 0x8]\n" -+ "ldr x2, [%0 , 0x10]\n" -+ "ldr x3, [%0 , 0x18]\n" -+ : : "r" (&boot_cpu_save[0])); -+ } -+} ---- a/plat/rockchip/rk3588/platform.mk -+++ b/plat/rockchip/rk3588/platform.mk -@@ -96,3 +96,4 @@ ENABLE_SPE_FOR_LOWER_ELS := 0 - - $(eval $(call add_define,PLAT_EXTRA_LD_SCRIPT)) - $(eval $(call add_define,PLAT_SKIP_DFS_TLB_DCACHE_MAINTENANCE)) -+$(eval $(call add_define,PLAT_RK_BL31_ENTRYPOINT))