mirror of
https://github.com/coolsnowwolf/lede.git
synced 2025-04-15 18:03:30 +00:00
1478 lines
43 KiB
Diff
1478 lines
43 KiB
Diff
From da1c5f6534eb6e125c25d517435022140c5696a7 Mon Sep 17 00:00:00 2001
|
|
From: Shengfei Xu <xsf@rock-chips.com>
|
|
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 <xsf@rock-chips.com>
|
|
---
|
|
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 <common/debug.h>
|
|
+#include <drivers/delay_timer.h>
|
|
+#include <platform_def.h>
|
|
+#include <plat_private.h>
|
|
+
|
|
+#include <otp.h>
|
|
+#include <rk3568_clk.h>
|
|
+#include <rk3568_def.h>
|
|
+#include <soc.h>
|
|
+
|
|
+/* 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 <cpus_on_fixed_addr.h>
|
|
#include <plat_private.h>
|
|
+#include <rk3568_clk.h>
|
|
#include <soc.h>
|
|
|
|
/*
|
|
@@ -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 <platform_def.h>
|
|
+
|
|
+#include <drivers/delay_timer.h>
|
|
+#include <drivers/scmi.h>
|
|
+
|
|
+#include <plat_private.h>
|
|
+#include <scmi_clock.h>
|
|
+#include <rk3568_clk.h>
|
|
+#include <otp.h>
|
|
+
|
|
+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 <mmio.h>
|
|
#include <platform_def.h>
|
|
|
|
+#include <plat_private.h>
|
|
+#include <rk3568_clk.h>
|
|
#include <soc.h>
|
|
|
|
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 <common/debug.h>
|
|
#include <common/runtime_svc.h>
|
|
-#include <lib/mmio.h>
|
|
-#include <platform_def.h>
|
|
+#include <drivers/scmi-msg.h>
|
|
|
|
#include <plat_sip_calls.h>
|
|
#include <rockchip_sip_svc.h>
|
|
@@ -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__ */
|