Attempt cm3588 support

This commit is contained in:
Timmy Welch 2024-07-17 23:36:40 -07:00
parent 626d2897a4
commit ea66aa9554
52 changed files with 27495 additions and 27 deletions
atf.patches
boot.scr
cmd
gokr-build-kernel
gokr-build-uboot
gokr-rebuild-kernel
gokr-rebuild-uboot
kernel.patches
0001-dt-bindings-arm-rockchip-Add-FriendlyElec-CM3588-NAS.patch0001-general-add-overlay-support.patch0002-arm64-dts-rockchip-Add-FriendlyElec-CM3588-NAS-board.patch0010-fix-clk-divisions.patch0011-irqchip-fix-its-timeout-issue.patch0012-fix-initial-PERST-GPIO-value.patch0022-RK3588-Add-Thermal-and-CpuFreq-Support.patch0024-RK3588-Add-Crypto-Support.patch0025-RK3588-Add-HW-RNG-Support.patch0026-RK3588-Add-VPU121-H.264-Decoder-Support.patch0027-RK3588-Add-rkvdec2-Support-v3.patch0028-media-v4l2-core-Initialize-h264-frame_mbs_only_flag-.patch0138-arm64-dts-rockchip-Add-HDMI0-bridge-to-rk3588.patch0139-arm64-dts-rockchip-Enable-HDMI0-PHY-clk-provider-on-.patch0144-phy-phy-rockchip-samsung-hdptx-Add-FRL-EARC-support.patch0145-phy-phy-rockchip-samsung-hdptx-Add-clock-provider.patch0146-drm-rockchip-vop2-Improve-display-modes-handling-on-.patch0147-arm64-dts-rockchip-rk3588-add-RGA2-node.patch0161-drm-bridge-synopsys-Add-initial-support-for-DW-HDMI-Controller.patch0162-drm-bridge-synopsys-Fix-HDMI-Controller.patch0170-drm-rockchip-vop2-add-clocks-reset-support.patch0801-wireless-add-bcm43752.patch0802-wireless-add-clk-property.patch1010-arm64-dts-rock-5b-Slow-down-emmc-to-hs200-and-add-ts.patch1011-board-rock-5b-arm64-dts-enable-spi-flash.patch1012-arm64-dts-rockchip-Enable-HDMI0-on-rock-5b.patch1014-arm64-dts-rockchip-Make-use-of-HDMI0-PHY-PLL-on-rock5b.patch1015-board-rock5b-automatic-fan-control.patch1020-Add-HDMI-and-VOP2-to-Rock-5A.patch1021-arch-arm64-dts-enable-gpu-node-for-rock-5a.patch1021-arm64-dts-Add-missing-nodes-to-Orange-Pi-5-Plus.patch1023-arm64-dts-rockchip-add-PCIe-for-M.2-E-Key-to-rock-5a.patch1031-arm64-dts-rockchip-Add-HDMI-support-to-ArmSoM-Sige7.patch1032-arm64-dts-rockchip-Add-ap6275p-wireless-support-to-A.patch1040-board-khadas-edge2-add-nodes.patch1041-board-khadas-edge2-mcu.patch1051-arm64-dts-rockchip-Add-NanoPC-T6-SPI-Flash.patch
rk3328-rock64.dtbrk3588-friendlyelec-cm3588-nas.dtbu-boot-rockchip.bin
uboot.patches
vmlinuz

File diff suppressed because it is too large Load Diff

@ -0,0 +1,465 @@
From 3bd5d90889173031e1a4177835225e3f9ffd6e49 Mon Sep 17 00:00:00 2001
From: XiaoDong Huang <derrick.huang@rock-chips.com>
Date: Sun, 25 Jun 2023 17:38:13 +0800
Subject: [PATCH] feat(rockchip): support SCMI for clock/reset domain
Signed-off-by: XiaoDong Huang <derrick.huang@rock-chips.com>
Change-Id: I5b983877a5b4e8acababbf7e0a3e2725e6479e08
---
diff --git a/plat/rockchip/common/include/rockchip_sip_svc.h b/plat/rockchip/common/include/rockchip_sip_svc.h
index 340d653..8836f9b 100644
--- a/plat/rockchip/common/include/rockchip_sip_svc.h
+++ b/plat/rockchip/common/include/rockchip_sip_svc.h
@@ -11,6 +11,7 @@
#define SIP_SVC_CALL_COUNT 0x8200ff00
#define SIP_SVC_UID 0x8200ff01
#define SIP_SVC_VERSION 0x8200ff03
+#define RK_SIP_SCMI_AGENT0 0x82000010
/* rockchip SiP Service Calls version numbers */
#define RK_SIP_SVC_VERSION_MAJOR 0x0
diff --git a/plat/rockchip/common/scmi/scmi.c b/plat/rockchip/common/scmi/scmi.c
new file mode 100644
index 0000000..23ea991
--- /dev/null
+++ b/plat/rockchip/common/scmi/scmi.c
@@ -0,0 +1,88 @@
+/*
+ * Copyright (c) 2024, Rockchip, Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+#include <string.h>
+
+#include <plat_scmi_def.h>
+
+#include <drivers/scmi-msg.h>
+#include <drivers/scmi.h>
+#include <lib/utils.h>
+#include <lib/utils_def.h>
+
+#define MAX_PROTOCOL_IN_LIST 8U
+
+static const char vendor[] = "rockchip";
+static const char sub_vendor[] = "";
+
+#pragma weak rockchip_scmi_protocol_table
+
+const uint8_t rockchip_scmi_protocol_table[1][MAX_PROTOCOL_IN_LIST] = {
+ { SCMI_PROTOCOL_ID_CLOCK,
+ SCMI_PROTOCOL_ID_RESET_DOMAIN,
+ 0
+ }
+};
+
+const char *plat_scmi_vendor_name(void)
+{
+ return vendor;
+}
+
+const char *plat_scmi_sub_vendor_name(void)
+{
+ return sub_vendor;
+}
+
+size_t plat_scmi_protocol_count(void)
+{
+ unsigned int count = 0U;
+ const uint8_t *protocol_list = rockchip_scmi_protocol_table[0];
+
+ while (protocol_list[count])
+ count++;
+
+ return count;
+}
+
+const uint8_t *plat_scmi_protocol_list(unsigned int agent_id)
+{
+ assert(agent_id < ARRAY_SIZE(rockchip_scmi_protocol_table));
+
+ return rockchip_scmi_protocol_table[agent_id];
+}
+
+static struct scmi_msg_channel scmi_channel[] = {
+ [0] = {
+ .shm_addr = SMT_BUFFER0_BASE,
+ .shm_size = SMT_BUF_SLOT_SIZE,
+ },
+
+#ifdef SMT_BUFFER1_BASE
+ [1] = {
+ .shm_addr = SMT_BUFFER1_BASE,
+ .shm_size = SMT_BUF_SLOT_SIZE,
+ },
+#endif
+};
+
+struct scmi_msg_channel *plat_scmi_get_channel(unsigned int agent_id)
+{
+ assert(agent_id < ARRAY_SIZE(scmi_channel));
+
+ return &scmi_channel[agent_id];
+}
+
+#pragma weak rockchip_init_scmi_server
+
+void rockchip_init_scmi_server(void)
+{
+ size_t i;
+
+ for (i = 0U; i < ARRAY_SIZE(scmi_channel); i++)
+ scmi_smt_init_agent_channel(&scmi_channel[i]);
+}
diff --git a/plat/rockchip/common/scmi/scmi_clock.c b/plat/rockchip/common/scmi/scmi_clock.c
new file mode 100644
index 0000000..4921d49
--- /dev/null
+++ b/plat/rockchip/common/scmi/scmi_clock.c
@@ -0,0 +1,157 @@
+/*
+ * Copyright (c) 2024, Rockchip, Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <drivers/scmi-msg.h>
+#include <drivers/scmi.h>
+
+#include "scmi_clock.h"
+
+#pragma weak rockchip_scmi_clock_count
+#pragma weak rockchip_scmi_get_clock
+
+size_t rockchip_scmi_clock_count(unsigned int agent_id __unused)
+{
+ return 0;
+}
+
+rk_scmi_clock_t *rockchip_scmi_get_clock(uint32_t agent_id __unused,
+ uint32_t scmi_id __unused)
+{
+ return NULL;
+}
+
+size_t plat_scmi_clock_count(unsigned int agent_id)
+{
+ return rockchip_scmi_clock_count(agent_id);
+}
+
+const char *plat_scmi_clock_get_name(unsigned int agent_id,
+ unsigned int scmi_id)
+{
+ rk_scmi_clock_t *clock;
+
+ clock = rockchip_scmi_get_clock(agent_id, scmi_id);
+ if (clock == 0)
+ return NULL;
+
+ return clock->name;
+}
+
+int32_t plat_scmi_clock_rates_array(unsigned int agent_id,
+ unsigned int scmi_id,
+ unsigned long *rates,
+ size_t *nb_elts,
+ uint32_t start_idx)
+{
+ uint32_t i;
+ unsigned long *rate_table;
+ rk_scmi_clock_t *clock;
+
+ clock = rockchip_scmi_get_clock(agent_id, scmi_id);
+ if (clock == 0)
+ return SCMI_NOT_FOUND;
+
+ rate_table = clock->rate_table;
+ if (rate_table == 0)
+ return SCMI_NOT_SUPPORTED;
+
+ if (rates == 0) {
+ *nb_elts = clock->rate_cnt;
+ goto out;
+ }
+
+ if (start_idx + *nb_elts > clock->rate_cnt)
+ return SCMI_OUT_OF_RANGE;
+
+ for (i = 0; i < *nb_elts; i++)
+ rates[i] = rate_table[start_idx + i];
+
+out:
+ return SCMI_SUCCESS;
+}
+
+int32_t plat_scmi_clock_rates_by_step(unsigned int agent_id __unused,
+ unsigned int scmi_id __unused,
+ unsigned long *steps __unused)
+{
+ return SCMI_NOT_SUPPORTED;
+}
+
+unsigned long plat_scmi_clock_get_rate(unsigned int agent_id,
+ unsigned int scmi_id)
+{
+ rk_scmi_clock_t *clock;
+ unsigned long rate = 0;
+
+ clock = rockchip_scmi_get_clock(agent_id, scmi_id);
+ if (clock == 0)
+ return 0;
+
+ if (clock->clk_ops && clock->clk_ops->get_rate)
+ rate = clock->clk_ops->get_rate(clock);
+
+ /* return cur_rate if no get_rate ops or get_rate return 0 */
+ if (rate == 0)
+ rate = clock->cur_rate;
+
+ return rate;
+}
+
+int32_t plat_scmi_clock_set_rate(unsigned int agent_id,
+ unsigned int scmi_id,
+ unsigned long rate)
+{
+ rk_scmi_clock_t *clock;
+ int32_t status = 0;
+
+ clock = rockchip_scmi_get_clock(agent_id, scmi_id);
+ if (clock == 0)
+ return SCMI_NOT_FOUND;
+
+ if (clock->clk_ops && clock->clk_ops->set_rate) {
+ status = clock->clk_ops->set_rate(clock, rate);
+ if (status == SCMI_SUCCESS)
+ clock->cur_rate = rate;
+ } else {
+ status = SCMI_NOT_SUPPORTED;
+ }
+
+ return status;
+}
+
+int32_t plat_scmi_clock_get_state(unsigned int agent_id,
+ unsigned int scmi_id)
+{
+ rk_scmi_clock_t *clock;
+
+ clock = rockchip_scmi_get_clock(agent_id, scmi_id);
+ if (clock == 0)
+ return 0;
+
+ return clock->enable;
+}
+
+int32_t plat_scmi_clock_set_state(unsigned int agent_id,
+ unsigned int scmi_id,
+ bool enable_not_disable)
+{
+ rk_scmi_clock_t *clock;
+ int32_t status = 0;
+
+ clock = rockchip_scmi_get_clock(agent_id, scmi_id);
+ if (clock == 0)
+ return SCMI_NOT_FOUND;
+
+ if (clock->clk_ops && clock->clk_ops->set_status) {
+ status = clock->clk_ops->set_status(clock, enable_not_disable);
+ if (status == SCMI_SUCCESS)
+ clock->enable = enable_not_disable;
+ } else {
+ status = SCMI_NOT_SUPPORTED;
+ }
+
+ return status;
+}
diff --git a/plat/rockchip/common/scmi/scmi_clock.h b/plat/rockchip/common/scmi/scmi_clock.h
new file mode 100644
index 0000000..e640fe1
--- /dev/null
+++ b/plat/rockchip/common/scmi/scmi_clock.h
@@ -0,0 +1,50 @@
+/*
+ * Copyright (c) 2024, Rockchip, Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef RK_SCMI_CLOCK_H
+#define RK_SCMI_CLOCK_H
+
+#include <stdint.h>
+
+#include <common.h>
+
+struct rk_scmi_clock;
+
+struct rk_clk_ops {
+ unsigned long (*get_rate)(struct rk_scmi_clock *clock);
+ int (*set_rate)(struct rk_scmi_clock *clock, unsigned long rate);
+ int (*set_status)(struct rk_scmi_clock *clock, bool status);
+};
+
+typedef struct rk_scmi_clock {
+ char name[SCMI_CLOCK_NAME_LENGTH_MAX];
+ uint8_t enable;
+ int8_t is_security;
+ uint32_t id;
+ uint32_t rate_cnt;
+ uint64_t cur_rate;
+ uint32_t enable_count;
+ const struct rk_clk_ops *clk_ops;
+ unsigned long *rate_table;
+} rk_scmi_clock_t;
+
+/*
+ * Return number of clock controllers for an agent
+ * @agent_id: SCMI agent ID
+ * Return number of clock controllers
+ */
+size_t rockchip_scmi_clock_count(unsigned int agent_id);
+
+/*
+ * Get rk_scmi_clock_t point
+ * @agent_id: SCMI agent ID
+ * @scmi_id: SCMI clock ID
+ * Return a rk_scmi_clock_t point
+ */
+rk_scmi_clock_t *rockchip_scmi_get_clock(uint32_t agent_id,
+ uint32_t scmi_id);
+
+#endif /* RK_SCMI_CLOCK_H */
diff --git a/plat/rockchip/common/scmi/scmi_rstd.c b/plat/rockchip/common/scmi/scmi_rstd.c
new file mode 100644
index 0000000..404d85e
--- /dev/null
+++ b/plat/rockchip/common/scmi/scmi_rstd.c
@@ -0,0 +1,74 @@
+/*
+ * Copyright (c) 2024, Rockchip, Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <drivers/scmi-msg.h>
+#include <drivers/scmi.h>
+
+#include "scmi_rstd.h"
+
+#pragma weak rockchip_scmi_rstd_count
+#pragma weak rockchip_scmi_get_rstd
+
+size_t rockchip_scmi_rstd_count(unsigned int agent_id __unused)
+{
+ return 0U;
+}
+
+rk_scmi_rstd_t *rockchip_scmi_get_rstd(unsigned int agent_id __unused,
+ unsigned int scmi_id __unused)
+{
+ return NULL;
+}
+
+size_t plat_scmi_rstd_count(unsigned int agent_id)
+{
+ return rockchip_scmi_rstd_count(agent_id);
+}
+
+const char *plat_scmi_rstd_get_name(unsigned int agent_id,
+ unsigned int scmi_id)
+{
+ rk_scmi_rstd_t *rstd;
+
+ rstd = rockchip_scmi_get_rstd(agent_id, scmi_id);
+ if (rstd == 0)
+ return NULL;
+
+ return rstd->name;
+}
+
+int32_t plat_scmi_rstd_autonomous(unsigned int agent_id,
+ unsigned int scmi_id,
+ unsigned int state)
+{
+ rk_scmi_rstd_t *rstd;
+
+ rstd = rockchip_scmi_get_rstd(agent_id, scmi_id);
+ if (rstd == 0)
+ return SCMI_NOT_FOUND;
+
+ if ((rstd->rstd_ops && rstd->rstd_ops->reset_auto) != 0)
+ return rstd->rstd_ops->reset_auto(rstd, state);
+ else
+ return SCMI_NOT_SUPPORTED;
+}
+
+int32_t plat_scmi_rstd_set_state(unsigned int agent_id,
+ unsigned int scmi_id,
+ bool assert_not_deassert)
+{
+ rk_scmi_rstd_t *rstd;
+
+ rstd = rockchip_scmi_get_rstd(agent_id, scmi_id);
+ if (rstd == 0)
+ return SCMI_NOT_FOUND;
+
+ if ((rstd->rstd_ops && rstd->rstd_ops->reset_explicit) != 0)
+ return rstd->rstd_ops->reset_explicit(rstd,
+ assert_not_deassert);
+ else
+ return SCMI_NOT_SUPPORTED;
+}
diff --git a/plat/rockchip/common/scmi/scmi_rstd.h b/plat/rockchip/common/scmi/scmi_rstd.h
new file mode 100644
index 0000000..1af5881
--- /dev/null
+++ b/plat/rockchip/common/scmi/scmi_rstd.h
@@ -0,0 +1,45 @@
+/*
+ * Copyright (c) 2024, Rockchip, Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef RK_SCMI_RESET_DOMAIN_H
+#define RK_SCMI_RESET_DOMAIN_H
+
+#include <stdint.h>
+
+#include <common.h>
+
+struct rk_scmi_rstd;
+
+struct rk_scmi_rstd_ops {
+ int (*reset_auto)(struct rk_scmi_rstd *rstd, uint32_t state);
+ int (*reset_explicit)(struct rk_scmi_rstd *rstd, bool assert_not_deassert);
+};
+
+typedef struct rk_scmi_rstd {
+ char name[SCMI_RESET_DOMAIN_ATTR_NAME_SZ];
+ uint32_t id;
+ uint32_t attribute;
+ uint32_t latency;
+ struct rk_scmi_rstd_ops *rstd_ops;
+} rk_scmi_rstd_t;
+
+/*
+ * Return number of reset domain for an agent
+ * @agent_id: SCMI agent ID
+ * Return number of reset domain
+ */
+size_t rockchip_scmi_rstd_count(unsigned int agent_id);
+
+/*
+ * Get rk_scmi_rstd_t point
+ * @agent_id: SCMI agent ID
+ * @scmi_id: SCMI rstd ID
+ * Return a rk_scmi_rstd_t point
+ */
+rk_scmi_rstd_t *rockchip_scmi_get_rstd(unsigned int agent_id,
+ unsigned int scmi_id);
+
+#endif /* RK_SCMI_RESET_DOMAIN_H */

@ -0,0 +1,139 @@
From c805c14c1026b3ae5445e211c2101c60cd76ad0e Mon Sep 17 00:00:00 2001
From: XiaoDong Huang <derrick.huang@rock-chips.com>
Date: Mon, 17 Jun 2024 10:55:27 +0800
Subject: [PATCH] feat(rk3588): enable crypto function
Signed-off-by: XiaoDong Huang <derrick.huang@rock-chips.com>
Change-Id: Ifee2eab55d9c13cef5f15926fb80016845e2a66d
---
diff --git a/bl31/aarch64/bl31_entrypoint.S b/bl31/aarch64/bl31_entrypoint.S
index dfb14e9..6d1e11e 100644
--- 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.
* ---------------------------------------------------------------
diff --git a/plat/rockchip/rk3588/drivers/pmu/pmu.c b/plat/rockchip/rk3588/drivers/pmu/pmu.c
index 83d6cad..a7c1c47 100644
--- a/plat/rockchip/rk3588/drivers/pmu/pmu.c
+++ b/plat/rockchip/rk3588/drivers/pmu/pmu.c
@@ -136,6 +136,22 @@
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 @@
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]));
+ }
+}
diff --git a/plat/rockchip/rk3588/platform.mk b/plat/rockchip/rk3588/platform.mk
index 07eda40..3d9dc59 100644
--- a/plat/rockchip/rk3588/platform.mk
+++ b/plat/rockchip/rk3588/platform.mk
@@ -96,3 +96,4 @@
$(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))

@ -0,0 +1,293 @@
From eb5dfe2a76180d85f33fa2e7ed5131852a003dac Mon Sep 17 00:00:00 2001
From: XiaoDong Huang <derrick.huang@rock-chips.com>
Date: Sun, 25 Jun 2023 19:23:07 +0800
Subject: [PATCH] feat(rockchip): add some pm helpers functions
Some power domains will be powered off when the system suspends,
so registers in the power domain need to be save/restore.
Now we add some functions to save/restore registers easily:
use rockchip_alloc_region_mem to allocate memory to save/restore registers in regions;
use rockchip_reg_rgn_save to save registers regions in regions;
use rockchip_reg_rgn_restore to restore registers in regions;
use rockchip_dump_reg_rgns to dump registers in regions;
Signed-off-by: XiaoDong Huang <derrick.huang@rock-chips.com>
Change-Id: I34f909a103fbe2d51456e1d92df0be570e35e2a1
---
diff --git a/plat/rockchip/common/include/plat_pm_helpers.h b/plat/rockchip/common/include/plat_pm_helpers.h
new file mode 100644
index 0000000..2204a65
--- /dev/null
+++ b/plat/rockchip/common/include/plat_pm_helpers.h
@@ -0,0 +1,51 @@
+/*
+ * Copyright (c) 2024, Rockchip, Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef PLAT_PM_HELPERS_H
+#define PLAT_PM_HELPERS_H
+
+#include <stdint.h>
+
+/**
+ * Use this macro to define a register region.
+ * start: start offset from the base address.
+ * end: end offset from the base address.
+ * stride: stride of registers in region.
+ * base: base address of registers in region.
+ * wmsk: write mask of registers in region.
+ */
+#define REG_REGION(_start, _end, _stride, _base, _wmsk) \
+{ \
+ .start = (_base) + (_start), \
+ .end = (_base) + (_end), \
+ .stride = _stride, \
+ .wmsk = _wmsk \
+}
+
+struct reg_region {
+ /* Start address of region */
+ uint32_t start;
+ /* End address of region */
+ uint32_t end;
+ /* Stride of registers in region */
+ uint32_t stride;
+ /* Write mask of registers in region */
+ uint32_t wmsk;
+ /* Buffer to save/restore registers in region */
+ uint32_t *buf;
+};
+
+void rockchip_alloc_region_mem(struct reg_region *rgns, uint32_t rgn_num);
+void rockchip_reg_rgn_save(struct reg_region *rgns, uint32_t rgn_num);
+void rockchip_reg_rgn_restore(struct reg_region *rgns, uint32_t rgn_num);
+void rockchip_reg_rgn_restore_reverse(struct reg_region *rgns, uint32_t rgn_num);
+void rockchip_regs_dump(uint32_t base,
+ uint32_t start_offset,
+ uint32_t end_offset,
+ uint32_t stride);
+void rockchip_dump_reg_rgns(struct reg_region *rgns, uint32_t rgn_num);
+
+#endif /* PLAT_PM_HELPERS_H */
diff --git a/plat/rockchip/common/plat_pm_helpers.c b/plat/rockchip/common/plat_pm_helpers.c
new file mode 100644
index 0000000..191b0ca
--- /dev/null
+++ b/plat/rockchip/common/plat_pm_helpers.c
@@ -0,0 +1,213 @@
+/*
+ * Copyright (c) 2024, Rockchip, Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+#include <errno.h>
+
+#include <arch_helpers.h>
+#include <bl31/bl31.h>
+#include <common/debug.h>
+#include <drivers/console.h>
+#include <drivers/delay_timer.h>
+#include <lib/mmio.h>
+#include <plat/common/platform.h>
+#include <platform_def.h>
+
+#include <plat_pm_helpers.h>
+
+#define ROCKCHIP_PM_REG_REGION_MEM_LEN (ROCKCHIP_PM_REG_REGION_MEM_SIZE / sizeof(uint32_t))
+
+/* REG region */
+#define RGN_LEN(_rgn) (((_rgn)->end - (_rgn)->start) / (_rgn)->stride + 1)
+
+#ifndef ROCKCHIP_PM_REG_REGION_MEM_SIZE
+#define ROCKCHIP_PM_REG_REGION_MEM_SIZE 0
+#endif
+
+#ifdef ROCKCHIP_REG_RGN_MEM_BASE
+static uint32_t *region_mem = (uint32_t *)ROCKCHIP_REG_RGN_MEM_BASE;
+#else
+static uint32_t region_mem[ROCKCHIP_PM_REG_REGION_MEM_LEN];
+#endif
+
+static int region_mem_idx;
+
+static int alloc_region_mem(uint32_t *buf, int max_len,
+ struct reg_region *rgns, uint32_t rgn_num)
+{
+ int i;
+ int total_len = 0, len = 0;
+ struct reg_region *r = rgns;
+
+ assert(buf && rgns && rgn_num);
+
+ for (i = 0; i < rgn_num; i++, r++) {
+ if (total_len < max_len)
+ r->buf = &buf[total_len];
+
+ len = RGN_LEN(r);
+ total_len += len;
+ }
+
+ if (total_len > max_len) {
+ ERROR("%s The buffer remain length:%d is too small for region:0x%x, at least %d\n",
+ __func__, max_len, rgns[0].start, total_len);
+ panic();
+ }
+
+ return total_len;
+}
+
+/**
+ * Alloc memory to reg_region->buf from region_mem.
+ * @rgns - struct reg_region array.
+ * @rgn_num - struct reg_region array length.
+ */
+void rockchip_alloc_region_mem(struct reg_region *rgns, uint32_t rgn_num)
+{
+ int max_len = 0, len;
+
+ assert(rgns && rgn_num);
+
+ max_len = ROCKCHIP_PM_REG_REGION_MEM_LEN - region_mem_idx;
+
+ len = alloc_region_mem(region_mem + region_mem_idx, max_len,
+ rgns, rgn_num);
+
+ region_mem_idx += len;
+}
+
+/**
+ * Save (reg_region->start ~ reg_region->end) to reg_region->buf.
+ * @rgns - struct reg_region array.
+ * @rgn_num - struct reg_region array length.
+ */
+void rockchip_reg_rgn_save(struct reg_region *rgns, uint32_t rgn_num)
+{
+ struct reg_region *r;
+ uint32_t addr;
+ int i, j;
+
+ assert(rgns && rgn_num);
+
+ for (i = 0; i < rgn_num; i++) {
+ r = &rgns[i];
+ for (j = 0, addr = r->start; addr <= r->end; addr += r->stride, j++)
+ r->buf[j] = mmio_read_32(addr);
+ }
+}
+
+/**
+ * Restore reg_region->buf to (reg_region->start ~ reg_region->end).
+ * @rgns - struct reg_region array.
+ * @rgn_num - struct reg_region array length.
+ */
+void rockchip_reg_rgn_restore(struct reg_region *rgns, uint32_t rgn_num)
+{
+ struct reg_region *r;
+ uint32_t addr;
+ int i, j;
+
+ assert(rgns && rgn_num);
+
+ for (i = 0; i < rgn_num; i++) {
+ r = &rgns[i];
+ for (j = 0, addr = r->start; addr <= r->end; addr += r->stride, j++)
+ mmio_write_32(addr, r->buf[j] | r->wmsk);
+
+ dsb();
+ }
+}
+
+/**
+ * Restore reg_region->buf to (reg_region->start ~ reg_region->end) reversely.
+ * @rgns - struct reg_region array.
+ * @rgn_num - struct reg_region array length.
+ */
+void rockchip_reg_rgn_restore_reverse(struct reg_region *rgns, uint32_t rgn_num)
+{
+ struct reg_region *r;
+ uint32_t addr;
+ int i, j;
+
+ assert(rgns && rgn_num);
+
+ for (i = rgn_num - 1; i >= 0; i--) {
+ r = &rgns[i];
+ j = RGN_LEN(r) - 1;
+ for (addr = r->end; addr >= r->start; addr -= r->stride, j--)
+ mmio_write_32(addr, r->buf[j] | r->wmsk);
+
+ dsb();
+ }
+}
+
+static void rockchip_print_hex(uint32_t val)
+{
+ int i;
+ unsigned char tmp;
+
+ putchar('0');
+ putchar('x');
+ for (i = 0; i < 8; val <<= 4, ++i) {
+ tmp = (val & 0xf0000000) >> 28;
+ if (tmp < 10)
+ putchar('0' + tmp);
+ else
+ putchar('a' + tmp - 10);
+ }
+}
+
+/**
+ * Dump registers (base + start_offset ~ base + end_offset)
+ * @base - the base addr of the register.
+ * @start_offset - the start offset to dump.
+ * @end_offset - the end offset to dump.
+ * @stride - the stride of the registers.
+ */
+void rockchip_regs_dump(uint32_t base,
+ uint32_t start_offset,
+ uint32_t end_offset,
+ uint32_t stride)
+{
+ uint32_t i;
+
+ for (i = start_offset; i <= end_offset; i += stride) {
+ if ((i - start_offset) % 16 == 0) {
+ putchar('\n');
+ rockchip_print_hex(base + i);
+ putchar(':');
+ putchar(' ');
+ putchar(' ');
+ putchar(' ');
+ putchar(' ');
+ }
+ rockchip_print_hex(mmio_read_32(base + i));
+ putchar(' ');
+ putchar(' ');
+ putchar(' ');
+ putchar(' ');
+ }
+ putchar('\n');
+}
+
+/**
+ * Dump reg regions
+ * @rgns - struct reg_region array.
+ * @rgn_num - struct reg_region array length.
+ */
+void rockchip_dump_reg_rgns(struct reg_region *rgns, uint32_t rgn_num)
+{
+ struct reg_region *r;
+ int i;
+
+ assert(rgns && rgn_num);
+
+ for (i = 0; i < rgn_num; i++) {
+ r = &rgns[i];
+ rockchip_regs_dump(0x0, r->start, r->end, r->stride);
+ }
+}

BIN
boot.scr

Binary file not shown.

@ -19,7 +19,7 @@ import (
var configContents []byte
// see https://www.kernel.org/releases.json
var latest = "https://cdn.kernel.org/pub/linux/kernel/v6.x/linux-6.9.8.tar.xz"
var latest = "https://git.kernel.org/torvalds/t/linux-6.10-rc7.tar.gz"
func downloadKernel() error {
out, err := os.Create(filepath.Base(latest))
@ -42,7 +42,7 @@ func downloadKernel() error {
}
func applyPatches(srcdir string) error {
patches, err := filepath.Glob("*.patch")
patches, err := filepath.Glob("kernel.patches/*.patch")
if err != nil {
return err
}
@ -152,7 +152,7 @@ func main() {
log.Fatalf("untar: %v", err)
}
srcdir := strings.TrimSuffix(filepath.Base(latest), ".tar.xz")
srcdir := strings.TrimSuffix(filepath.Base(latest), ".tar.gz")
log.Printf("applying patches")
if err := applyPatches(srcdir); err != nil {
@ -172,7 +172,7 @@ func main() {
log.Fatal(err)
}
if err := copyFile("/tmp/buildresult/rk3328-rock64.dtb", "arch/arm64/boot/dts/rockchip/rk3328-rock64.dtb"); err != nil {
if err := copyFile("/tmp/buildresult/rk3588-friendlyelec-cm3588-nas.dtb", "arch/arm64/boot/dts/rockchip/rk3588-friendlyelec-cm3588-nas.dtb"); err != nil {
log.Fatal(err)
}
}

@ -13,15 +13,15 @@ import (
const ubootRev = "fd46ea0e701920eb205c2bce9d527bf0dec10b59"
const ubootTS = 1720219003
const trustedRepoRev = "10eb851f92acc67f7cdb955770e3bdced3026677"
const trustedRepoRev = "c970c1c38f6d06a3e48e00ea7533c0e427311bcb"
const (
uBootRepo = "https://github.com/u-boot/u-boot"
trustedFirmwareRepo = "https://github.com/ARM-software/arm-trusted-firmware"
)
func applyPatches(srcdir string) error {
patches, err := filepath.Glob("*.patch")
func applyPatches(srcdir, t string) error {
patches, err := filepath.Glob(t+".patches/*.patch")
if err != nil {
return err
}
@ -47,7 +47,7 @@ func applyPatches(srcdir string) error {
}
func compile(trustedFirmwareDir string) error {
defconfig := exec.Command("make", "ARCH=arm64", "rock64-rk3328_defconfig")
defconfig := exec.Command("make", "ARCH=arm64", "nanopc-t6-rk3588_defconfig")
defconfig.Stdout = os.Stdout
defconfig.Stderr = os.Stderr
if err := defconfig.Run(); err != nil {
@ -70,7 +70,8 @@ func compile(trustedFirmwareDir string) error {
"ARCH=arm64",
"CROSS_COMPILE=aarch64-linux-gnu-",
"SOURCE_DATE_EPOCH="+strconv.Itoa(ubootTS),
fmt.Sprintf("BL31=%s/build/rk3328/release/bl31/bl31.elf", trustedFirmwareDir),
fmt.Sprintf("BL31=%s/build/rk3588/release/bl31/bl31.elf", trustedFirmwareDir),
fmt.Sprintf("ROCKCHIP_TPL=%s","/usr/src/uboot.patches/rk3588_ddr_lp4_2112MHz_lp5_2400MHz_v1.16.bin"),
)
make.Stdout = os.Stdout
make.Stderr = os.Stderr
@ -140,7 +141,23 @@ func main() {
{"git", "remote", "add", "origin", trustedFirmwareRepo},
{"git", "fetch", "--depth=1", "origin", trustedRepoRev},
{"git", "checkout", "FETCH_HEAD"},
{"make", "SOURCE_DATE_EPOCH=1600000000", "CROSS_COMPILE=aarch64-linux-gnu-", "PLAT=rk3328"},
} {
log.Printf("Running %s", cmd)
cmdObj := exec.Command(cmd[0], cmd[1:]...)
cmdObj.Stdout = os.Stdout
cmdObj.Stderr = os.Stderr
cmdObj.Dir = trustedFirmwareDir
if err := cmdObj.Run(); err != nil {
log.Fatal(err)
}
}
log.Printf("applying patches")
if err := applyPatches(trustedFirmwareDir, "atf"); err != nil {
log.Fatal(err)
}
for _, cmd := range [][]string{
{"make", "SOURCE_DATE_EPOCH=1600000000", "CROSS_COMPILE=aarch64-linux-gnu-", "PLAT=rk3588"},
} {
log.Printf("Running %s", cmd)
cmdObj := exec.Command(cmd[0], cmd[1:]...)
@ -153,7 +170,7 @@ func main() {
}
var bootCmdPath string
if p, err := filepath.Abs("boot.cmd"); err != nil {
if p, err := filepath.Abs("uboot.patches/boot.cmd"); err != nil {
log.Fatal(err)
} else {
bootCmdPath = p
@ -180,7 +197,7 @@ func main() {
}
log.Printf("applying patches")
if err := applyPatches(ubootDir); err != nil {
if err := applyPatches(ubootDir, "uboot"); err != nil {
log.Fatal(err)
}

@ -18,6 +18,7 @@ const dockerFileContents = `
FROM debian:bullseye
RUN apt-get update && apt-get install -y crossbuild-essential-arm64 bc libssl-dev bison flex
RUN mkdir -p /usr/src/kernel.patches
COPY gokr-build-kernel /usr/bin/gokr-build-kernel
{{- range $idx, $path := .Patches }}
@ -41,8 +42,43 @@ var dockerFileTmpl = template.Must(template.New("dockerfile").
Parse(dockerFileContents))
var patchFiles = []string{
// "0001-ODROID-XU4-regulator-s2mps11-call-shutdown-function-.patch",
// "0002-ODROID-XU4-regulator-s2mps11-add-ethernet-power-rese.patch",
"kernel.patches/0001-dt-bindings-arm-rockchip-Add-FriendlyElec-CM3588-NAS.patch",
"kernel.patches/0002-arm64-dts-rockchip-Add-FriendlyElec-CM3588-NAS-board.patch",
"kernel.patches/0010-fix-clk-divisions.patch",
"kernel.patches/0011-irqchip-fix-its-timeout-issue.patch",
"kernel.patches/0012-fix-initial-PERST-GPIO-value.patch",
"kernel.patches/0022-RK3588-Add-Thermal-and-CpuFreq-Support.patch",
"kernel.patches/0024-RK3588-Add-Crypto-Support.patch",
"kernel.patches/0025-RK3588-Add-HW-RNG-Support.patch",
"kernel.patches/0026-RK3588-Add-VPU121-H.264-Decoder-Support.patch",
"kernel.patches/0027-RK3588-Add-rkvdec2-Support-v3.patch",
"kernel.patches/0028-media-v4l2-core-Initialize-h264-frame_mbs_only_flag-.patch",
"kernel.patches/0138-arm64-dts-rockchip-Add-HDMI0-bridge-to-rk3588.patch",
"kernel.patches/0139-arm64-dts-rockchip-Enable-HDMI0-PHY-clk-provider-on-.patch",
"kernel.patches/0144-phy-phy-rockchip-samsung-hdptx-Add-FRL-EARC-support.patch",
"kernel.patches/0145-phy-phy-rockchip-samsung-hdptx-Add-clock-provider.patch",
"kernel.patches/0146-drm-rockchip-vop2-Improve-display-modes-handling-on-.patch",
"kernel.patches/0147-arm64-dts-rockchip-rk3588-add-RGA2-node.patch",
"kernel.patches/0161-drm-bridge-synopsys-Add-initial-support-for-DW-HDMI-Controller.patch",
"kernel.patches/0162-drm-bridge-synopsys-Fix-HDMI-Controller.patch",
"kernel.patches/0170-drm-rockchip-vop2-add-clocks-reset-support.patch",
"kernel.patches/0801-wireless-add-bcm43752.patch",
"kernel.patches/0802-wireless-add-clk-property.patch",
"kernel.patches/1010-arm64-dts-rock-5b-Slow-down-emmc-to-hs200-and-add-ts.patch",
"kernel.patches/1011-board-rock-5b-arm64-dts-enable-spi-flash.patch",
"kernel.patches/1012-arm64-dts-rockchip-Enable-HDMI0-on-rock-5b.patch",
"kernel.patches/1014-arm64-dts-rockchip-Make-use-of-HDMI0-PHY-PLL-on-rock5b.patch",
"kernel.patches/1015-board-rock5b-automatic-fan-control.patch",
"kernel.patches/1020-Add-HDMI-and-VOP2-to-Rock-5A.patch",
"kernel.patches/1021-arch-arm64-dts-enable-gpu-node-for-rock-5a.patch",
"kernel.patches/1021-arm64-dts-Add-missing-nodes-to-Orange-Pi-5-Plus.patch",
"kernel.patches/1023-arm64-dts-rockchip-add-PCIe-for-M.2-E-Key-to-rock-5a.patch",
"kernel.patches/1031-arm64-dts-rockchip-Add-HDMI-support-to-ArmSoM-Sige7.patch",
"kernel.patches/1032-arm64-dts-rockchip-Add-ap6275p-wireless-support-to-A.patch",
"kernel.patches/1040-board-khadas-edge2-add-nodes.patch",
"kernel.patches/1041-board-khadas-edge2-mcu.patch",
"kernel.patches/1051-arm64-dts-rockchip-Add-NanoPC-T6-SPI-Flash.patch",
// "linux-6.10-rc7.tar.gz",
}
func copyFile(dest, src string) error {
@ -135,8 +171,8 @@ func main() {
}
defer os.RemoveAll(tmp)
cmd := exec.Command("go", "install", "github.com/anupcshan/gokrazy-rock64-kernel/cmd/gokr-build-kernel")
cmd.Env = append(os.Environ(), "GOOS=linux", "CGO_ENABLED=0", "GOBIN="+tmp)
cmd := exec.Command("go", "build", "-o", tmp, "github.com/anupcshan/gokrazy-rock64-kernel/cmd/gokr-build-kernel")
cmd.Env = append(os.Environ(), "GOOS=linux", "CGO_ENABLED=0")
cmd.Stderr = os.Stderr
if err := cmd.Run(); err != nil {
log.Fatalf("%v: %v", cmd.Args, err)
@ -157,15 +193,18 @@ func main() {
if err != nil {
log.Fatal(err)
}
dtbPath, err := find("rk3328-rock64.dtb")
dtbPath, err := find("rk3588-friendlyelec-cm3588-nas.dtb")
if err != nil {
log.Fatal(err)
}
err = os.MkdirAll(filepath.Join(tmp, "kernel.patches"), 0750)
if err != nil {
log.Fatal(err)
}
// Copy all files into the temporary directory so that docker
// includes them in the build context.
for _, path := range patchPaths {
if err := copyFile(filepath.Join(tmp, filepath.Base(path)), path); err != nil {
if err := copyFile(filepath.Join(tmp, "kernel.patches", filepath.Base(path)), path); err != nil {
log.Fatal(err)
}
}
@ -239,7 +278,7 @@ func main() {
log.Fatal(err)
}
if err := copyFile(dtbPath, filepath.Join(tmp, "rk3328-rock64.dtb")); err != nil {
if err := copyFile(dtbPath, filepath.Join(tmp, "rk3588-friendlyelec-cm3588-nas.dtb")); err != nil {
log.Fatal(err)
}
}

@ -19,6 +19,8 @@ FROM debian:bookworm
RUN apt-get update && apt-get install -y crossbuild-essential-arm64 bc libssl-dev bison flex git python3 python3-setuptools swig python3-dev python3-pyelftools uuid-dev libgnutls28-dev
COPY gokr-build-uboot /usr/bin/gokr-build-uboot
RUN mkdir -p /usr/src/atf.patches
RUN mkdir -p /usr/src/uboot.patches
{{- range $idx, $path := .Patches }}
COPY {{ $path }} /usr/src/{{ $path }}
{{- end }}
@ -39,7 +41,16 @@ var dockerFileTmpl = template.Must(template.New("dockerfile").
}).
Parse(dockerFileContents))
var patchFiles = []string{"boot.cmd"}
var ubootPatchFiles = []string{
"uboot.patches/boot.cmd",
"uboot.patches/rk3588_ddr_lp4_2112MHz_lp5_2400MHz_v1.16.bin",
}
var atfPatchFiles = []string{
"atf.patches/feat-rk3588-support-rk3588.patch",
"atf.patches/rk3588-enable-crypto-function.patch",
"atf.patches/feat-rockchip-support-SCMI-for-clock-reset-domain.patch",
"atf.patches/rockchip-add-some-pm-helpers-functions.patch",
}
func copyFile(dest, src string) error {
out, err := os.Create(dest)
@ -131,8 +142,8 @@ func main() {
}
defer os.RemoveAll(tmp)
cmd := exec.Command("go", "install", "github.com/anupcshan/gokrazy-rock64-kernel/cmd/gokr-build-uboot")
cmd.Env = append(os.Environ(), "GOOS=linux", "CGO_ENABLED=0", "GOBIN="+tmp)
cmd := exec.Command("go", "build", "-o", tmp, "github.com/anupcshan/gokrazy-rock64-kernel/cmd/gokr-build-uboot")
cmd.Env = append(os.Environ(), "GOOS=linux", "CGO_ENABLED=0")
cmd.Stderr = os.Stderr
if err := cmd.Run(); err != nil {
log.Fatalf("%v: %v", cmd.Args, err)
@ -141,7 +152,8 @@ func main() {
buildPath := filepath.Join(tmp, "gokr-build-uboot")
var patchPaths []string
for _, filename := range patchFiles {
for _, filename := range ubootPatchFiles {
path, err := find(filename)
if err != nil {
log.Fatal(err)
@ -149,10 +161,37 @@ func main() {
patchPaths = append(patchPaths, path)
}
err = os.MkdirAll(filepath.Join(tmp, "uboot.patches"), 0750)
if err != nil {
log.Fatal(err)
}
// Copy all files into the temporary directory so that docker
// includes them in the build context.
for _, path := range patchPaths {
if err := copyFile(filepath.Join(tmp, filepath.Base(path)), path); err != nil {
if err = copyFile(filepath.Join(tmp, "uboot.patches", filepath.Base(path)), path); err != nil {
log.Fatal(err)
}
}
patchPaths = patchPaths[0:0]
for _, filename := range atfPatchFiles {
path, err := find(filename)
if err != nil {
log.Fatal(err)
}
patchPaths = append(patchPaths, path)
}
err = os.MkdirAll(filepath.Join(tmp, "atf.patches"), 0750)
if err != nil {
log.Fatal(err)
}
// Copy all files into the temporary directory so that docker
// includes them in the build context.
for _, path := range patchPaths {
if err := copyFile(filepath.Join(tmp, "atf.patches", filepath.Base(path)), path); err != nil {
log.Fatal(err)
}
}
@ -175,7 +214,7 @@ func main() {
Uid: u.Uid,
Gid: u.Gid,
BuildPath: buildPath,
Patches: patchFiles,
Patches: append(atfPatchFiles, ubootPatchFiles...),
}); err != nil {
log.Fatal(err)
}

@ -0,0 +1,37 @@
From e6b6a82789baf275a597ef312a145c3b4a44da19 Mon Sep 17 00:00:00 2001
From: Sebastian Kropatsch <seb-dev@mail.de>
Date: Sun, 16 Jun 2024 23:48:29 +0200
Subject: [PATCH 1/2] dt-bindings: arm: rockchip: Add FriendlyElec CM3588 NAS
Add devicetree bindings for the FriendlyElec CM3588 NAS board.
The CM3588 NAS by FriendlyElec pairs the CM3588 compute module, based on
the Rockchip RK3588 SoC, with the CM3588 NAS Kit carrier board.
Acked-by: Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
Signed-off-by: Sebastian Kropatsch <seb-dev@mail.de>
---
Documentation/devicetree/bindings/arm/rockchip.yaml | 7 +++++++
1 file changed, 7 insertions(+)
diff --git a/Documentation/devicetree/bindings/arm/rockchip.yaml b/Documentation/devicetree/bindings/arm/rockchip.yaml
index fcf7316ec..86379b8cc 100644
--- a/Documentation/devicetree/bindings/arm/rockchip.yaml
+++ b/Documentation/devicetree/bindings/arm/rockchip.yaml
@@ -236,6 +236,13 @@ properties:
- const: friendlyarm,nanopc-t6
- const: rockchip,rk3588
+ - description: FriendlyElec CM3588-based boards
+ items:
+ - enum:
+ - friendlyarm,cm3588-nas
+ - const: friendlyarm,cm3588
+ - const: rockchip,rk3588
+
- description: GeekBuying GeekBox
items:
- const: geekbuying,geekbox
--
2.45.2

@ -0,0 +1,69 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Paolo Sabatino <paolo.sabatino@gmail.com>
Date: Sun, 2 Jun 2024 21:53:01 +0200
Subject: compile .scr and install overlays in right path
---
scripts/Makefile.dtbinst | 13 +++++++++-
scripts/Makefile.lib | 8 +++++-
2 files changed, 19 insertions(+), 2 deletions(-)
diff --git a/scripts/Makefile.dtbinst b/scripts/Makefile.dtbinst
index 111111111111..222222222222 100644
--- a/scripts/Makefile.dtbinst
+++ b/scripts/Makefile.dtbinst
@@ -33,7 +33,18 @@ endef
$(foreach d, $(sort $(dir $(dtbs))), $(eval $(call gen_install_rules,$(d))))
-dtbs := $(notdir $(dtbs))
+# Very convoluted way to flatten all the device tree
+# directories, but keep the "/overlay/" directory
+
+# topmost directory (ie: from rockchip/overlay/rk322x-emmc.dtbo extracts rockchip)
+topmost_dir = $(firstword $(subst /, ,$(dtbs)))
+# collect dtbs entries which starts with "$topmost_dir/overlay/", then remove "$topmost_dir"
+dtbs_overlays = $(subst $(topmost_dir)/,,$(filter $(topmost_dir)/overlay/%, $(dtbs)))
+# collect the non-overlay dtbs
+dtbs_regular = $(filter-out $(topmost_dir)/overlay/%, $(dtbs))
+# compose the dtbs variable flattening all the non-overlays entries
+# and appending the overlays entries
+dtbs := $(notdir $(dtbs_regular)) $(dtbs_overlays)
endif # CONFIG_ARCH_WANT_FLAT_DTB_INSTALL
diff --git a/scripts/Makefile.lib b/scripts/Makefile.lib
index 111111111111..222222222222 100644
--- a/scripts/Makefile.lib
+++ b/scripts/Makefile.lib
@@ -402,7 +402,7 @@ $(obj)/%.dtbo.S: $(obj)/%.dtbo FORCE
quiet_cmd_dtc = DTC $@
cmd_dtc = $(HOSTCC) -E $(dtc_cpp_flags) -x assembler-with-cpp -o $(dtc-tmp) $< ; \
- $(DTC) -o $@ -b 0 \
+ $(DTC) -@ -o $@ -b 0 \
$(addprefix -i,$(dir $<) $(DTC_INCLUDE)) $(DTC_FLAGS) \
-d $(depfile).dtc.tmp $(dtc-tmp) ; \
cat $(depfile).pre.tmp $(depfile).dtc.tmp > $(depfile)
@@ -427,12 +427,18 @@ quiet_cmd_dtb = $(quiet_cmd_dtc)
cmd_dtb = $(cmd_dtc)
endif
+quiet_cmd_scr = MKIMAGE $@
+cmd_scr = mkimage -C none -A $(ARCH) -T script -d $< $@
+
$(obj)/%.dtb: $(obj)/%.dts $(DTC) $(DT_TMP_SCHEMA) FORCE
$(call if_changed_dep,dtb)
$(obj)/%.dtbo: $(src)/%.dtso $(DTC) FORCE
$(call if_changed_dep,dtc)
+$(obj)/%.scr: $(src)/%.scr-cmd FORCE
+ $(call if_changed,scr)
+
dtc-tmp = $(subst $(comma),_,$(dot-target).dts.tmp)
# Bzip2
--
Armbian

File diff suppressed because it is too large Load Diff

@ -0,0 +1,142 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Sebastian Reichel <sebastian.reichel@collabora.com>
Date: Tue, 24 Oct 2023 16:09:35 +0200
Subject: math.h: add DIV_ROUND_UP_NO_OVERFLOW
Add a new DIV_ROUND_UP helper, which cannot overflow when
big numbers are being used.
Signed-off-by: Sebastian Reichel <sebastian.reichel@collabora.com>
---
include/linux/math.h | 11 ++++++++++
1 file changed, 11 insertions(+)
diff --git a/include/linux/math.h b/include/linux/math.h
index 111111111111..222222222222 100644
--- a/include/linux/math.h
+++ b/include/linux/math.h
@@ -36,6 +36,17 @@
#define DIV_ROUND_UP __KERNEL_DIV_ROUND_UP
+/**
+ * DIV_ROUND_UP_NO_OVERFLOW - divide two numbers and always round up
+ * @n: numerator / dividend
+ * @d: denominator / divisor
+ *
+ * This functions does the same as DIV_ROUND_UP, but internally uses a
+ * division and a modulo operation instead of math tricks. This way it
+ * avoids overflowing when handling big numbers.
+ */
+#define DIV_ROUND_UP_NO_OVERFLOW(n, d) (((n) / (d)) + !!((n) % (d)))
+
#define DIV_ROUND_DOWN_ULL(ll, d) \
({ unsigned long long _tmp = (ll); do_div(_tmp, d); _tmp; })
--
Armbian
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Sebastian Reichel <sebastian.reichel@collabora.com>
Date: Tue, 24 Oct 2023 16:13:50 +0200
Subject: clk: divider: Fix divisor masking on 64 bit platforms
The clock framework handles clock rates as "unsigned long", so u32 on
32-bit architectures and u64 on 64-bit architectures.
The current code casts the dividend to u64 on 32-bit to avoid a
potential overflow. For example DIV_ROUND_UP(3000000000, 1500000000)
= (3.0G + 1.5G - 1) / 1.5G = = OVERFLOW / 1.5G, which has been
introduced in commit 9556f9dad8f5 ("clk: divider: handle integer overflow
when dividing large clock rates").
On 64 bit platforms this masks the divisor, so that only the lower
32 bit are used. Thus requesting a frequency >= 4.3GHz results
in incorrect values. For example requesting 4300000000 (4.3 GHz) will
effectively request ca. 5 MHz. Requesting clk_round_rate(clk, ULONG_MAX)
is a bit of a special case, since that still returns correct values as
long as the parent clock is below 8.5 GHz.
Fix this by switching to DIV_ROUND_UP_NO_OVERFLOW, which cannot
overflow. This avoids any requirements on the arguments (except
that divisor should not be 0 obviously).
Signed-off-by: Sebastian Reichel <sebastian.reichel@collabora.com>
---
drivers/clk/clk-divider.c | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/drivers/clk/clk-divider.c b/drivers/clk/clk-divider.c
index 111111111111..222222222222 100644
--- a/drivers/clk/clk-divider.c
+++ b/drivers/clk/clk-divider.c
@@ -220,7 +220,7 @@ static int _div_round_up(const struct clk_div_table *table,
unsigned long parent_rate, unsigned long rate,
unsigned long flags)
{
- int div = DIV_ROUND_UP_ULL((u64)parent_rate, rate);
+ int div = DIV_ROUND_UP_NO_OVERFLOW(parent_rate, rate);
if (flags & CLK_DIVIDER_POWER_OF_TWO)
div = __roundup_pow_of_two(div);
@@ -237,7 +237,7 @@ static int _div_round_closest(const struct clk_div_table *table,
int up, down;
unsigned long up_rate, down_rate;
- up = DIV_ROUND_UP_ULL((u64)parent_rate, rate);
+ up = DIV_ROUND_UP_NO_OVERFLOW(parent_rate, rate);
down = parent_rate / rate;
if (flags & CLK_DIVIDER_POWER_OF_TWO) {
@@ -473,7 +473,7 @@ int divider_get_val(unsigned long rate, unsigned long parent_rate,
{
unsigned int div, value;
- div = DIV_ROUND_UP_ULL((u64)parent_rate, rate);
+ div = DIV_ROUND_UP_NO_OVERFLOW(parent_rate, rate);
if (!_is_valid_div(table, div, flags))
return -EINVAL;
--
Armbian
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Sebastian Reichel <sebastian.reichel@collabora.com>
Date: Tue, 24 Oct 2023 18:09:57 +0200
Subject: clk: composite: replace open-coded abs_diff()
Replace the open coded abs_diff() with the existing helper function.
Suggested-by: Andy Shevchenko <andriy.shevchenko@intel.com>
Signed-off-by: Sebastian Reichel <sebastian.reichel@collabora.com>
---
drivers/clk/clk-composite.c | 6 ++----
1 file changed, 2 insertions(+), 4 deletions(-)
diff --git a/drivers/clk/clk-composite.c b/drivers/clk/clk-composite.c
index 111111111111..222222222222 100644
--- a/drivers/clk/clk-composite.c
+++ b/drivers/clk/clk-composite.c
@@ -6,6 +6,7 @@
#include <linux/clk-provider.h>
#include <linux/device.h>
#include <linux/err.h>
+#include <linux/math.h>
#include <linux/slab.h>
static u8 clk_composite_get_parent(struct clk_hw *hw)
@@ -119,10 +120,7 @@ static int clk_composite_determine_rate(struct clk_hw *hw,
if (ret)
continue;
- if (req->rate >= tmp_req.rate)
- rate_diff = req->rate - tmp_req.rate;
- else
- rate_diff = tmp_req.rate - req->rate;
+ rate_diff = abs_diff(req->rate, tmp_req.rate);
if (!rate_diff || !req->best_parent_hw
|| best_rate_diff > rate_diff) {
--
Armbian

@ -0,0 +1,214 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Muhammed Efe Cetin <efectn@protonmail.com>
Date: Fri, 11 Aug 2023 17:56:00 +0300
Subject: irqchip/irq-gic-v3-its: fix its timeout issue for rk35xx boards
---
drivers/irqchip/irq-gic-v3-its.c | 79 +++++++++-
1 file changed, 72 insertions(+), 7 deletions(-)
diff --git a/drivers/irqchip/irq-gic-v3-its.c b/drivers/irqchip/irq-gic-v3-its.c
index 111111111111..222222222222 100644
--- a/drivers/irqchip/irq-gic-v3-its.c
+++ b/drivers/irqchip/irq-gic-v3-its.c
@@ -163,6 +163,7 @@ struct its_device {
struct its_node *its;
struct event_lpi_map event_map;
void *itt;
+ u32 itt_sz;
u32 nr_ites;
u32 device_id;
bool shared;
@@ -2191,6 +2192,9 @@ static void gic_reset_prop_table(void *va)
static struct page *its_allocate_prop_table(gfp_t gfp_flags)
{
struct page *prop_page;
+
+ if (of_machine_is_compatible("rockchip,rk3568") || of_machine_is_compatible("rockchip,rk3566") || of_machine_is_compatible("rockchip,rk3588"))
+ gfp_flags |= GFP_DMA32;
prop_page = alloc_pages(gfp_flags, get_order(LPI_PROPBASE_SZ));
if (!prop_page)
@@ -2315,6 +2319,7 @@ static int its_setup_baser(struct its_node *its, struct its_baser *baser,
u32 alloc_pages, psz;
struct page *page;
void *base;
+ gfp_t gfp_flags;
psz = baser->psz;
alloc_pages = (PAGE_ORDER_TO_SIZE(order) / psz);
@@ -2326,7 +2331,11 @@ static int its_setup_baser(struct its_node *its, struct its_baser *baser,
order = get_order(GITS_BASER_PAGES_MAX * psz);
}
- page = alloc_pages_node(its->numa_node, GFP_KERNEL | __GFP_ZERO, order);
+ gfp_flags = GFP_KERNEL | __GFP_ZERO;
+ if (of_machine_is_compatible("rockchip,rk3568") || of_machine_is_compatible("rockchip,rk3566") || of_machine_is_compatible("rockchip,rk3588"))
+ gfp_flags |= GFP_DMA32;
+
+ page = alloc_pages_node(its->numa_node, gfp_flags, order);
if (!page)
return -ENOMEM;
@@ -2376,6 +2385,15 @@ static int its_setup_baser(struct its_node *its, struct its_baser *baser,
its_write_baser(its, baser, val);
tmp = baser->val;
+ if (of_machine_is_compatible("rockchip,rk3568") ||
+ of_machine_is_compatible("rockchip,rk3566") ||
+ of_machine_is_compatible("rockchip,rk3588")) {
+ if (tmp & GITS_BASER_SHAREABILITY_MASK)
+ tmp &= ~GITS_BASER_SHAREABILITY_MASK;
+ else
+ gic_flush_dcache_to_poc(base, PAGE_ORDER_TO_SIZE(order));
+ }
+
if ((val ^ tmp) & GITS_BASER_SHAREABILITY_MASK) {
/*
* Shareability didn't stick. Just use
@@ -2965,7 +2983,9 @@ static int its_alloc_collections(struct its_node *its)
static struct page *its_allocate_pending_table(gfp_t gfp_flags)
{
struct page *pend_page;
-
+
+ if (of_machine_is_compatible("rockchip,rk3568") || of_machine_is_compatible("rockchip,rk3566") || of_machine_is_compatible("rockchip,rk3588"))
+ gfp_flags |= GFP_DMA32;
pend_page = alloc_pages(gfp_flags | __GFP_ZERO,
get_order(LPI_PENDBASE_SZ));
if (!pend_page)
@@ -3124,6 +3144,11 @@ static void its_cpu_init_lpis(void)
if (!rdists_support_shareable())
tmp &= ~GICR_PROPBASER_SHAREABILITY_MASK;
+ if (of_machine_is_compatible("rockchip,rk3568") ||
+ of_machine_is_compatible("rockchip,rk3566") ||
+ of_machine_is_compatible("rockchip,rk3588"))
+ tmp &= ~GICR_PROPBASER_SHAREABILITY_MASK;
+
if ((tmp ^ val) & GICR_PROPBASER_SHAREABILITY_MASK) {
if (!(tmp & GICR_PROPBASER_SHAREABILITY_MASK)) {
/*
@@ -3151,6 +3176,11 @@ static void its_cpu_init_lpis(void)
if (!rdists_support_shareable())
tmp &= ~GICR_PENDBASER_SHAREABILITY_MASK;
+ if (of_machine_is_compatible("rockchip,rk3568") ||
+ of_machine_is_compatible("rockchip,rk3566") ||
+ of_machine_is_compatible("rockchip,rk3588"))
+ tmp &= ~GICR_PENDBASER_SHAREABILITY_MASK;
+
if (!(tmp & GICR_PENDBASER_SHAREABILITY_MASK)) {
/*
* The HW reports non-shareable, we must remove the
@@ -3314,7 +3344,11 @@ static bool its_alloc_table_entry(struct its_node *its,
/* Allocate memory for 2nd level table */
if (!table[idx]) {
- page = alloc_pages_node(its->numa_node, GFP_KERNEL | __GFP_ZERO,
+ gfp_t gfp_flags = GFP_KERNEL | __GFP_ZERO;
+
+ if (of_machine_is_compatible("rockchip,rk3568") || of_machine_is_compatible("rockchip,rk3566") || of_machine_is_compatible("rockchip,rk3588"))
+ gfp_flags |= GFP_DMA32;
+ page = alloc_pages_node(its->numa_node, gfp_flags,
get_order(baser->psz));
if (!page)
return false;
@@ -3403,6 +3437,7 @@ static struct its_device *its_create_device(struct its_node *its, u32 dev_id,
int nr_lpis;
int nr_ites;
int sz;
+ gfp_t gfp_flags;
if (!its_alloc_device_table(its, dev_id))
return NULL;
@@ -3418,7 +3453,15 @@ static struct its_device *its_create_device(struct its_node *its, u32 dev_id,
nr_ites = max(2, nvecs);
sz = nr_ites * (FIELD_GET(GITS_TYPER_ITT_ENTRY_SIZE, its->typer) + 1);
sz = max(sz, ITS_ITT_ALIGN) + ITS_ITT_ALIGN - 1;
- itt = kzalloc_node(sz, GFP_KERNEL, its->numa_node);
+ gfp_flags = GFP_KERNEL;
+
+ if (of_machine_is_compatible("rockchip,rk3568") || of_machine_is_compatible("rockchip,rk3566") || of_machine_is_compatible("rockchip,rk3588")) {
+ gfp_flags |= GFP_DMA32;
+ itt = (void *)__get_free_pages(gfp_flags, get_order(sz));
+ } else {
+ itt = kzalloc_node(sz, gfp_flags, its->numa_node);
+ }
+
if (alloc_lpis) {
lpi_map = its_lpi_alloc(nvecs, &lpi_base, &nr_lpis);
if (lpi_map)
@@ -3432,7 +3475,13 @@ static struct its_device *its_create_device(struct its_node *its, u32 dev_id,
if (!dev || !itt || !col_map || (!lpi_map && alloc_lpis)) {
kfree(dev);
- kfree(itt);
+
+ if (of_machine_is_compatible("rockchip,rk3568") ||
+ of_machine_is_compatible("rockchip,rk3566") || of_machine_is_compatible("rockchip,rk3588"))
+ free_pages((unsigned long)itt, get_order(sz));
+ else
+ kfree(itt);
+
bitmap_free(lpi_map);
kfree(col_map);
return NULL;
@@ -3442,6 +3491,7 @@ static struct its_device *its_create_device(struct its_node *its, u32 dev_id,
dev->its = its;
dev->itt = itt;
+ dev->itt_sz = sz;
dev->nr_ites = nr_ites;
dev->event_map.lpi_map = lpi_map;
dev->event_map.col_map = col_map;
@@ -3469,7 +3519,13 @@ static void its_free_device(struct its_device *its_dev)
list_del(&its_dev->entry);
raw_spin_unlock_irqrestore(&its_dev->its->lock, flags);
kfree(its_dev->event_map.col_map);
- kfree(its_dev->itt);
+
+ if (of_machine_is_compatible("rockchip,rk3568") ||
+ of_machine_is_compatible("rockchip,rk3566") || of_machine_is_compatible("rockchip,rk3588"))
+ free_pages((unsigned long)its_dev->itt, get_order(its_dev->itt_sz));
+ else
+ kfree(its_dev->itt);
+
kfree(its_dev);
}
@@ -5078,6 +5134,7 @@ static int __init its_probe_one(struct its_node *its)
struct page *page;
u32 ctlr;
int err;
+ gfp_t gfp_flags;
its_enable_quirks(its);
@@ -5111,7 +5168,10 @@ static int __init its_probe_one(struct its_node *its)
}
}
- page = alloc_pages_node(its->numa_node, GFP_KERNEL | __GFP_ZERO,
+ gfp_flags = GFP_KERNEL | __GFP_ZERO;
+ if (of_machine_is_compatible("rockchip,rk3568") || of_machine_is_compatible("rockchip,rk3566") || of_machine_is_compatible("rockchip,rk3588"))
+ gfp_flags |= GFP_DMA32;
+ page = alloc_pages_node(its->numa_node, gfp_flags,
get_order(ITS_CMD_QUEUE_SZ));
if (!page) {
err = -ENOMEM;
@@ -5140,6 +5200,11 @@ static int __init its_probe_one(struct its_node *its)
if (its->flags & ITS_FLAGS_FORCE_NON_SHAREABLE)
tmp &= ~GITS_CBASER_SHAREABILITY_MASK;
+ if (of_machine_is_compatible("rockchip,rk3568") ||
+ of_machine_is_compatible("rockchip,rk3566") ||
+ of_machine_is_compatible("rockchip,rk3588"))
+ tmp &= ~GITS_CBASER_SHAREABILITY_MASK;
+
if ((tmp ^ baser) & GITS_CBASER_SHAREABILITY_MASK) {
if (!(tmp & GITS_CBASER_SHAREABILITY_MASK)) {
/*
--
Armbian

@ -0,0 +1,30 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: yangchaohong <45483831+yangchaohong@users.noreply.github.com>
Date: Wed, 1 May 2024 08:30:43 +0100
Subject: [ARCHEOLOGY] Fix PCIe for RK35xx+Fix ROCK5A PCIe device tree
> X-Git-Archeology: - Revision b1f648ee755de73a922a33d6a432f310ea4ff3e0: https://github.com/armbian/build/commit/b1f648ee755de73a922a33d6a432f310ea4ff3e0
> X-Git-Archeology: Date: Wed, 01 May 2024 08:30:43 +0100
> X-Git-Archeology: From: yangchaohong <45483831+yangchaohong@users.noreply.github.com>
> X-Git-Archeology: Subject: Fix PCIe for RK35xx+Fix ROCK5A PCIe device tree
> X-Git-Archeology:
---
drivers/pci/controller/dwc/pcie-dw-rockchip.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/pci/controller/dwc/pcie-dw-rockchip.c b/drivers/pci/controller/dwc/pcie-dw-rockchip.c
index 111111111111..222222222222 100644
--- a/drivers/pci/controller/dwc/pcie-dw-rockchip.c
+++ b/drivers/pci/controller/dwc/pcie-dw-rockchip.c
@@ -240,7 +240,7 @@ static int rockchip_pcie_resource_get(struct platform_device *pdev,
return PTR_ERR(rockchip->apb_base);
rockchip->rst_gpio = devm_gpiod_get_optional(&pdev->dev, "reset",
- GPIOD_OUT_HIGH);
+ GPIOD_OUT_LOW);
if (IS_ERR(rockchip->rst_gpio))
return PTR_ERR(rockchip->rst_gpio);
--
Armbian

@ -0,0 +1,758 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Alexey Charkov <alchark@gmail.com>
Date: Mon, 6 May 2024 13:36:32 +0400
Subject: arm64: dts: rockchip: add thermal zones information on RK3588
This includes the necessary device tree data to allow thermal
monitoring on RK3588(s) using the on-chip TSADC device, along with
trip points for automatic thermal management.
Each of the CPU clusters (one for the little cores and two for
the big cores) get a passive cooling trip point at 85C, which
will trigger DVFS throttling of the respective cluster upon
reaching a high temperature condition.
All zones also have a critical trip point at 115C, which will
trigger a reset.
Signed-off-by: Alexey Charkov <alchark@gmail.com>
---
arch/arm64/boot/dts/rockchip/rk3588s.dtsi | 147 ++++++++++
1 file changed, 147 insertions(+)
diff --git a/arch/arm64/boot/dts/rockchip/rk3588s.dtsi b/arch/arm64/boot/dts/rockchip/rk3588s.dtsi
index 111111111111..222222222222 100644
--- a/arch/arm64/boot/dts/rockchip/rk3588s.dtsi
+++ b/arch/arm64/boot/dts/rockchip/rk3588s.dtsi
@@ -10,6 +10,7 @@
#include <dt-bindings/reset/rockchip,rk3588-cru.h>
#include <dt-bindings/phy/phy.h>
#include <dt-bindings/ata/ahci.h>
+#include <dt-bindings/thermal/thermal.h>
/ {
compatible = "rockchip,rk3588";
@@ -2368,6 +2369,152 @@ pwm15: pwm@febf0030 {
status = "disabled";
};
+ thermal_zones: thermal-zones {
+ /* sensor near the center of the SoC */
+ package_thermal: package-thermal {
+ polling-delay-passive = <0>;
+ polling-delay = <0>;
+ thermal-sensors = <&tsadc 0>;
+
+ trips {
+ package_crit: package-crit {
+ temperature = <115000>;
+ hysteresis = <0>;
+ type = "critical";
+ };
+ };
+ };
+
+ /* sensor between A76 cores 0 and 1 */
+ bigcore0_thermal: bigcore0-thermal {
+ polling-delay-passive = <100>;
+ polling-delay = <0>;
+ thermal-sensors = <&tsadc 1>;
+
+ trips {
+ bigcore0_alert: bigcore0-alert {
+ temperature = <85000>;
+ hysteresis = <2000>;
+ type = "passive";
+ };
+ bigcore0_crit: bigcore0-crit {
+ temperature = <115000>;
+ hysteresis = <0>;
+ type = "critical";
+ };
+ };
+ cooling-maps {
+ map0 {
+ trip = <&bigcore0_alert>;
+ cooling-device =
+ <&cpu_b0 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
+ <&cpu_b1 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>;
+ };
+ };
+ };
+
+ /* sensor between A76 cores 2 and 3 */
+ bigcore2_thermal: bigcore2-thermal {
+ polling-delay-passive = <100>;
+ polling-delay = <0>;
+ thermal-sensors = <&tsadc 2>;
+
+ trips {
+ bigcore2_alert: bigcore2-alert {
+ temperature = <85000>;
+ hysteresis = <2000>;
+ type = "passive";
+ };
+ bigcore2_crit: bigcore2-crit {
+ temperature = <115000>;
+ hysteresis = <0>;
+ type = "critical";
+ };
+ };
+ cooling-maps {
+ map0 {
+ trip = <&bigcore2_alert>;
+ cooling-device =
+ <&cpu_b2 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
+ <&cpu_b3 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>;
+ };
+ };
+ };
+
+ /* sensor between the four A55 cores */
+ little_core_thermal: littlecore-thermal {
+ polling-delay-passive = <100>;
+ polling-delay = <0>;
+ thermal-sensors = <&tsadc 3>;
+
+ trips {
+ littlecore_alert: littlecore-alert {
+ temperature = <85000>;
+ hysteresis = <2000>;
+ type = "passive";
+ };
+ littlecore_crit: littlecore-crit {
+ temperature = <115000>;
+ hysteresis = <0>;
+ type = "critical";
+ };
+ };
+ cooling-maps {
+ map0 {
+ trip = <&littlecore_alert>;
+ cooling-device =
+ <&cpu_l0 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
+ <&cpu_l1 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
+ <&cpu_l2 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
+ <&cpu_l3 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>;
+ };
+ };
+ };
+
+ /* sensor near the PD_CENTER power domain */
+ center_thermal: center-thermal {
+ polling-delay-passive = <0>;
+ polling-delay = <0>;
+ thermal-sensors = <&tsadc 4>;
+
+ trips {
+ center_crit: center-crit {
+ temperature = <115000>;
+ hysteresis = <0>;
+ type = "critical";
+ };
+ };
+ };
+
+ gpu_thermal: gpu-thermal {
+ polling-delay-passive = <0>;
+ polling-delay = <0>;
+ thermal-sensors = <&tsadc 5>;
+
+ trips {
+ gpu_crit: gpu-crit {
+ temperature = <115000>;
+ hysteresis = <0>;
+ type = "critical";
+ };
+ };
+ };
+
+ npu_thermal: npu-thermal {
+ polling-delay-passive = <0>;
+ polling-delay = <0>;
+ thermal-sensors = <&tsadc 6>;
+
+ trips {
+ npu_crit: npu-crit {
+ temperature = <115000>;
+ hysteresis = <0>;
+ type = "critical";
+ };
+ };
+ };
+ };
+
tsadc: tsadc@fec00000 {
compatible = "rockchip,rk3588-tsadc";
reg = <0x0 0xfec00000 0x0 0x400>;
--
Armbian
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Alexey Charkov <alchark@gmail.com>
Date: Mon, 6 May 2024 13:36:33 +0400
Subject: arm64: dts: rockchip: enable thermal management on all RK3588 boards
This enables the on-chip thermal monitoring sensor (TSADC) on all
RK3588(s) boards that don't have it enabled yet. It provides temperature
monitoring for the SoC and emergency thermal shutdowns, and is thus
important to have in place before CPU DVFS is enabled, as high CPU
operating performance points can overheat the chip quickly in the
absence of thermal management.
Signed-off-by: Alexey Charkov <alchark@gmail.com>
---
arch/arm64/boot/dts/rockchip/rk3588-armsom-sige7.dts | 4 ++++
arch/arm64/boot/dts/rockchip/rk3588-edgeble-neu6a-common.dtsi | 4 ++++
arch/arm64/boot/dts/rockchip/rk3588-evb1-v10.dts | 4 ++++
arch/arm64/boot/dts/rockchip/rk3588-ok3588-c.dts | 4 ++++
arch/arm64/boot/dts/rockchip/rk3588-rock-5b.dts | 4 ++++
arch/arm64/boot/dts/rockchip/rk3588-toybrick-x0.dts | 4 ++++
arch/arm64/boot/dts/rockchip/rk3588-turing-rk1.dtsi | 4 ++++
arch/arm64/boot/dts/rockchip/rk3588s-rock-5a.dts | 4 ++++
8 files changed, 32 insertions(+)
diff --git a/arch/arm64/boot/dts/rockchip/rk3588-armsom-sige7.dts b/arch/arm64/boot/dts/rockchip/rk3588-armsom-sige7.dts
index 111111111111..222222222222 100644
--- a/arch/arm64/boot/dts/rockchip/rk3588-armsom-sige7.dts
+++ b/arch/arm64/boot/dts/rockchip/rk3588-armsom-sige7.dts
@@ -673,6 +673,10 @@ regulator-state-mem {
};
};
+&tsadc {
+ status = "okay";
+};
+
&u2phy0 {
status = "okay";
};
diff --git a/arch/arm64/boot/dts/rockchip/rk3588-edgeble-neu6a-common.dtsi b/arch/arm64/boot/dts/rockchip/rk3588-edgeble-neu6a-common.dtsi
index 111111111111..222222222222 100644
--- a/arch/arm64/boot/dts/rockchip/rk3588-edgeble-neu6a-common.dtsi
+++ b/arch/arm64/boot/dts/rockchip/rk3588-edgeble-neu6a-common.dtsi
@@ -466,3 +466,7 @@ regulator-state-mem {
};
};
};
+
+&tsadc {
+ status = "okay";
+};
diff --git a/arch/arm64/boot/dts/rockchip/rk3588-evb1-v10.dts b/arch/arm64/boot/dts/rockchip/rk3588-evb1-v10.dts
index 111111111111..222222222222 100644
--- a/arch/arm64/boot/dts/rockchip/rk3588-evb1-v10.dts
+++ b/arch/arm64/boot/dts/rockchip/rk3588-evb1-v10.dts
@@ -1131,6 +1131,10 @@ &sata0 {
status = "okay";
};
+&tsadc {
+ status = "okay";
+};
+
&u2phy0 {
status = "okay";
};
diff --git a/arch/arm64/boot/dts/rockchip/rk3588-ok3588-c.dts b/arch/arm64/boot/dts/rockchip/rk3588-ok3588-c.dts
index 111111111111..222222222222 100644
--- a/arch/arm64/boot/dts/rockchip/rk3588-ok3588-c.dts
+++ b/arch/arm64/boot/dts/rockchip/rk3588-ok3588-c.dts
@@ -376,6 +376,10 @@ &sdmmc {
status = "okay";
};
+&tsadc {
+ status = "okay";
+};
+
&u2phy2 {
status = "okay";
};
diff --git a/arch/arm64/boot/dts/rockchip/rk3588-rock-5b.dts b/arch/arm64/boot/dts/rockchip/rk3588-rock-5b.dts
index 111111111111..222222222222 100644
--- a/arch/arm64/boot/dts/rockchip/rk3588-rock-5b.dts
+++ b/arch/arm64/boot/dts/rockchip/rk3588-rock-5b.dts
@@ -743,6 +743,10 @@ regulator-state-mem {
};
};
+&tsadc {
+ status = "okay";
+};
+
&uart2 {
pinctrl-0 = <&uart2m0_xfer>;
status = "okay";
diff --git a/arch/arm64/boot/dts/rockchip/rk3588-toybrick-x0.dts b/arch/arm64/boot/dts/rockchip/rk3588-toybrick-x0.dts
index 111111111111..222222222222 100644
--- a/arch/arm64/boot/dts/rockchip/rk3588-toybrick-x0.dts
+++ b/arch/arm64/boot/dts/rockchip/rk3588-toybrick-x0.dts
@@ -648,6 +648,10 @@ regulator-state-mem {
};
};
+&tsadc {
+ status = "okay";
+};
+
&u2phy2 {
status = "okay";
};
diff --git a/arch/arm64/boot/dts/rockchip/rk3588-turing-rk1.dtsi b/arch/arm64/boot/dts/rockchip/rk3588-turing-rk1.dtsi
index 111111111111..222222222222 100644
--- a/arch/arm64/boot/dts/rockchip/rk3588-turing-rk1.dtsi
+++ b/arch/arm64/boot/dts/rockchip/rk3588-turing-rk1.dtsi
@@ -601,6 +601,10 @@ regulator-state-mem {
};
};
+&tsadc {
+ status = "okay";
+};
+
&uart2 {
pinctrl-0 = <&uart2m0_xfer>;
status = "okay";
diff --git a/arch/arm64/boot/dts/rockchip/rk3588s-rock-5a.dts b/arch/arm64/boot/dts/rockchip/rk3588s-rock-5a.dts
index 111111111111..222222222222 100644
--- a/arch/arm64/boot/dts/rockchip/rk3588s-rock-5a.dts
+++ b/arch/arm64/boot/dts/rockchip/rk3588s-rock-5a.dts
@@ -699,6 +699,10 @@ regulator-state-mem {
};
};
+&tsadc {
+ status = "okay";
+};
+
&u2phy0 {
status = "okay";
};
--
Armbian
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Alexey Charkov <alchark@gmail.com>
Date: Mon, 6 May 2024 13:36:34 +0400
Subject: arm64: dts: rockchip: add passive GPU cooling on RK3588
As the GPU support on RK3588 has been merged upstream, along with OPP
values, add a corresponding cooling map for passive cooling using the GPU.
Signed-off-by: Alexey Charkov <alchark@gmail.com>
---
arch/arm64/boot/dts/rockchip/rk3588s.dtsi | 14 +++++++++-
1 file changed, 13 insertions(+), 1 deletion(-)
diff --git a/arch/arm64/boot/dts/rockchip/rk3588s.dtsi b/arch/arm64/boot/dts/rockchip/rk3588s.dtsi
index 111111111111..222222222222 100644
--- a/arch/arm64/boot/dts/rockchip/rk3588s.dtsi
+++ b/arch/arm64/boot/dts/rockchip/rk3588s.dtsi
@@ -2487,17 +2487,29 @@ center_crit: center-crit {
};
gpu_thermal: gpu-thermal {
- polling-delay-passive = <0>;
+ polling-delay-passive = <100>;
polling-delay = <0>;
thermal-sensors = <&tsadc 5>;
trips {
+ gpu_alert: gpu-alert {
+ temperature = <85000>;
+ hysteresis = <2000>;
+ type = "passive";
+ };
gpu_crit: gpu-crit {
temperature = <115000>;
hysteresis = <0>;
type = "critical";
};
};
+ cooling-maps {
+ map0 {
+ trip = <&gpu_alert>;
+ cooling-device =
+ <&gpu THERMAL_NO_LIMIT THERMAL_NO_LIMIT>;
+ };
+ };
};
npu_thermal: npu-thermal {
--
Armbian
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Alexey Charkov <alchark@gmail.com>
Date: Mon, 6 May 2024 13:36:36 +0400
Subject: arm64: dts: rockchip: Add CPU/memory regulator coupling for RK3588
RK3588 chips allow for their CPU cores to be powered by a different
supply vs. their corresponding memory interfaces, and two of the
boards currently upstream do that (EVB1 and QuartzPro64).
The voltage of the memory interface though has to match that of the
CPU cores that use it, which downstream kernels achieve by the means
of a custom cpufreq driver which adjusts both at the same time.
It seems that regulator coupling is a more appropriate generic
interface for it, so this patch introduces coupling to affected
device trees to ensure that memory interface voltage is also updated
whenever cpufreq switches between CPU OPPs.
Note that other boards, such as Radxa Rock 5B, define both the CPU
and memory interface regulators as aliases to the same DT node, so
this doesn't apply there.
Signed-off-by: Alexey Charkov <alchark@gmail.com>
---
arch/arm64/boot/dts/rockchip/rk3588-evb1-v10.dts | 12 ++++++++++
arch/arm64/boot/dts/rockchip/rk3588-quartzpro64.dts | 12 ++++++++++
2 files changed, 24 insertions(+)
diff --git a/arch/arm64/boot/dts/rockchip/rk3588-evb1-v10.dts b/arch/arm64/boot/dts/rockchip/rk3588-evb1-v10.dts
index 111111111111..222222222222 100644
--- a/arch/arm64/boot/dts/rockchip/rk3588-evb1-v10.dts
+++ b/arch/arm64/boot/dts/rockchip/rk3588-evb1-v10.dts
@@ -878,6 +878,8 @@ regulators {
vdd_cpu_big1_s0: dcdc-reg1 {
regulator-always-on;
regulator-boot-on;
+ regulator-coupled-with = <&vdd_cpu_big1_mem_s0>;
+ regulator-coupled-max-spread = <10000>;
regulator-min-microvolt = <550000>;
regulator-max-microvolt = <1050000>;
regulator-ramp-delay = <12500>;
@@ -890,6 +892,8 @@ regulator-state-mem {
vdd_cpu_big0_s0: dcdc-reg2 {
regulator-always-on;
regulator-boot-on;
+ regulator-coupled-with = <&vdd_cpu_big0_mem_s0>;
+ regulator-coupled-max-spread = <10000>;
regulator-min-microvolt = <550000>;
regulator-max-microvolt = <1050000>;
regulator-ramp-delay = <12500>;
@@ -902,6 +906,8 @@ regulator-state-mem {
vdd_cpu_lit_s0: dcdc-reg3 {
regulator-always-on;
regulator-boot-on;
+ regulator-coupled-with = <&vdd_cpu_lit_mem_s0>;
+ regulator-coupled-max-spread = <10000>;
regulator-min-microvolt = <550000>;
regulator-max-microvolt = <950000>;
regulator-ramp-delay = <12500>;
@@ -926,6 +932,8 @@ regulator-state-mem {
vdd_cpu_big1_mem_s0: dcdc-reg5 {
regulator-always-on;
regulator-boot-on;
+ regulator-coupled-with = <&vdd_cpu_big1_s0>;
+ regulator-coupled-max-spread = <10000>;
regulator-min-microvolt = <675000>;
regulator-max-microvolt = <1050000>;
regulator-ramp-delay = <12500>;
@@ -939,6 +947,8 @@ regulator-state-mem {
vdd_cpu_big0_mem_s0: dcdc-reg6 {
regulator-always-on;
regulator-boot-on;
+ regulator-coupled-with = <&vdd_cpu_big0_s0>;
+ regulator-coupled-max-spread = <10000>;
regulator-min-microvolt = <675000>;
regulator-max-microvolt = <1050000>;
regulator-ramp-delay = <12500>;
@@ -963,6 +973,8 @@ regulator-state-mem {
vdd_cpu_lit_mem_s0: dcdc-reg8 {
regulator-always-on;
regulator-boot-on;
+ regulator-coupled-with = <&vdd_cpu_lit_s0>;
+ regulator-coupled-max-spread = <10000>;
regulator-min-microvolt = <675000>;
regulator-max-microvolt = <950000>;
regulator-ramp-delay = <12500>;
diff --git a/arch/arm64/boot/dts/rockchip/rk3588-quartzpro64.dts b/arch/arm64/boot/dts/rockchip/rk3588-quartzpro64.dts
index 111111111111..222222222222 100644
--- a/arch/arm64/boot/dts/rockchip/rk3588-quartzpro64.dts
+++ b/arch/arm64/boot/dts/rockchip/rk3588-quartzpro64.dts
@@ -833,6 +833,8 @@ vdd_cpu_big1_s0: dcdc-reg1 {
regulator-name = "vdd_cpu_big1_s0";
regulator-always-on;
regulator-boot-on;
+ regulator-coupled-with = <&vdd_cpu_big1_mem_s0>;
+ regulator-coupled-max-spread = <10000>;
regulator-min-microvolt = <550000>;
regulator-max-microvolt = <1050000>;
regulator-ramp-delay = <12500>;
@@ -846,6 +848,8 @@ vdd_cpu_big0_s0: dcdc-reg2 {
regulator-name = "vdd_cpu_big0_s0";
regulator-always-on;
regulator-boot-on;
+ regulator-coupled-with = <&vdd_cpu_big0_mem_s0>;
+ regulator-coupled-max-spread = <10000>;
regulator-min-microvolt = <550000>;
regulator-max-microvolt = <1050000>;
regulator-ramp-delay = <12500>;
@@ -859,6 +863,8 @@ vdd_cpu_lit_s0: dcdc-reg3 {
regulator-name = "vdd_cpu_lit_s0";
regulator-always-on;
regulator-boot-on;
+ regulator-coupled-with = <&vdd_cpu_lit_mem_s0>;
+ regulator-coupled-max-spread = <10000>;
regulator-min-microvolt = <550000>;
regulator-max-microvolt = <950000>;
regulator-ramp-delay = <12500>;
@@ -885,6 +891,8 @@ vdd_cpu_big1_mem_s0: dcdc-reg5 {
regulator-name = "vdd_cpu_big1_mem_s0";
regulator-always-on;
regulator-boot-on;
+ regulator-coupled-with = <&vdd_cpu_big1_s0>;
+ regulator-coupled-max-spread = <10000>;
regulator-min-microvolt = <675000>;
regulator-max-microvolt = <1050000>;
regulator-ramp-delay = <12500>;
@@ -899,6 +907,8 @@ vdd_cpu_big0_mem_s0: dcdc-reg6 {
regulator-name = "vdd_cpu_big0_mem_s0";
regulator-always-on;
regulator-boot-on;
+ regulator-coupled-with = <&vdd_cpu_big0_s0>;
+ regulator-coupled-max-spread = <10000>;
regulator-min-microvolt = <675000>;
regulator-max-microvolt = <1050000>;
regulator-ramp-delay = <12500>;
@@ -925,6 +935,8 @@ vdd_cpu_lit_mem_s0: dcdc-reg8 {
regulator-name = "vdd_cpu_lit_mem_s0";
regulator-always-on;
regulator-boot-on;
+ regulator-coupled-with = <&vdd_cpu_lit_s0>;
+ regulator-coupled-max-spread = <10000>;
regulator-min-microvolt = <675000>;
regulator-max-microvolt = <950000>;
regulator-ramp-delay = <12500>;
--
Armbian
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Alexey Charkov <alchark@gmail.com>
Date: Mon, 6 May 2024 13:36:37 +0400
Subject: arm64: dts: rockchip: Add OPP data for CPU cores on RK3588
By default the CPUs on RK3588 start up in a conservative performance
mode. Add frequency and voltage mappings to the device tree to enable
dynamic scaling via cpufreq.
OPP values are adapted from Radxa's downstream kernel for Rock 5B [1],
stripping them down to the minimum frequency and voltage combinations
as expected by the generic upstream cpufreq-dt driver, and also dropping
those OPPs that don't differ in voltage but only in frequency (keeping
the top frequency OPP in each case).
Note that this patch ignores voltage scaling for the CPU memory
interface which the downstream kernel does through a custom cpufreq
driver, and which is why the downstream version has two sets of voltage
values for each OPP (the second one being meant for the memory
interface supply regulator). This is done instead via regulator
coupling between CPU and memory interface supplies on affected boards.
This has been tested on Rock 5B with u-boot 2023.11 compiled from
Collabora's integration tree [2] with binary bl31 and appears to be
stable both under active cooling and passive cooling (with throttling)
[1] https://github.com/radxa/kernel/blob/stable-5.10-rock5/arch/arm64/boot/dts/rockchip/rk3588s.dtsi
[2] https://gitlab.collabora.com/hardware-enablement/rockchip-3588/u-boot
Signed-off-by: Alexey Charkov <alchark@gmail.com>
---
arch/arm64/boot/dts/rockchip/rk3588s.dtsi | 122 ++++++++++
1 file changed, 122 insertions(+)
diff --git a/arch/arm64/boot/dts/rockchip/rk3588s.dtsi b/arch/arm64/boot/dts/rockchip/rk3588s.dtsi
index 111111111111..222222222222 100644
--- a/arch/arm64/boot/dts/rockchip/rk3588s.dtsi
+++ b/arch/arm64/boot/dts/rockchip/rk3588s.dtsi
@@ -97,6 +97,7 @@ cpu_l0: cpu@0 {
clocks = <&scmi_clk SCMI_CLK_CPUL>;
assigned-clocks = <&scmi_clk SCMI_CLK_CPUL>;
assigned-clock-rates = <816000000>;
+ operating-points-v2 = <&cluster0_opp_table>;
cpu-idle-states = <&CPU_SLEEP>;
i-cache-size = <32768>;
i-cache-line-size = <64>;
@@ -116,6 +117,7 @@ cpu_l1: cpu@100 {
enable-method = "psci";
capacity-dmips-mhz = <530>;
clocks = <&scmi_clk SCMI_CLK_CPUL>;
+ operating-points-v2 = <&cluster0_opp_table>;
cpu-idle-states = <&CPU_SLEEP>;
i-cache-size = <32768>;
i-cache-line-size = <64>;
@@ -135,6 +137,7 @@ cpu_l2: cpu@200 {
enable-method = "psci";
capacity-dmips-mhz = <530>;
clocks = <&scmi_clk SCMI_CLK_CPUL>;
+ operating-points-v2 = <&cluster0_opp_table>;
cpu-idle-states = <&CPU_SLEEP>;
i-cache-size = <32768>;
i-cache-line-size = <64>;
@@ -154,6 +157,7 @@ cpu_l3: cpu@300 {
enable-method = "psci";
capacity-dmips-mhz = <530>;
clocks = <&scmi_clk SCMI_CLK_CPUL>;
+ operating-points-v2 = <&cluster0_opp_table>;
cpu-idle-states = <&CPU_SLEEP>;
i-cache-size = <32768>;
i-cache-line-size = <64>;
@@ -175,6 +179,7 @@ cpu_b0: cpu@400 {
clocks = <&scmi_clk SCMI_CLK_CPUB01>;
assigned-clocks = <&scmi_clk SCMI_CLK_CPUB01>;
assigned-clock-rates = <816000000>;
+ operating-points-v2 = <&cluster1_opp_table>;
cpu-idle-states = <&CPU_SLEEP>;
i-cache-size = <65536>;
i-cache-line-size = <64>;
@@ -194,6 +199,7 @@ cpu_b1: cpu@500 {
enable-method = "psci";
capacity-dmips-mhz = <1024>;
clocks = <&scmi_clk SCMI_CLK_CPUB01>;
+ operating-points-v2 = <&cluster1_opp_table>;
cpu-idle-states = <&CPU_SLEEP>;
i-cache-size = <65536>;
i-cache-line-size = <64>;
@@ -215,6 +221,7 @@ cpu_b2: cpu@600 {
clocks = <&scmi_clk SCMI_CLK_CPUB23>;
assigned-clocks = <&scmi_clk SCMI_CLK_CPUB23>;
assigned-clock-rates = <816000000>;
+ operating-points-v2 = <&cluster2_opp_table>;
cpu-idle-states = <&CPU_SLEEP>;
i-cache-size = <65536>;
i-cache-line-size = <64>;
@@ -234,6 +241,7 @@ cpu_b3: cpu@700 {
enable-method = "psci";
capacity-dmips-mhz = <1024>;
clocks = <&scmi_clk SCMI_CLK_CPUB23>;
+ operating-points-v2 = <&cluster2_opp_table>;
cpu-idle-states = <&CPU_SLEEP>;
i-cache-size = <65536>;
i-cache-line-size = <64>;
@@ -348,6 +356,120 @@ l3_cache: l3-cache {
};
};
+ cluster0_opp_table: opp-table-cluster0 {
+ compatible = "operating-points-v2";
+ opp-shared;
+
+ opp-1008000000 {
+ opp-hz = /bits/ 64 <1008000000>;
+ opp-microvolt = <675000 675000 950000>;
+ clock-latency-ns = <40000>;
+ };
+ opp-1200000000 {
+ opp-hz = /bits/ 64 <1200000000>;
+ opp-microvolt = <712500 712500 950000>;
+ clock-latency-ns = <40000>;
+ };
+ opp-1416000000 {
+ opp-hz = /bits/ 64 <1416000000>;
+ opp-microvolt = <762500 762500 950000>;
+ clock-latency-ns = <40000>;
+ opp-suspend;
+ };
+ opp-1608000000 {
+ opp-hz = /bits/ 64 <1608000000>;
+ opp-microvolt = <850000 850000 950000>;
+ clock-latency-ns = <40000>;
+ };
+ opp-1800000000 {
+ opp-hz = /bits/ 64 <1800000000>;
+ opp-microvolt = <950000 950000 950000>;
+ clock-latency-ns = <40000>;
+ };
+ };
+
+ cluster1_opp_table: opp-table-cluster1 {
+ compatible = "operating-points-v2";
+ opp-shared;
+
+ opp-1200000000 {
+ opp-hz = /bits/ 64 <1200000000>;
+ opp-microvolt = <675000 675000 1000000>;
+ clock-latency-ns = <40000>;
+ };
+ opp-1416000000 {
+ opp-hz = /bits/ 64 <1416000000>;
+ opp-microvolt = <725000 725000 1000000>;
+ clock-latency-ns = <40000>;
+ };
+ opp-1608000000 {
+ opp-hz = /bits/ 64 <1608000000>;
+ opp-microvolt = <762500 762500 1000000>;
+ clock-latency-ns = <40000>;
+ };
+ opp-1800000000 {
+ opp-hz = /bits/ 64 <1800000000>;
+ opp-microvolt = <850000 850000 1000000>;
+ clock-latency-ns = <40000>;
+ };
+ opp-2016000000 {
+ opp-hz = /bits/ 64 <2016000000>;
+ opp-microvolt = <925000 925000 1000000>;
+ clock-latency-ns = <40000>;
+ };
+ opp-2208000000 {
+ opp-hz = /bits/ 64 <2208000000>;
+ opp-microvolt = <987500 987500 1000000>;
+ clock-latency-ns = <40000>;
+ };
+ opp-2400000000 {
+ opp-hz = /bits/ 64 <2400000000>;
+ opp-microvolt = <1000000 1000000 1000000>;
+ clock-latency-ns = <40000>;
+ };
+ };
+
+ cluster2_opp_table: opp-table-cluster2 {
+ compatible = "operating-points-v2";
+ opp-shared;
+
+ opp-1200000000 {
+ opp-hz = /bits/ 64 <1200000000>;
+ opp-microvolt = <675000 675000 1000000>;
+ clock-latency-ns = <40000>;
+ };
+ opp-1416000000 {
+ opp-hz = /bits/ 64 <1416000000>;
+ opp-microvolt = <725000 725000 1000000>;
+ clock-latency-ns = <40000>;
+ };
+ opp-1608000000 {
+ opp-hz = /bits/ 64 <1608000000>;
+ opp-microvolt = <762500 762500 1000000>;
+ clock-latency-ns = <40000>;
+ };
+ opp-1800000000 {
+ opp-hz = /bits/ 64 <1800000000>;
+ opp-microvolt = <850000 850000 1000000>;
+ clock-latency-ns = <40000>;
+ };
+ opp-2016000000 {
+ opp-hz = /bits/ 64 <2016000000>;
+ opp-microvolt = <925000 925000 1000000>;
+ clock-latency-ns = <40000>;
+ };
+ opp-2208000000 {
+ opp-hz = /bits/ 64 <2208000000>;
+ opp-microvolt = <987500 987500 1000000>;
+ clock-latency-ns = <40000>;
+ };
+ opp-2400000000 {
+ opp-hz = /bits/ 64 <2400000000>;
+ opp-microvolt = <1000000 1000000 1000000>;
+ clock-latency-ns = <40000>;
+ };
+ };
+
display_subsystem: display-subsystem {
compatible = "rockchip,display-subsystem";
ports = <&vop_out>;
--
Armbian

File diff suppressed because it is too large Load Diff

@ -0,0 +1,663 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Muhammed Efe Cetin <efectn@protonmail.com>
Date: Thu, 16 Nov 2023 17:49:42 +0300
Subject: hwrng: rockchip: Add support for Rockchip HW RNG
---
drivers/char/hw_random/Kconfig | 13 +
drivers/char/hw_random/Makefile | 1 +
drivers/char/hw_random/rockchip-rng.c | 574 ++++++++++
3 files changed, 588 insertions(+)
diff --git a/drivers/char/hw_random/Kconfig b/drivers/char/hw_random/Kconfig
index 111111111111..222222222222 100644
--- a/drivers/char/hw_random/Kconfig
+++ b/drivers/char/hw_random/Kconfig
@@ -538,6 +538,19 @@ config HW_RANDOM_XIPHERA
To compile this driver as a module, choose M here: the
module will be called xiphera-trng.
+config HW_RANDOM_ROCKCHIP
+ tristate "Rockchip Random Number Generator support"
+ depends on ARCH_ROCKCHIP
+ default HW_RANDOM
+ help
+ This driver provides kernel-side support for the Random Number
+ Generator hardware found on Rockchip cpus.
+
+ To compile this driver as a module, choose M here: the
+ module will be called rockchip-rng.
+
+ If unsure, say Y.
+
config HW_RANDOM_ARM_SMCCC_TRNG
tristate "Arm SMCCC TRNG firmware interface support"
depends on HAVE_ARM_SMCCC_DISCOVERY
diff --git a/drivers/char/hw_random/Makefile b/drivers/char/hw_random/Makefile
index 111111111111..222222222222 100644
--- a/drivers/char/hw_random/Makefile
+++ b/drivers/char/hw_random/Makefile
@@ -35,6 +35,7 @@ obj-$(CONFIG_HW_RANDOM_IPROC_RNG200) += iproc-rng200.o
obj-$(CONFIG_HW_RANDOM_ST) += st-rng.o
obj-$(CONFIG_HW_RANDOM_XGENE) += xgene-rng.o
obj-$(CONFIG_HW_RANDOM_STM32) += stm32-rng.o
+obj-$(CONFIG_HW_RANDOM_ROCKCHIP) += rockchip-rng.o
obj-$(CONFIG_HW_RANDOM_PIC32) += pic32-rng.o
obj-$(CONFIG_HW_RANDOM_MESON) += meson-rng.o
obj-$(CONFIG_HW_RANDOM_CAVIUM) += cavium-rng.o cavium-rng-vf.o
diff --git a/drivers/char/hw_random/rockchip-rng.c b/drivers/char/hw_random/rockchip-rng.c
new file mode 100644
index 000000000000..111111111111
--- /dev/null
+++ b/drivers/char/hw_random/rockchip-rng.c
@@ -0,0 +1,574 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * rockchip-rng.c Random Number Generator driver for the Rockchip
+ *
+ * Copyright (c) 2018, Fuzhou Rockchip Electronics Co., Ltd.
+ * Author: Lin Jinhan <troy.lin@rock-chips.com>
+ *
+ */
+#include <linux/clk.h>
+#include <linux/hw_random.h>
+#include <linux/iopoll.h>
+#include <linux/module.h>
+#include <linux/mod_devicetable.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+#include <linux/pm_runtime.h>
+
+#define _SBF(s, v) ((v) << (s))
+#define HIWORD_UPDATE(val, mask, shift) \
+ ((val) << (shift) | (mask) << ((shift) + 16))
+
+#define ROCKCHIP_AUTOSUSPEND_DELAY 100
+#define ROCKCHIP_POLL_PERIOD_US 100
+#define ROCKCHIP_POLL_TIMEOUT_US 50000
+#define RK_MAX_RNG_BYTE (32)
+
+/* start of CRYPTO V1 register define */
+#define CRYPTO_V1_CTRL 0x0008
+#define CRYPTO_V1_RNG_START BIT(8)
+#define CRYPTO_V1_RNG_FLUSH BIT(9)
+
+#define CRYPTO_V1_TRNG_CTRL 0x0200
+#define CRYPTO_V1_OSC_ENABLE BIT(16)
+#define CRYPTO_V1_TRNG_SAMPLE_PERIOD(x) (x)
+
+#define CRYPTO_V1_TRNG_DOUT_0 0x0204
+/* end of CRYPTO V1 register define */
+
+/* start of CRYPTO V2 register define */
+#define CRYPTO_V2_RNG_DEFAULT_OFFSET 0x0400
+#define CRYPTO_V2_RNG_CTL 0x0
+#define CRYPTO_V2_RNG_64_BIT_LEN _SBF(4, 0x00)
+#define CRYPTO_V2_RNG_128_BIT_LEN _SBF(4, 0x01)
+#define CRYPTO_V2_RNG_192_BIT_LEN _SBF(4, 0x02)
+#define CRYPTO_V2_RNG_256_BIT_LEN _SBF(4, 0x03)
+#define CRYPTO_V2_RNG_FATESY_SOC_RING _SBF(2, 0x00)
+#define CRYPTO_V2_RNG_SLOWER_SOC_RING_0 _SBF(2, 0x01)
+#define CRYPTO_V2_RNG_SLOWER_SOC_RING_1 _SBF(2, 0x02)
+#define CRYPTO_V2_RNG_SLOWEST_SOC_RING _SBF(2, 0x03)
+#define CRYPTO_V2_RNG_ENABLE BIT(1)
+#define CRYPTO_V2_RNG_START BIT(0)
+#define CRYPTO_V2_RNG_SAMPLE_CNT 0x0004
+#define CRYPTO_V2_RNG_DOUT_0 0x0010
+/* end of CRYPTO V2 register define */
+
+/* start of TRNG_V1 register define */
+/* TRNG is no longer subordinate to the Crypto module */
+#define TRNG_V1_CTRL 0x0000
+#define TRNG_V1_CTRL_NOP _SBF(0, 0x00)
+#define TRNG_V1_CTRL_RAND _SBF(0, 0x01)
+#define TRNG_V1_CTRL_SEED _SBF(0, 0x02)
+
+#define TRNG_V1_STAT 0x0004
+#define TRNG_V1_STAT_SEEDED BIT(9)
+#define TRNG_V1_STAT_GENERATING BIT(30)
+#define TRNG_V1_STAT_RESEEDING BIT(31)
+
+#define TRNG_V1_MODE 0x0008
+#define TRNG_V1_MODE_128_BIT _SBF(3, 0x00)
+#define TRNG_V1_MODE_256_BIT _SBF(3, 0x01)
+
+#define TRNG_V1_IE 0x0010
+#define TRNG_V1_IE_GLBL_EN BIT(31)
+#define TRNG_V1_IE_SEED_DONE_EN BIT(1)
+#define TRNG_V1_IE_RAND_RDY_EN BIT(0)
+
+#define TRNG_V1_ISTAT 0x0014
+#define TRNG_V1_ISTAT_RAND_RDY BIT(0)
+
+/* RAND0 ~ RAND7 */
+#define TRNG_V1_RAND0 0x0020
+#define TRNG_V1_RAND7 0x003C
+
+#define TRNG_V1_AUTO_RQSTS 0x0060
+
+#define TRNG_V1_VERSION 0x00F0
+#define TRNG_v1_VERSION_CODE 0x46bc
+/* end of TRNG_V1 register define */
+
+/* start of RKRNG register define */
+#define RKRNG_CTRL 0x0010
+#define RKRNG_CTRL_INST_REQ BIT(0)
+#define RKRNG_CTRL_RESEED_REQ BIT(1)
+#define RKRNG_CTRL_TEST_REQ BIT(2)
+#define RKRNG_CTRL_SW_DRNG_REQ BIT(3)
+#define RKRNG_CTRL_SW_TRNG_REQ BIT(4)
+
+#define RKRNG_STATE 0x0014
+#define RKRNG_STATE_INST_ACK BIT(0)
+#define RKRNG_STATE_RESEED_ACK BIT(1)
+#define RKRNG_STATE_TEST_ACK BIT(2)
+#define RKRNG_STATE_SW_DRNG_ACK BIT(3)
+#define RKRNG_STATE_SW_TRNG_ACK BIT(4)
+
+/* DRNG_DATA_0 ~ DNG_DATA_7 */
+#define RKRNG_DRNG_DATA_0 0x0070
+#define RKRNG_DRNG_DATA_7 0x008C
+
+/* end of RKRNG register define */
+
+struct rk_rng_soc_data {
+ u32 default_offset;
+
+ int (*rk_rng_init)(struct hwrng *rng);
+ int (*rk_rng_read)(struct hwrng *rng, void *buf, size_t max, bool wait);
+};
+
+struct rk_rng {
+ struct device *dev;
+ struct hwrng rng;
+ void __iomem *mem;
+ struct rk_rng_soc_data *soc_data;
+ int clk_num;
+ struct clk_bulk_data *clk_bulks;
+};
+
+static void rk_rng_writel(struct rk_rng *rng, u32 val, u32 offset)
+{
+ __raw_writel(val, rng->mem + offset);
+}
+
+static u32 rk_rng_readl(struct rk_rng *rng, u32 offset)
+{
+ return __raw_readl(rng->mem + offset);
+}
+
+static int rk_rng_init(struct hwrng *rng)
+{
+ int ret;
+ struct rk_rng *rk_rng = container_of(rng, struct rk_rng, rng);
+
+ dev_dbg(rk_rng->dev, "clk_bulk_prepare_enable.\n");
+
+ ret = clk_bulk_prepare_enable(rk_rng->clk_num, rk_rng->clk_bulks);
+ if (ret < 0) {
+ dev_err(rk_rng->dev, "failed to enable clks %d\n", ret);
+ return ret;
+ }
+
+ return 0;
+}
+
+static void rk_rng_cleanup(struct hwrng *rng)
+{
+ struct rk_rng *rk_rng = container_of(rng, struct rk_rng, rng);
+
+ dev_dbg(rk_rng->dev, "clk_bulk_disable_unprepare.\n");
+ clk_bulk_disable_unprepare(rk_rng->clk_num, rk_rng->clk_bulks);
+}
+
+static int rk_rng_read(struct hwrng *rng, void *buf, size_t max, bool wait)
+{
+ int ret;
+ int read_len = 0;
+ struct rk_rng *rk_rng = container_of(rng, struct rk_rng, rng);
+
+ if (!rk_rng->soc_data->rk_rng_read)
+ return -EFAULT;
+
+ ret = pm_runtime_get_sync(rk_rng->dev);
+ if (ret < 0) {
+ pm_runtime_put_noidle(rk_rng->dev);
+ return ret;
+ }
+
+ ret = 0;
+ while (max > ret) {
+ read_len = rk_rng->soc_data->rk_rng_read(rng, buf + ret,
+ max - ret, wait);
+ if (read_len < 0) {
+ ret = read_len;
+ break;
+ }
+ ret += read_len;
+ }
+
+ pm_runtime_mark_last_busy(rk_rng->dev);
+ pm_runtime_put_sync_autosuspend(rk_rng->dev);
+
+ return ret;
+}
+
+static void rk_rng_read_regs(struct rk_rng *rng, u32 offset, void *buf,
+ size_t size)
+{
+ u32 i;
+
+ for (i = 0; i < size; i += 4)
+ *(u32 *)(buf + i) = be32_to_cpu(rk_rng_readl(rng, offset + i));
+}
+
+static int crypto_v1_read(struct hwrng *rng, void *buf, size_t max, bool wait)
+{
+ int ret = 0;
+ u32 reg_ctrl = 0;
+ struct rk_rng *rk_rng = container_of(rng, struct rk_rng, rng);
+
+ /* enable osc_ring to get entropy, sample period is set as 100 */
+ reg_ctrl = CRYPTO_V1_OSC_ENABLE | CRYPTO_V1_TRNG_SAMPLE_PERIOD(100);
+ rk_rng_writel(rk_rng, reg_ctrl, CRYPTO_V1_TRNG_CTRL);
+
+ reg_ctrl = HIWORD_UPDATE(CRYPTO_V1_RNG_START, CRYPTO_V1_RNG_START, 0);
+
+ rk_rng_writel(rk_rng, reg_ctrl, CRYPTO_V1_CTRL);
+
+ ret = read_poll_timeout(rk_rng_readl, reg_ctrl,
+ !(reg_ctrl & CRYPTO_V1_RNG_START),
+ ROCKCHIP_POLL_PERIOD_US,
+ ROCKCHIP_POLL_TIMEOUT_US, false,
+ rk_rng, CRYPTO_V1_CTRL);
+
+ if (ret < 0)
+ goto out;
+
+ ret = min_t(size_t, max, RK_MAX_RNG_BYTE);
+
+ rk_rng_read_regs(rk_rng, CRYPTO_V1_TRNG_DOUT_0, buf, ret);
+
+out:
+ /* close TRNG */
+ rk_rng_writel(rk_rng, HIWORD_UPDATE(0, CRYPTO_V1_RNG_START, 0),
+ CRYPTO_V1_CTRL);
+
+ return ret;
+}
+
+static int crypto_v2_read(struct hwrng *rng, void *buf, size_t max, bool wait)
+{
+ int ret = 0;
+ u32 reg_ctrl = 0;
+ struct rk_rng *rk_rng = container_of(rng, struct rk_rng, rng);
+
+ /* enable osc_ring to get entropy, sample period is set as 100 */
+ rk_rng_writel(rk_rng, 100, CRYPTO_V2_RNG_SAMPLE_CNT);
+
+ reg_ctrl |= CRYPTO_V2_RNG_256_BIT_LEN;
+ reg_ctrl |= CRYPTO_V2_RNG_SLOWER_SOC_RING_0;
+ reg_ctrl |= CRYPTO_V2_RNG_ENABLE;
+ reg_ctrl |= CRYPTO_V2_RNG_START;
+
+ rk_rng_writel(rk_rng, HIWORD_UPDATE(reg_ctrl, 0xffff, 0),
+ CRYPTO_V2_RNG_CTL);
+
+ ret = read_poll_timeout(rk_rng_readl, reg_ctrl,
+ !(reg_ctrl & CRYPTO_V2_RNG_START),
+ ROCKCHIP_POLL_PERIOD_US,
+ ROCKCHIP_POLL_TIMEOUT_US, false,
+ rk_rng, CRYPTO_V2_RNG_CTL);
+ if (ret < 0)
+ goto out;
+
+ ret = min_t(size_t, max, RK_MAX_RNG_BYTE);
+
+ rk_rng_read_regs(rk_rng, CRYPTO_V2_RNG_DOUT_0, buf, ret);
+
+out:
+ /* close TRNG */
+ rk_rng_writel(rk_rng, HIWORD_UPDATE(0, 0xffff, 0), CRYPTO_V2_RNG_CTL);
+
+ return ret;
+}
+
+static int trng_v1_init(struct hwrng *rng)
+{
+ int ret;
+ uint32_t auto_reseed_cnt = 1000;
+ uint32_t reg_ctrl, status, version;
+ struct rk_rng *rk_rng = container_of(rng, struct rk_rng, rng);
+
+ version = rk_rng_readl(rk_rng, TRNG_V1_VERSION);
+ if (version != TRNG_v1_VERSION_CODE) {
+ dev_err(rk_rng->dev,
+ "wrong trng version, expected = %08x, actual = %08x\n",
+ TRNG_V1_VERSION, version);
+ ret = -EFAULT;
+ goto exit;
+ }
+
+ status = rk_rng_readl(rk_rng, TRNG_V1_STAT);
+
+ /* TRNG should wait RAND_RDY triggered if it is busy or not seeded */
+ if (!(status & TRNG_V1_STAT_SEEDED) ||
+ (status & TRNG_V1_STAT_GENERATING) ||
+ (status & TRNG_V1_STAT_RESEEDING)) {
+ uint32_t mask = TRNG_V1_STAT_SEEDED |
+ TRNG_V1_STAT_GENERATING |
+ TRNG_V1_STAT_RESEEDING;
+
+ udelay(10);
+
+ /* wait for GENERATING and RESEEDING flag to clear */
+ read_poll_timeout(rk_rng_readl, reg_ctrl,
+ (reg_ctrl & mask) == TRNG_V1_STAT_SEEDED,
+ ROCKCHIP_POLL_PERIOD_US,
+ ROCKCHIP_POLL_TIMEOUT_US, false,
+ rk_rng, TRNG_V1_STAT);
+ }
+
+ /* clear ISTAT flag because trng may auto reseeding when power on */
+ reg_ctrl = rk_rng_readl(rk_rng, TRNG_V1_ISTAT);
+ rk_rng_writel(rk_rng, reg_ctrl, TRNG_V1_ISTAT);
+
+ /* auto reseed after (auto_reseed_cnt * 16) byte rand generate */
+ rk_rng_writel(rk_rng, auto_reseed_cnt, TRNG_V1_AUTO_RQSTS);
+
+ ret = 0;
+exit:
+
+ return ret;
+}
+
+static int trng_v1_read(struct hwrng *rng, void *buf, size_t max, bool wait)
+{
+ int ret = 0;
+ u32 reg_ctrl = 0;
+ struct rk_rng *rk_rng = container_of(rng, struct rk_rng, rng);
+
+ /* clear ISTAT anyway */
+ reg_ctrl = rk_rng_readl(rk_rng, TRNG_V1_ISTAT);
+ rk_rng_writel(rk_rng, reg_ctrl, TRNG_V1_ISTAT);
+
+ /* generate 256bit random */
+ rk_rng_writel(rk_rng, TRNG_V1_MODE_256_BIT, TRNG_V1_MODE);
+ rk_rng_writel(rk_rng, TRNG_V1_CTRL_RAND, TRNG_V1_CTRL);
+
+ /*
+ * Generate2 56 bit random data will cost 1024 clock cycles.
+ * Estimated at 150M RNG module frequency, it takes 6.7 microseconds.
+ */
+ udelay(10);
+ reg_ctrl = rk_rng_readl(rk_rng, TRNG_V1_ISTAT);
+ if (!(reg_ctrl & TRNG_V1_ISTAT_RAND_RDY)) {
+ /* wait RAND_RDY triggered */
+ ret = read_poll_timeout(rk_rng_readl, reg_ctrl,
+ (reg_ctrl & TRNG_V1_ISTAT_RAND_RDY),
+ ROCKCHIP_POLL_PERIOD_US,
+ ROCKCHIP_POLL_TIMEOUT_US, false,
+ rk_rng, TRNG_V1_ISTAT);
+ if (ret < 0)
+ goto out;
+ }
+
+ ret = min_t(size_t, max, RK_MAX_RNG_BYTE);
+
+ rk_rng_read_regs(rk_rng, TRNG_V1_RAND0, buf, ret);
+
+ /* clear all status flag */
+ rk_rng_writel(rk_rng, reg_ctrl, TRNG_V1_ISTAT);
+out:
+ /* close TRNG */
+ rk_rng_writel(rk_rng, TRNG_V1_CTRL_NOP, TRNG_V1_CTRL);
+
+ return ret;
+}
+
+static int rkrng_init(struct hwrng *rng)
+{
+ struct rk_rng *rk_rng = container_of(rng, struct rk_rng, rng);
+ u32 reg = 0;
+
+ rk_rng_writel(rk_rng, HIWORD_UPDATE(0, 0xffff, 0), RKRNG_CTRL);
+
+ reg = rk_rng_readl(rk_rng, RKRNG_STATE);
+ rk_rng_writel(rk_rng, reg, RKRNG_STATE);
+
+ return 0;
+}
+
+static int rkrng_read(struct hwrng *rng, void *buf, size_t max, bool wait)
+{
+ struct rk_rng *rk_rng = container_of(rng, struct rk_rng, rng);
+ u32 reg_ctrl = 0;
+ int ret;
+
+ reg_ctrl = RKRNG_CTRL_SW_DRNG_REQ;
+
+ rk_rng_writel(rk_rng, HIWORD_UPDATE(reg_ctrl, 0xffff, 0), RKRNG_CTRL);
+
+ ret = readl_poll_timeout(rk_rng->mem + RKRNG_STATE, reg_ctrl,
+ (reg_ctrl & RKRNG_STATE_SW_DRNG_ACK),
+ ROCKCHIP_POLL_PERIOD_US,
+ ROCKCHIP_POLL_TIMEOUT_US);
+
+ if (ret)
+ goto exit;
+
+ rk_rng_writel(rk_rng, reg_ctrl, RKRNG_STATE);
+
+ ret = min_t(size_t, max, RK_MAX_RNG_BYTE);
+
+ rk_rng_read_regs(rk_rng, RKRNG_DRNG_DATA_0, buf, ret);
+
+exit:
+ /* close TRNG */
+ rk_rng_writel(rk_rng, HIWORD_UPDATE(0, 0xffff, 0), RKRNG_CTRL);
+
+ return ret;
+}
+
+static const struct rk_rng_soc_data crypto_v1_soc_data = {
+ .default_offset = 0,
+
+ .rk_rng_read = crypto_v1_read,
+};
+
+static const struct rk_rng_soc_data crypto_v2_soc_data = {
+ .default_offset = CRYPTO_V2_RNG_DEFAULT_OFFSET,
+
+ .rk_rng_read = crypto_v2_read,
+};
+
+static const struct rk_rng_soc_data trng_v1_soc_data = {
+ .default_offset = 0,
+
+ .rk_rng_init = trng_v1_init,
+ .rk_rng_read = trng_v1_read,
+};
+
+static const struct rk_rng_soc_data rkrng_soc_data = {
+ .default_offset = 0,
+
+ .rk_rng_init = rkrng_init,
+ .rk_rng_read = rkrng_read,
+};
+
+static const struct of_device_id rk_rng_dt_match[] = {
+ {
+ .compatible = "rockchip,cryptov1-rng",
+ .data = (void *)&crypto_v1_soc_data,
+ },
+ {
+ .compatible = "rockchip,cryptov2-rng",
+ .data = (void *)&crypto_v2_soc_data,
+ },
+ {
+ .compatible = "rockchip,trngv1",
+ .data = (void *)&trng_v1_soc_data,
+ },
+ {
+ .compatible = "rockchip,rkrng",
+ .data = (void *)&rkrng_soc_data,
+ },
+ { },
+};
+
+MODULE_DEVICE_TABLE(of, rk_rng_dt_match);
+
+static int rk_rng_probe(struct platform_device *pdev)
+{
+ int ret;
+ struct rk_rng *rk_rng;
+ struct device_node *np = pdev->dev.of_node;
+ const struct of_device_id *match;
+ resource_size_t map_size;
+
+ dev_dbg(&pdev->dev, "probing...\n");
+ rk_rng = devm_kzalloc(&pdev->dev, sizeof(struct rk_rng), GFP_KERNEL);
+ if (!rk_rng)
+ return -ENOMEM;
+
+ match = of_match_node(rk_rng_dt_match, np);
+ rk_rng->soc_data = (struct rk_rng_soc_data *)match->data;
+
+ rk_rng->dev = &pdev->dev;
+ rk_rng->rng.name = "rockchip";
+#ifndef CONFIG_PM
+ rk_rng->rng.init = rk_rng_init;
+ rk_rng->rng.cleanup = rk_rng_cleanup,
+#endif
+ rk_rng->rng.read = rk_rng_read;
+ rk_rng->rng.quality = 999;
+
+ rk_rng->mem = devm_of_iomap(&pdev->dev, pdev->dev.of_node, 0, &map_size);
+ if (IS_ERR(rk_rng->mem))
+ return PTR_ERR(rk_rng->mem);
+
+ /* compatible with crypto v2 module */
+ /*
+ * With old dtsi configurations, the RNG base was equal to the crypto
+ * base, so both drivers could not be enabled at the same time.
+ * RNG base = CRYPTO base + RNG offset
+ * (Since RK356X, RNG module is no longer belongs to CRYPTO module)
+ *
+ * With new dtsi configurations, CRYPTO regs is divided into two parts
+ * |---cipher---|---rng---|---pka---|, and RNG base is real RNG base.
+ * RNG driver and CRYPTO driver could be enabled at the same time.
+ */
+ if (map_size > rk_rng->soc_data->default_offset)
+ rk_rng->mem += rk_rng->soc_data->default_offset;
+
+ rk_rng->clk_num = devm_clk_bulk_get_all(&pdev->dev, &rk_rng->clk_bulks);
+ if (rk_rng->clk_num < 0) {
+ dev_err(&pdev->dev, "failed to get clks property\n");
+ return -ENODEV;
+ }
+
+ platform_set_drvdata(pdev, rk_rng);
+
+ pm_runtime_set_autosuspend_delay(&pdev->dev,
+ ROCKCHIP_AUTOSUSPEND_DELAY);
+ pm_runtime_use_autosuspend(&pdev->dev);
+ pm_runtime_enable(&pdev->dev);
+
+ ret = devm_hwrng_register(&pdev->dev, &rk_rng->rng);
+ if (ret) {
+ pm_runtime_dont_use_autosuspend(&pdev->dev);
+ pm_runtime_disable(&pdev->dev);
+ }
+
+ /* for some platform need hardware operation when probe */
+ if (rk_rng->soc_data->rk_rng_init) {
+ pm_runtime_get_sync(rk_rng->dev);
+
+ ret = rk_rng->soc_data->rk_rng_init(&rk_rng->rng);
+
+ pm_runtime_mark_last_busy(rk_rng->dev);
+ pm_runtime_put_sync_autosuspend(rk_rng->dev);
+ }
+
+ return ret;
+}
+
+#ifdef CONFIG_PM
+static int rk_rng_runtime_suspend(struct device *dev)
+{
+ struct rk_rng *rk_rng = dev_get_drvdata(dev);
+
+ rk_rng_cleanup(&rk_rng->rng);
+
+ return 0;
+}
+
+static int rk_rng_runtime_resume(struct device *dev)
+{
+ struct rk_rng *rk_rng = dev_get_drvdata(dev);
+
+ return rk_rng_init(&rk_rng->rng);
+}
+
+static const struct dev_pm_ops rk_rng_pm_ops = {
+ SET_RUNTIME_PM_OPS(rk_rng_runtime_suspend,
+ rk_rng_runtime_resume, NULL)
+ SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend,
+ pm_runtime_force_resume)
+};
+
+#endif
+
+static struct platform_driver rk_rng_driver = {
+ .driver = {
+ .name = "rockchip-rng",
+#ifdef CONFIG_PM
+ .pm = &rk_rng_pm_ops,
+#endif
+ .of_match_table = rk_rng_dt_match,
+ },
+ .probe = rk_rng_probe,
+};
+
+module_platform_driver(rk_rng_driver);
+
+MODULE_DESCRIPTION("ROCKCHIP H/W Random Number Generator driver");
+MODULE_AUTHOR("Lin Jinhan <troy.lin@rock-chips.com>");
+MODULE_LICENSE("GPL v2");
--
Armbian
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Muhammed Efe Cetin <efectn@protonmail.com>
Date: Thu, 16 Nov 2023 17:52:35 +0300
Subject: arm64: dts: Add HW RNG support to RK3588S
---
arch/arm64/boot/dts/rockchip/rk3588s.dtsi | 10 ++++++++++
1 file changed, 10 insertions(+)
diff --git a/arch/arm64/boot/dts/rockchip/rk3588s.dtsi b/arch/arm64/boot/dts/rockchip/rk3588s.dtsi
index 111111111111..222222222222 100644
--- a/arch/arm64/boot/dts/rockchip/rk3588s.dtsi
+++ b/arch/arm64/boot/dts/rockchip/rk3588s.dtsi
@@ -1935,6 +1935,16 @@ crypto: crypto@fe370000 {
status = "okay";
};
+ rng: rng@fe378000 {
+ compatible = "rockchip,trngv1";
+ reg = <0x0 0xfe378000 0x0 0x200>;
+ interrupts = <GIC_SPI 400 IRQ_TYPE_LEVEL_HIGH 0>;
+ clocks = <&scmi_clk SCMI_HCLK_SECURE_NS>;
+ clock-names = "hclk_trng";
+ resets = <&scmi_reset SRST_H_TRNG_NS>;
+ reset-names = "reset";
+ };
+
i2s0_8ch: i2s@fe470000 {
compatible = "rockchip,rk3588-i2s-tdm";
reg = <0x0 0xfe470000 0x0 0x1000>;
--
Armbian

@ -0,0 +1,311 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Sebastian Reichel <sebastian.reichel@collabora.com>
Date: Thu, 13 Jun 2024 15:48:42 +0200
Subject: media: dt-bindings: rk3568-vepu: Add RK3588 VEPU121
From: Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
This encoder-only device is present four times on this SoC, and should
support everything the rk3568 vepu supports (so JPEG, H.264 and VP8
encoding). No fallback compatible has been added, since the operating
systems might already support RK3568 VEPU and want to avoid registering
four of them separately considering they can be used as a cluster.
Signed-off-by: Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
Signed-off-by: Sebastian Reichel <sebastian.reichel@collabora.com>
---
Documentation/devicetree/bindings/media/rockchip,rk3568-vepu.yaml | 1 +
1 file changed, 1 insertion(+)
diff --git a/Documentation/devicetree/bindings/media/rockchip,rk3568-vepu.yaml b/Documentation/devicetree/bindings/media/rockchip,rk3568-vepu.yaml
index 111111111111..222222222222 100644
--- a/Documentation/devicetree/bindings/media/rockchip,rk3568-vepu.yaml
+++ b/Documentation/devicetree/bindings/media/rockchip,rk3568-vepu.yaml
@@ -17,6 +17,7 @@ properties:
compatible:
enum:
- rockchip,rk3568-vepu
+ - rockchip,rk3588-vepu121
reg:
maxItems: 1
--
Armbian
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Sebastian Reichel <sebastian.reichel@collabora.com>
Date: Thu, 13 Jun 2024 15:48:44 +0200
Subject: media: hantro: Disable multicore support
Avoid exposing equal Hantro video codecs to userspace. Equal video
codecs allow scheduling work between the cores. For that kernel support
is required, which does not yet exist. Until that is implemented avoid
exposing each core separately to userspace so that multicore can be
added in the future without breaking userspace ABI.
This was written with Rockchip RK3588 in mind (which has 4 Hantro H1
cores), but applies to all SoCs.
Signed-off-by: Sebastian Reichel <sebastian.reichel@collabora.com>
---
drivers/media/platform/verisilicon/hantro_drv.c | 37 ++++++++++
1 file changed, 37 insertions(+)
diff --git a/drivers/media/platform/verisilicon/hantro_drv.c b/drivers/media/platform/verisilicon/hantro_drv.c
index 111111111111..222222222222 100644
--- a/drivers/media/platform/verisilicon/hantro_drv.c
+++ b/drivers/media/platform/verisilicon/hantro_drv.c
@@ -992,6 +992,39 @@ static const struct media_device_ops hantro_m2m_media_ops = {
.req_queue = v4l2_m2m_request_queue,
};
+/*
+ * Some SoCs, like RK3588 have multiple identical Hantro cores, but the
+ * kernel is currently missing support for multi-core handling. Exposing
+ * separate devices for each core to userspace is bad, since that does
+ * not allow scheduling tasks properly (and creates ABI). With this workaround
+ * the driver will only probe for the first core and early exit for the other
+ * cores. Once the driver gains multi-core support, the same technique
+ * for detecting the main core can be used to cluster all cores together.
+ */
+static int hantro_disable_multicore(struct hantro_dev *vpu)
+{
+ const char *compatible;
+ struct device_node *node;
+ int ret;
+
+ /* Intentionally ignores the fallback strings */
+ ret = of_property_read_string(vpu->dev->of_node, "compatible", &compatible);
+ if (ret)
+ return ret;
+
+ /* first compatible node found from the root node is considered the main core */
+ node = of_find_compatible_node(NULL, NULL, compatible);
+ if (!node)
+ return -EINVAL; /* broken DT? */
+
+ if (vpu->dev->of_node != node) {
+ dev_info(vpu->dev, "missing multi-core support, ignoring this instance\n");
+ return -ENODEV;
+ }
+
+ return 0;
+}
+
static int hantro_probe(struct platform_device *pdev)
{
const struct of_device_id *match;
@@ -1011,6 +1044,10 @@ static int hantro_probe(struct platform_device *pdev)
match = of_match_node(of_hantro_match, pdev->dev.of_node);
vpu->variant = match->data;
+ ret = hantro_disable_multicore(vpu);
+ if (ret)
+ return ret;
+
/*
* Support for nxp,imx8mq-vpu is kept for backwards compatibility
* but it's deprecated. Please update your DTS file to use
--
Armbian
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Sebastian Reichel <sebastian.reichel@collabora.com>
Date: Thu, 13 Jun 2024 15:48:45 +0200
Subject: media: hantro: Add RK3588 VEPU121
RK3588 handling is exactly the same as RK3568. This is not
handled using fallback compatibles to avoid exposing multiple
video devices on kernels not having the multicore disable
patch.
Signed-off-by: Sebastian Reichel <sebastian.reichel@collabora.com>
---
drivers/media/platform/verisilicon/hantro_drv.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/drivers/media/platform/verisilicon/hantro_drv.c b/drivers/media/platform/verisilicon/hantro_drv.c
index 111111111111..222222222222 100644
--- a/drivers/media/platform/verisilicon/hantro_drv.c
+++ b/drivers/media/platform/verisilicon/hantro_drv.c
@@ -722,6 +722,7 @@ static const struct of_device_id of_hantro_match[] = {
{ .compatible = "rockchip,rk3399-vpu", .data = &rk3399_vpu_variant, },
{ .compatible = "rockchip,rk3568-vepu", .data = &rk3568_vepu_variant, },
{ .compatible = "rockchip,rk3568-vpu", .data = &rk3568_vpu_variant, },
+ { .compatible = "rockchip,rk3588-vepu121", .data = &rk3568_vepu_variant, },
{ .compatible = "rockchip,rk3588-av1-vpu", .data = &rk3588_vpu981_variant, },
#endif
#ifdef CONFIG_VIDEO_HANTRO_IMX8M
--
Armbian
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Sebastian Reichel <sebastian.reichel@collabora.com>
Date: Thu, 13 Jun 2024 15:48:46 +0200
Subject: arm64: dts: rockchip: Add VEPU121 to RK3588
From: Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
RK3588 has 4 Hantro G1 encoder-only cores. They are all independent IP,
but can be used as a cluster (i.e. sharing work between the cores).
These cores are called VEPU121 in the TRM. The TRM describes one more
VEPU121, but that is combined with a Hantro H1. That one will be handled
using the VPU binding instead.
Signed-off-by: Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
Signed-off-by: Sebastian Reichel <sebastian.reichel@collabora.com>
---
arch/arm64/boot/dts/rockchip/rk3588s.dtsi | 80 ++++++++++
1 file changed, 80 insertions(+)
diff --git a/arch/arm64/boot/dts/rockchip/rk3588s.dtsi b/arch/arm64/boot/dts/rockchip/rk3588s.dtsi
index 111111111111..222222222222 100644
--- a/arch/arm64/boot/dts/rockchip/rk3588s.dtsi
+++ b/arch/arm64/boot/dts/rockchip/rk3588s.dtsi
@@ -1282,6 +1282,86 @@ power-domain@RK3588_PD_SDMMC {
};
};
+ vepu121_0: video-codec@fdba0000 {
+ compatible = "rockchip,rk3588-vepu121";
+ reg = <0x0 0xfdba0000 0x0 0x800>;
+ interrupts = <GIC_SPI 122 IRQ_TYPE_LEVEL_HIGH 0>;
+ clocks = <&cru ACLK_JPEG_ENCODER0>, <&cru HCLK_JPEG_ENCODER0>;
+ clock-names = "aclk", "hclk";
+ iommus = <&vepu121_0_mmu>;
+ power-domains = <&power RK3588_PD_VDPU>;
+ };
+
+ vepu121_0_mmu: iommu@fdba0800 {
+ compatible = "rockchip,rk3588-iommu", "rockchip,rk3568-iommu";
+ reg = <0x0 0xfdba0800 0x0 0x40>;
+ interrupts = <GIC_SPI 121 IRQ_TYPE_LEVEL_HIGH 0>;
+ clocks = <&cru ACLK_JPEG_ENCODER0>, <&cru HCLK_JPEG_ENCODER0>;
+ clock-names = "aclk", "iface";
+ power-domains = <&power RK3588_PD_VDPU>;
+ #iommu-cells = <0>;
+ };
+
+ vepu121_1: video-codec@fdba4000 {
+ compatible = "rockchip,rk3588-vepu121";
+ reg = <0x0 0xfdba4000 0x0 0x800>;
+ interrupts = <GIC_SPI 124 IRQ_TYPE_LEVEL_HIGH 0>;
+ clocks = <&cru ACLK_JPEG_ENCODER1>, <&cru HCLK_JPEG_ENCODER1>;
+ clock-names = "aclk", "hclk";
+ iommus = <&vepu121_1_mmu>;
+ power-domains = <&power RK3588_PD_VDPU>;
+ };
+
+ vepu121_1_mmu: iommu@fdba4800 {
+ compatible = "rockchip,rk3588-iommu", "rockchip,rk3568-iommu";
+ reg = <0x0 0xfdba4800 0x0 0x40>;
+ interrupts = <GIC_SPI 123 IRQ_TYPE_LEVEL_HIGH 0>;
+ clocks = <&cru ACLK_JPEG_ENCODER1>, <&cru HCLK_JPEG_ENCODER1>;
+ clock-names = "aclk", "iface";
+ power-domains = <&power RK3588_PD_VDPU>;
+ #iommu-cells = <0>;
+ };
+
+ vepu121_2: video-codec@fdba8000 {
+ compatible = "rockchip,rk3588-vepu121";
+ reg = <0x0 0xfdba8000 0x0 0x800>;
+ interrupts = <GIC_SPI 126 IRQ_TYPE_LEVEL_HIGH 0>;
+ clocks = <&cru ACLK_JPEG_ENCODER2>, <&cru HCLK_JPEG_ENCODER2>;
+ clock-names = "aclk", "hclk";
+ iommus = <&vepu121_2_mmu>;
+ power-domains = <&power RK3588_PD_VDPU>;
+ };
+
+ vepu121_2_mmu: iommu@fdba8800 {
+ compatible = "rockchip,rk3588-iommu", "rockchip,rk3568-iommu";
+ reg = <0x0 0xfdba8800 0x0 0x40>;
+ interrupts = <GIC_SPI 125 IRQ_TYPE_LEVEL_HIGH 0>;
+ clocks = <&cru ACLK_JPEG_ENCODER2>, <&cru HCLK_JPEG_ENCODER2>;
+ clock-names = "aclk", "iface";
+ power-domains = <&power RK3588_PD_VDPU>;
+ #iommu-cells = <0>;
+ };
+
+ vepu121_3: video-codec@fdbac000 {
+ compatible = "rockchip,rk3588-vepu121";
+ reg = <0x0 0xfdbac000 0x0 0x800>;
+ interrupts = <GIC_SPI 128 IRQ_TYPE_LEVEL_HIGH 0>;
+ clocks = <&cru ACLK_JPEG_ENCODER3>, <&cru HCLK_JPEG_ENCODER3>;
+ clock-names = "aclk", "hclk";
+ iommus = <&vepu121_3_mmu>;
+ power-domains = <&power RK3588_PD_VDPU>;
+ };
+
+ vepu121_3_mmu: iommu@fdbac800 {
+ compatible = "rockchip,rk3588-iommu", "rockchip,rk3568-iommu";
+ reg = <0x0 0xfdbac800 0x0 0x40>;
+ interrupts = <GIC_SPI 127 IRQ_TYPE_LEVEL_HIGH 0>;
+ clocks = <&cru ACLK_JPEG_ENCODER3>, <&cru HCLK_JPEG_ENCODER3>;
+ clock-names = "aclk", "iface";
+ power-domains = <&power RK3588_PD_VDPU>;
+ #iommu-cells = <0>;
+ };
+
av1d: video-codec@fdc70000 {
compatible = "rockchip,rk3588-av1-vpu";
reg = <0x0 0xfdc70000 0x0 0x800>;
--
Armbian
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Sebastian Reichel <sebastian.reichel@collabora.com>
Date: Thu, 13 Jun 2024 15:48:47 +0200
Subject: arm64: dts: rockchip: Add VPU121 support for RK3588
From: Jianfeng Liu <liujianfeng1994@gmail.com>
Enable Hantro G1 video decoder in RK3588's devicetree.
Tested with FFmpeg v4l2_request code taken from [1]
with MPEG2, H.264 and VP8 samples.
[1] https://github.com/LibreELEC/LibreELEC.tv/blob/master/packages/multimedia/ffmpeg/patches/v4l2-request/ffmpeg-001-v4l2-request.patch
Signed-off-by: Jianfeng Liu <liujianfeng1994@gmail.com>
Tested-by: Hugh Cole-Baker <sigmaris@gmail.com>
Signed-off-by: Sebastian Reichel <sebastian.reichel@collabora.com>
---
arch/arm64/boot/dts/rockchip/rk3588s.dtsi | 22 ++++++++++
1 file changed, 22 insertions(+)
diff --git a/arch/arm64/boot/dts/rockchip/rk3588s.dtsi b/arch/arm64/boot/dts/rockchip/rk3588s.dtsi
index 111111111111..222222222222 100644
--- a/arch/arm64/boot/dts/rockchip/rk3588s.dtsi
+++ b/arch/arm64/boot/dts/rockchip/rk3588s.dtsi
@@ -1282,6 +1282,28 @@ power-domain@RK3588_PD_SDMMC {
};
};
+ vpu121: video-codec@fdb50000 {
+ compatible = "rockchip,rk3588-vpu121", "rockchip,rk3399-vpu";
+ reg = <0x0 0xfdb50000 0x0 0x800>;
+ interrupts = <GIC_SPI 120 IRQ_TYPE_LEVEL_HIGH 0>,
+ <GIC_SPI 119 IRQ_TYPE_LEVEL_HIGH 0>;
+ interrupt-names = "vepu", "vdpu";
+ clocks = <&cru ACLK_VPU>, <&cru HCLK_VPU>;
+ clock-names = "aclk", "hclk";
+ iommus = <&vpu121_mmu>;
+ power-domains = <&power RK3588_PD_VDPU>;
+ };
+
+ vpu121_mmu: iommu@fdb50800 {
+ compatible = "rockchip,rk3588-iommu", "rockchip,rk3568-iommu";
+ reg = <0x0 0xfdb50800 0x0 0x40>;
+ interrupts = <GIC_SPI 118 IRQ_TYPE_LEVEL_HIGH 0>;
+ clock-names = "aclk", "iface";
+ clocks = <&cru ACLK_VPU>, <&cru HCLK_VPU>;
+ power-domains = <&power RK3588_PD_VDPU>;
+ #iommu-cells = <0>;
+ };
+
vepu121_0: video-codec@fdba0000 {
compatible = "rockchip,rk3588-vepu121";
reg = <0x0 0xfdba0000 0x0 0x800>;
--
Armbian

File diff suppressed because it is too large Load Diff

@ -0,0 +1,43 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: amazingfate <liujianfeng1994@gmail.com>
Date: Fri, 21 Jun 2024 16:32:55 +0800
Subject: media: v4l2-core: Initialize h264 frame_mbs_only_flag as 1
---
drivers/media/v4l2-core/v4l2-ctrls-core.c | 13 ++++++++++
1 file changed, 13 insertions(+)
diff --git a/drivers/media/v4l2-core/v4l2-ctrls-core.c b/drivers/media/v4l2-core/v4l2-ctrls-core.c
index 111111111111..222222222222 100644
--- a/drivers/media/v4l2-core/v4l2-ctrls-core.c
+++ b/drivers/media/v4l2-core/v4l2-ctrls-core.c
@@ -111,6 +111,7 @@ static void std_init_compound(const struct v4l2_ctrl *ctrl, u32 idx,
struct v4l2_ctrl_vp9_frame *p_vp9_frame;
struct v4l2_ctrl_fwht_params *p_fwht_params;
struct v4l2_ctrl_h264_scaling_matrix *p_h264_scaling_matrix;
+ struct v4l2_ctrl_h264_sps *p_h264_sps;
struct v4l2_ctrl_av1_sequence *p_av1_sequence;
void *p = ptr.p + idx * ctrl->elem_size;
@@ -179,6 +180,18 @@ static void std_init_compound(const struct v4l2_ctrl *ctrl, u32 idx,
*/
memset(p_h264_scaling_matrix, 16, sizeof(*p_h264_scaling_matrix));
break;
+ case V4L2_CTRL_TYPE_H264_SPS:
+ p_h264_sps = p;
+ /*
+ * Without V4L2_H264_SPS_FLAG_FRAME_MBS_ONLY,
+ * frame_mbs_only_flag set to 0 will translate to a miniumum
+ * height of 32 (see H.264 specification 7-8). Some driver may
+ * have a minimum size lower then 32, which would fail
+ * validation with the SPS value. Set this flag, so that there
+ * is now doubling in the height, allowing a valid default.
+ */
+ p_h264_sps->flags = V4L2_H264_SPS_FLAG_FRAME_MBS_ONLY;
+ break;
}
}
--
Armbian

@ -0,0 +1,81 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Cristian Ciocaltea <cristian.ciocaltea@collabora.com>
Date: Mon, 15 Jan 2024 22:47:41 +0200
Subject: arm64: dts: rockchip: Add HDMI0 bridge to rk3588
Add DT node for the HDMI0 bridge found on RK3588 SoC.
Signed-off-by: Cristian Ciocaltea <cristian.ciocaltea@collabora.com>
---
arch/arm64/boot/dts/rockchip/rk3588s.dtsi | 55 ++++++++++
1 file changed, 55 insertions(+)
diff --git a/arch/arm64/boot/dts/rockchip/rk3588s.dtsi b/arch/arm64/boot/dts/rockchip/rk3588s.dtsi
index 111111111111..222222222222 100644
--- a/arch/arm64/boot/dts/rockchip/rk3588s.dtsi
+++ b/arch/arm64/boot/dts/rockchip/rk3588s.dtsi
@@ -1516,6 +1516,61 @@ i2s9_8ch: i2s@fddfc000 {
status = "disabled";
};
+ hdmi0: hdmi@fde80000 {
+ compatible = "rockchip,rk3588-dw-hdmi";
+ reg = <0x0 0xfde80000 0x0 0x20000>;
+ interrupts = <GIC_SPI 169 IRQ_TYPE_LEVEL_HIGH 0>,
+ <GIC_SPI 170 IRQ_TYPE_LEVEL_HIGH 0>,
+ <GIC_SPI 171 IRQ_TYPE_LEVEL_HIGH 0>,
+ <GIC_SPI 172 IRQ_TYPE_LEVEL_HIGH 0>,
+ <GIC_SPI 360 IRQ_TYPE_LEVEL_HIGH 0>;
+ clocks = <&cru PCLK_HDMITX0>,
+ <&cru CLK_HDMIHDP0>,
+ <&cru CLK_HDMITX0_EARC>,
+ <&cru CLK_HDMITX0_REF>,
+ <&cru MCLK_I2S5_8CH_TX>,
+ <&cru DCLK_VOP0>,
+ <&cru DCLK_VOP1>,
+ <&cru DCLK_VOP2>,
+ <&cru DCLK_VOP3>,
+ <&cru HCLK_VO1>;
+ clock-names = "pclk",
+ "hpd",
+ "earc",
+ "hdmitx_ref",
+ "aud",
+ "dclk_vp0",
+ "dclk_vp1",
+ "dclk_vp2",
+ "dclk_vp3",
+ "hclk_vo1";
+ resets = <&cru SRST_HDMITX0_REF>, <&cru SRST_HDMIHDP0>;
+ reset-names = "ref", "hdp";
+ power-domains = <&power RK3588_PD_VO1>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&hdmim0_tx0_cec &hdmim0_tx0_hpd
+ &hdmim0_tx0_scl &hdmim0_tx0_sda>;
+ reg-io-width = <4>;
+ rockchip,grf = <&sys_grf>;
+ rockchip,vo1_grf = <&vo1_grf>;
+ phys = <&hdptxphy_hdmi0>;
+ phy-names = "hdmi";
+ status = "disabled";
+
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ hdmi0_in: port@0 {
+ reg = <0>;
+ };
+
+ hdmi0_out: port@1 {
+ reg = <1>;
+ };
+ };
+ };
+
qos_gpu_m0: qos@fdf35000 {
compatible = "rockchip,rk3588-qos", "syscon";
reg = <0x0 0xfdf35000 0x0 0x20>;
--
Armbian

@ -0,0 +1,26 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Cristian Ciocaltea <cristian.ciocaltea@collabora.com>
Date: Tue, 16 Jan 2024 03:13:38 +0200
Subject: arm64: dts: rockchip: Enable HDMI0 PHY clk provider on rk3588
The HDMI0 PHY can be used as a clock provider on RK3588, hence add the
missing #clock-cells property.
---
arch/arm64/boot/dts/rockchip/rk3588s.dtsi | 1 +
1 file changed, 1 insertion(+)
diff --git a/arch/arm64/boot/dts/rockchip/rk3588s.dtsi b/arch/arm64/boot/dts/rockchip/rk3588s.dtsi
index 111111111111..222222222222 100644
--- a/arch/arm64/boot/dts/rockchip/rk3588s.dtsi
+++ b/arch/arm64/boot/dts/rockchip/rk3588s.dtsi
@@ -2985,6 +2985,7 @@ hdptxphy_hdmi0: phy@fed60000 {
reg = <0x0 0xfed60000 0x0 0x2000>;
clocks = <&cru CLK_USB2PHY_HDPTXRXPHY_REF>, <&cru PCLK_HDPTX0>;
clock-names = "ref", "apb";
+ #clock-cells = <0>;
#phy-cells = <0>;
resets = <&cru SRST_HDPTX0>, <&cru SRST_P_HDPTX0>,
<&cru SRST_HDPTX0_INIT>, <&cru SRST_HDPTX0_CMN>,
--
Armbian

@ -0,0 +1,549 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Cristian Ciocaltea <cristian.ciocaltea@collabora.com>
Date: Mon, 5 Feb 2024 01:38:48 +0200
Subject: phy: phy-rockchip-samsung-hdptx: Add FRL & EARC support
For upstreaming, this requires extending the standard PHY API to support
HDMI configuration options [1].
Currently, the bus_width PHY attribute is used to pass clock rate and
flags for 10-bit color depth, FRL and EARC. This is done by the HDMI
bridge driver via phy_set_bus_width().
[1]: https://lore.kernel.org/all/59d5595a24bbcca897e814440179fa2caf3dff38.1707040881.git.Sandor.yu@nxp.com/
Signed-off-by: Cristian Ciocaltea <cristian.ciocaltea@collabora.com>
---
drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c | 434 +++++++++-
1 file changed, 431 insertions(+), 3 deletions(-)
diff --git a/drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c b/drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c
index 111111111111..222222222222 100644
--- a/drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c
+++ b/drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c
@@ -190,6 +190,12 @@
#define LN3_TX_SER_RATE_SEL_HBR2 BIT(3)
#define LN3_TX_SER_RATE_SEL_HBR3 BIT(2)
+#define HDMI20_MAX_RATE 600000000
+#define DATA_RATE_MASK 0xFFFFFFF
+#define COLOR_DEPTH_MASK BIT(31)
+#define HDMI_MODE_MASK BIT(30)
+#define HDMI_EARC_MASK BIT(29)
+
struct lcpll_config {
u32 bit_rate;
u8 lcvco_mode_en;
@@ -272,6 +278,25 @@ struct rk_hdptx_phy {
struct clk_bulk_data *clks;
int nr_clks;
struct reset_control_bulk_data rsts[RST_MAX];
+ bool earc_en;
+};
+
+static const struct lcpll_config lcpll_cfg[] = {
+ { 48000000, 1, 0, 0, 0x7d, 0x7d, 1, 1, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 2,
+ 0, 0x13, 0x18, 1, 0, 0x20, 0x0c, 1, 0, },
+ { 40000000, 1, 1, 0, 0x68, 0x68, 1, 1, 0, 0, 0, 1, 1, 1, 1, 9, 0, 1, 1,
+ 0, 2, 3, 1, 0, 0x20, 0x0c, 1, 0, },
+ { 32000000, 1, 1, 1, 0x6b, 0x6b, 1, 1, 0, 1, 2, 1, 1, 1, 1, 9, 1, 2, 1,
+ 0, 0x0d, 0x18, 1, 0, 0x20, 0x0c, 1, 1, },
+};
+
+static const struct ropll_config ropll_frl_cfg[] = {
+ { 24000000, 0x19, 0x19, 1, 1, 0, 1, 2, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 1,
+ 0, 0, 0x20, 0x0c, 1, 0x0e, 0, 0, },
+ { 18000000, 0x7d, 0x7d, 1, 1, 0, 1, 1, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 1,
+ 0, 0, 0x20, 0x0c, 1, 0x0e, 0, 0, },
+ { 9000000, 0x7d, 0x7d, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 1,
+ 0, 0, 0x20, 0x0c, 1, 0x0e, 0, 0, },
};
static const struct ropll_config ropll_tmds_cfg[] = {
@@ -449,6 +474,73 @@ static const struct reg_sequence rk_hdtpx_tmds_cmn_init_seq[] = {
REG_SEQ0(CMN_REG(009b), 0x00),
};
+static const struct reg_sequence rk_hdtpx_frl_cmn_init_seq[] = {
+ REG_SEQ0(CMN_REG(0011), 0x00),
+ REG_SEQ0(CMN_REG(0017), 0x00),
+ REG_SEQ0(CMN_REG(0026), 0x53),
+ REG_SEQ0(CMN_REG(0030), 0x00),
+ REG_SEQ0(CMN_REG(0031), 0x20),
+ REG_SEQ0(CMN_REG(0032), 0x30),
+ REG_SEQ0(CMN_REG(0033), 0x0b),
+ REG_SEQ0(CMN_REG(0034), 0x23),
+ REG_SEQ0(CMN_REG(0042), 0xb8),
+ REG_SEQ0(CMN_REG(004e), 0x14),
+ REG_SEQ0(CMN_REG(0074), 0x00),
+ REG_SEQ0(CMN_REG(0081), 0x09),
+ REG_SEQ0(CMN_REG(0086), 0x01),
+ REG_SEQ0(CMN_REG(0087), 0x0c),
+ REG_SEQ0(CMN_REG(009b), 0x10),
+};
+
+static const struct reg_sequence rk_hdtpx_frl_ropll_cmn_init_seq[] = {
+ REG_SEQ0(CMN_REG(0008), 0x00),
+ REG_SEQ0(CMN_REG(001e), 0x14),
+ REG_SEQ0(CMN_REG(0020), 0x00),
+ REG_SEQ0(CMN_REG(0021), 0x00),
+ REG_SEQ0(CMN_REG(0022), 0x11),
+ REG_SEQ0(CMN_REG(0023), 0x00),
+ REG_SEQ0(CMN_REG(0025), 0x00),
+ REG_SEQ0(CMN_REG(0027), 0x00),
+ REG_SEQ0(CMN_REG(0028), 0x00),
+ REG_SEQ0(CMN_REG(002a), 0x01),
+ REG_SEQ0(CMN_REG(002b), 0x00),
+ REG_SEQ0(CMN_REG(002c), 0x00),
+ REG_SEQ0(CMN_REG(002d), 0x00),
+ REG_SEQ0(CMN_REG(002e), 0x00),
+ REG_SEQ0(CMN_REG(002f), 0x04),
+ REG_SEQ0(CMN_REG(003d), 0x40),
+ REG_SEQ0(CMN_REG(005c), 0x25),
+ REG_SEQ0(CMN_REG(0089), 0x00),
+ REG_SEQ0(CMN_REG(0094), 0x00),
+ REG_SEQ0(CMN_REG(0097), 0x02),
+ REG_SEQ0(CMN_REG(0099), 0x04),
+};
+
+static const struct reg_sequence rk_hdtpx_frl_lcpll_cmn_init_seq[] = {
+ REG_SEQ0(CMN_REG(0025), 0x10),
+ REG_SEQ0(CMN_REG(0027), 0x01),
+ REG_SEQ0(CMN_REG(0028), 0x0d),
+ REG_SEQ0(CMN_REG(002e), 0x02),
+ REG_SEQ0(CMN_REG(002f), 0x0d),
+ REG_SEQ0(CMN_REG(003d), 0x00),
+ REG_SEQ0(CMN_REG(0051), 0x00),
+ REG_SEQ0(CMN_REG(0055), 0x00),
+ REG_SEQ0(CMN_REG(0059), 0x11),
+ REG_SEQ0(CMN_REG(005a), 0x03),
+ REG_SEQ0(CMN_REG(005c), 0x05),
+ REG_SEQ0(CMN_REG(005e), 0x07),
+ REG_SEQ0(CMN_REG(0060), 0x01),
+ REG_SEQ0(CMN_REG(0064), 0x07),
+ REG_SEQ0(CMN_REG(0065), 0x00),
+ REG_SEQ0(CMN_REG(0069), 0x00),
+ REG_SEQ0(CMN_REG(006c), 0x00),
+ REG_SEQ0(CMN_REG(0070), 0x01),
+ REG_SEQ0(CMN_REG(0089), 0x02),
+ REG_SEQ0(CMN_REG(0095), 0x00),
+ REG_SEQ0(CMN_REG(0097), 0x00),
+ REG_SEQ0(CMN_REG(0099), 0x00),
+};
+
static const struct reg_sequence rk_hdtpx_common_sb_init_seq[] = {
REG_SEQ0(SB_REG(0114), 0x00),
REG_SEQ0(SB_REG(0115), 0x00),
@@ -472,6 +564,17 @@ static const struct reg_sequence rk_hdtpx_tmds_lntop_lowbr_seq[] = {
REG_SEQ0(LNTOP_REG(0205), 0x1f),
};
+static const struct reg_sequence rk_hdtpx_frl_lntop_init_seq[] = {
+ REG_SEQ0(LNTOP_REG(0200), 0x04),
+ REG_SEQ0(LNTOP_REG(0201), 0x00),
+ REG_SEQ0(LNTOP_REG(0202), 0x00),
+ REG_SEQ0(LNTOP_REG(0203), 0xf0),
+ REG_SEQ0(LNTOP_REG(0204), 0xff),
+ REG_SEQ0(LNTOP_REG(0205), 0xff),
+ REG_SEQ0(LNTOP_REG(0206), 0x05),
+ REG_SEQ0(LNTOP_REG(0207), 0x0f),
+};
+
static const struct reg_sequence rk_hdtpx_common_lane_init_seq[] = {
REG_SEQ0(LANE_REG(0303), 0x0c),
REG_SEQ0(LANE_REG(0307), 0x20),
@@ -550,6 +653,40 @@ static const struct reg_sequence rk_hdtpx_tmds_lane_init_seq[] = {
REG_SEQ0(LANE_REG(0606), 0x1c),
};
+static const struct reg_sequence rk_hdtpx_frl_ropll_lane_init_seq[] = {
+ REG_SEQ0(LANE_REG(0312), 0x3c),
+ REG_SEQ0(LANE_REG(0412), 0x3c),
+ REG_SEQ0(LANE_REG(0512), 0x3c),
+ REG_SEQ0(LANE_REG(0612), 0x3c),
+};
+
+static const struct reg_sequence rk_hdtpx_frl_lcpll_lane_init_seq[] = {
+ REG_SEQ0(LANE_REG(0312), 0x3c),
+ REG_SEQ0(LANE_REG(0412), 0x3c),
+ REG_SEQ0(LANE_REG(0512), 0x3c),
+ REG_SEQ0(LANE_REG(0612), 0x3c),
+ REG_SEQ0(LANE_REG(0303), 0x2f),
+ REG_SEQ0(LANE_REG(0403), 0x2f),
+ REG_SEQ0(LANE_REG(0503), 0x2f),
+ REG_SEQ0(LANE_REG(0603), 0x2f),
+ REG_SEQ0(LANE_REG(0305), 0x03),
+ REG_SEQ0(LANE_REG(0405), 0x03),
+ REG_SEQ0(LANE_REG(0505), 0x03),
+ REG_SEQ0(LANE_REG(0605), 0x03),
+ REG_SEQ0(LANE_REG(0306), 0xfc),
+ REG_SEQ0(LANE_REG(0406), 0xfc),
+ REG_SEQ0(LANE_REG(0506), 0xfc),
+ REG_SEQ0(LANE_REG(0606), 0xfc),
+ REG_SEQ0(LANE_REG(0305), 0x4f),
+ REG_SEQ0(LANE_REG(0405), 0x4f),
+ REG_SEQ0(LANE_REG(0505), 0x4f),
+ REG_SEQ0(LANE_REG(0605), 0x4f),
+ REG_SEQ0(LANE_REG(0304), 0x14),
+ REG_SEQ0(LANE_REG(0404), 0x14),
+ REG_SEQ0(LANE_REG(0504), 0x14),
+ REG_SEQ0(LANE_REG(0604), 0x14),
+};
+
static bool rk_hdptx_phy_is_rw_reg(struct device *dev, unsigned int reg)
{
switch (reg) {
@@ -651,6 +788,47 @@ static int rk_hdptx_post_enable_pll(struct rk_hdptx_phy *hdptx)
return 0;
}
+static int rk_hdptx_post_power_up(struct rk_hdptx_phy *hdptx)
+{
+ u32 val;
+ int ret;
+
+ val = (HDPTX_I_BIAS_EN | HDPTX_I_BGR_EN) << 16 |
+ HDPTX_I_BIAS_EN | HDPTX_I_BGR_EN;
+ regmap_write(hdptx->grf, GRF_HDPTX_CON0, val);
+
+ usleep_range(10, 15);
+ reset_control_deassert(hdptx->rsts[RST_INIT].rstc);
+
+ usleep_range(10, 15);
+ val = HDPTX_I_PLL_EN << 16 | HDPTX_I_PLL_EN;
+ regmap_write(hdptx->grf, GRF_HDPTX_CON0, val);
+
+ usleep_range(10, 15);
+ reset_control_deassert(hdptx->rsts[RST_CMN].rstc);
+
+ ret = regmap_read_poll_timeout(hdptx->grf, GRF_HDPTX_STATUS, val,
+ val & HDPTX_O_PLL_LOCK_DONE, 20, 400);
+ if (ret) {
+ dev_err(hdptx->dev, "Failed to get PHY PLL lock: %d\n", ret);
+ return ret;
+ }
+
+ usleep_range(20, 30);
+ reset_control_deassert(hdptx->rsts[RST_LANE].rstc);
+
+ ret = regmap_read_poll_timeout(hdptx->grf, GRF_HDPTX_STATUS, val,
+ val & HDPTX_O_PHY_RDY, 100, 5000);
+ if (ret) {
+ dev_err(hdptx->dev, "Failed to get PHY ready: %d\n", ret);
+ return ret;
+ }
+
+ dev_dbg(hdptx->dev, "PHY ready\n");
+
+ return 0;
+}
+
static void rk_hdptx_phy_disable(struct rk_hdptx_phy *hdptx)
{
u32 val;
@@ -680,6 +858,99 @@ static void rk_hdptx_phy_disable(struct rk_hdptx_phy *hdptx)
regmap_write(hdptx->grf, GRF_HDPTX_CON0, val);
}
+static void rk_hdptx_earc_config(struct rk_hdptx_phy *hdptx)
+{
+ regmap_update_bits(hdptx->regmap, SB_REG(0113), SB_RX_RCAL_OPT_CODE_MASK,
+ FIELD_PREP(SB_RX_RCAL_OPT_CODE_MASK, 1));
+ regmap_write(hdptx->regmap, SB_REG(011c), 0x04);
+ regmap_update_bits(hdptx->regmap, SB_REG(011b), SB_AFC_TOL_MASK,
+ FIELD_PREP(SB_AFC_TOL_MASK, 3));
+ regmap_write(hdptx->regmap, SB_REG(0109), 0x05);
+
+ regmap_update_bits(hdptx->regmap, SB_REG(0120),
+ SB_EARC_EN_MASK | SB_EARC_AFC_EN_MASK,
+ FIELD_PREP(SB_EARC_EN_MASK, 1) |
+ FIELD_PREP(SB_EARC_AFC_EN_MASK, 1));
+ regmap_update_bits(hdptx->regmap, SB_REG(011b), SB_EARC_SIG_DET_BYPASS_MASK,
+ FIELD_PREP(SB_EARC_SIG_DET_BYPASS_MASK, 1));
+ regmap_update_bits(hdptx->regmap, SB_REG(011f),
+ SB_PWM_AFC_CTRL_MASK | SB_RCAL_RSTN_MASK,
+ FIELD_PREP(SB_PWM_AFC_CTRL_MASK, 0xc) |
+ FIELD_PREP(SB_RCAL_RSTN_MASK, 1));
+ regmap_update_bits(hdptx->regmap, SB_REG(0115), SB_READY_DELAY_TIME_MASK,
+ FIELD_PREP(SB_READY_DELAY_TIME_MASK, 2));
+ regmap_update_bits(hdptx->regmap, SB_REG(0113), SB_RX_RTERM_CTRL_MASK,
+ FIELD_PREP(SB_RX_RTERM_CTRL_MASK, 3));
+ regmap_update_bits(hdptx->regmap, SB_REG(0102), ANA_SB_RXTERM_OFFSP_MASK,
+ FIELD_PREP(ANA_SB_RXTERM_OFFSP_MASK, 3));
+ regmap_update_bits(hdptx->regmap, SB_REG(0103), ANA_SB_RXTERM_OFFSN_MASK,
+ FIELD_PREP(ANA_SB_RXTERM_OFFSN_MASK, 3));
+
+ regmap_write(hdptx->regmap, SB_REG(011a), 0x03);
+ regmap_write(hdptx->regmap, SB_REG(0118), 0x0a);
+ regmap_write(hdptx->regmap, SB_REG(011e), 0x6a);
+ regmap_write(hdptx->regmap, SB_REG(011d), 0x67);
+
+ regmap_update_bits(hdptx->regmap, SB_REG(0117), FAST_PULSE_TIME_MASK,
+ FIELD_PREP(FAST_PULSE_TIME_MASK, 4));
+ regmap_update_bits(hdptx->regmap, SB_REG(0114),
+ SB_TG_SB_EN_DELAY_TIME_MASK | SB_TG_RXTERM_EN_DELAY_TIME_MASK,
+ FIELD_PREP(SB_TG_SB_EN_DELAY_TIME_MASK, 2) |
+ FIELD_PREP(SB_TG_RXTERM_EN_DELAY_TIME_MASK, 2));
+ regmap_update_bits(hdptx->regmap, SB_REG(0105), ANA_SB_TX_HLVL_PROG_MASK,
+ FIELD_PREP(ANA_SB_TX_HLVL_PROG_MASK, 7));
+ regmap_update_bits(hdptx->regmap, SB_REG(0106), ANA_SB_TX_LLVL_PROG_MASK,
+ FIELD_PREP(ANA_SB_TX_LLVL_PROG_MASK, 7));
+ regmap_update_bits(hdptx->regmap, SB_REG(010f), ANA_SB_VREG_GAIN_CTRL_MASK,
+ FIELD_PREP(ANA_SB_VREG_GAIN_CTRL_MASK, 0));
+ regmap_update_bits(hdptx->regmap, SB_REG(0110), ANA_SB_VREG_REF_SEL_MASK,
+ FIELD_PREP(ANA_SB_VREG_REF_SEL_MASK, 1));
+ regmap_update_bits(hdptx->regmap, SB_REG(0115), SB_TG_OSC_EN_DELAY_TIME_MASK,
+ FIELD_PREP(SB_TG_OSC_EN_DELAY_TIME_MASK, 2));
+ regmap_update_bits(hdptx->regmap, SB_REG(0116), AFC_RSTN_DELAY_TIME_MASK,
+ FIELD_PREP(AFC_RSTN_DELAY_TIME_MASK, 2));
+ regmap_update_bits(hdptx->regmap, SB_REG(0109), ANA_SB_DMRX_AFC_DIV_RATIO_MASK,
+ FIELD_PREP(ANA_SB_DMRX_AFC_DIV_RATIO_MASK, 5));
+ regmap_update_bits(hdptx->regmap, SB_REG(0103), OVRD_SB_RX_RESCAL_DONE_MASK,
+ FIELD_PREP(OVRD_SB_RX_RESCAL_DONE_MASK, 1));
+ regmap_update_bits(hdptx->regmap, SB_REG(0104), OVRD_SB_EN_MASK,
+ FIELD_PREP(OVRD_SB_EN_MASK, 1));
+ regmap_update_bits(hdptx->regmap, SB_REG(0102), OVRD_SB_RXTERM_EN_MASK,
+ FIELD_PREP(OVRD_SB_RXTERM_EN_MASK, 1));
+ regmap_update_bits(hdptx->regmap, SB_REG(0105), OVRD_SB_EARC_CMDC_EN_MASK,
+ FIELD_PREP(OVRD_SB_EARC_CMDC_EN_MASK, 1));
+ regmap_update_bits(hdptx->regmap, SB_REG(010f),
+ OVRD_SB_VREG_EN_MASK | OVRD_SB_VREG_LPF_BYPASS_MASK,
+ FIELD_PREP(OVRD_SB_VREG_EN_MASK, 1) |
+ FIELD_PREP(OVRD_SB_VREG_LPF_BYPASS_MASK, 1));
+ regmap_update_bits(hdptx->regmap, SB_REG(0123), OVRD_SB_READY_MASK,
+ FIELD_PREP(OVRD_SB_READY_MASK, 1));
+
+ usleep_range(1000, 1100);
+ regmap_update_bits(hdptx->regmap, SB_REG(0103), SB_RX_RESCAL_DONE_MASK,
+ FIELD_PREP(SB_RX_RESCAL_DONE_MASK, 1));
+ usleep_range(50, 60);
+ regmap_update_bits(hdptx->regmap, SB_REG(0104), SB_EN_MASK,
+ FIELD_PREP(SB_EN_MASK, 1));
+ usleep_range(50, 60);
+ regmap_update_bits(hdptx->regmap, SB_REG(0102), SB_RXTERM_EN_MASK,
+ FIELD_PREP(SB_RXTERM_EN_MASK, 1));
+ usleep_range(50, 60);
+ regmap_update_bits(hdptx->regmap, SB_REG(0105), SB_EARC_CMDC_EN_MASK,
+ FIELD_PREP(SB_EARC_CMDC_EN_MASK, 1));
+ regmap_update_bits(hdptx->regmap, SB_REG(010f), SB_VREG_EN_MASK,
+ FIELD_PREP(SB_VREG_EN_MASK, 1));
+ usleep_range(50, 60);
+ regmap_update_bits(hdptx->regmap, SB_REG(010f), OVRD_SB_VREG_LPF_BYPASS_MASK,
+ FIELD_PREP(OVRD_SB_VREG_LPF_BYPASS_MASK, 1));
+ usleep_range(250, 300);
+ regmap_update_bits(hdptx->regmap, SB_REG(010f), OVRD_SB_VREG_LPF_BYPASS_MASK,
+ FIELD_PREP(OVRD_SB_VREG_LPF_BYPASS_MASK, 0));
+ usleep_range(100, 120);
+ regmap_update_bits(hdptx->regmap, SB_REG(0123), SB_READY_MASK,
+ FIELD_PREP(SB_READY_MASK, 1));
+}
+
static bool rk_hdptx_phy_clk_pll_calc(unsigned int data_rate,
struct ropll_config *cfg)
{
@@ -755,9 +1026,13 @@ static bool rk_hdptx_phy_clk_pll_calc(unsigned int data_rate,
static int rk_hdptx_ropll_tmds_cmn_config(struct rk_hdptx_phy *hdptx,
unsigned int rate)
{
+ int i, bus_width = phy_get_bus_width(hdptx->phy);
+ u8 color_depth = (bus_width & COLOR_DEPTH_MASK) ? 1 : 0;
const struct ropll_config *cfg = NULL;
struct ropll_config rc = {0};
- int i;
+
+ if (color_depth)
+ rate = rate * 10 / 8;
for (i = 0; i < ARRAY_SIZE(ropll_tmds_cfg); i++)
if (rate == ropll_tmds_cfg[i].bit_rate) {
@@ -813,6 +1088,9 @@ static int rk_hdptx_ropll_tmds_cmn_config(struct rk_hdptx_phy *hdptx,
regmap_update_bits(hdptx->regmap, CMN_REG(0086), PLL_PCG_POSTDIV_SEL_MASK,
FIELD_PREP(PLL_PCG_POSTDIV_SEL_MASK, cfg->pms_sdiv));
+ regmap_update_bits(hdptx->regmap, CMN_REG(0086), PLL_PCG_CLK_SEL_MASK,
+ FIELD_PREP(PLL_PCG_CLK_SEL_MASK, color_depth));
+
regmap_update_bits(hdptx->regmap, CMN_REG(0086), PLL_PCG_CLK_EN,
PLL_PCG_CLK_EN);
@@ -853,9 +1131,146 @@ static int rk_hdptx_ropll_tmds_mode_config(struct rk_hdptx_phy *hdptx,
rk_hdptx_multi_reg_write(hdptx, rk_hdtpx_common_lane_init_seq);
rk_hdptx_multi_reg_write(hdptx, rk_hdtpx_tmds_lane_init_seq);
+ if (hdptx->earc_en)
+ rk_hdptx_earc_config(hdptx);
+
return rk_hdptx_post_enable_lane(hdptx);
}
+static int rk_hdptx_ropll_frl_mode_config(struct rk_hdptx_phy *hdptx,
+ u32 bus_width)
+{
+ u32 bit_rate = bus_width & DATA_RATE_MASK;
+ u8 color_depth = (bus_width & COLOR_DEPTH_MASK) ? 1 : 0;
+ const struct ropll_config *cfg = NULL;
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(ropll_frl_cfg); i++)
+ if (bit_rate == ropll_frl_cfg[i].bit_rate) {
+ cfg = &ropll_frl_cfg[i];
+ break;
+ }
+
+ if (!cfg) {
+ dev_err(hdptx->dev, "%s cannot find pll cfg\n", __func__);
+ return -EINVAL;
+ }
+
+ rk_hdptx_pre_power_up(hdptx);
+
+ reset_control_assert(hdptx->rsts[RST_ROPLL].rstc);
+ usleep_range(10, 20);
+ reset_control_deassert(hdptx->rsts[RST_ROPLL].rstc);
+
+ rk_hdptx_multi_reg_write(hdptx, rk_hdtpx_common_cmn_init_seq);
+ rk_hdptx_multi_reg_write(hdptx, rk_hdtpx_frl_cmn_init_seq);
+ rk_hdptx_multi_reg_write(hdptx, rk_hdtpx_frl_ropll_cmn_init_seq);
+
+ regmap_write(hdptx->regmap, CMN_REG(0051), cfg->pms_mdiv);
+ regmap_write(hdptx->regmap, CMN_REG(0055), cfg->pms_mdiv_afc);
+ regmap_write(hdptx->regmap, CMN_REG(0059),
+ (cfg->pms_pdiv << 4) | cfg->pms_refdiv);
+ regmap_write(hdptx->regmap, CMN_REG(005a), cfg->pms_sdiv << 4);
+
+ regmap_update_bits(hdptx->regmap, CMN_REG(005e), ROPLL_SDM_EN_MASK,
+ FIELD_PREP(ROPLL_SDM_EN_MASK, cfg->sdm_en));
+ if (!cfg->sdm_en)
+ regmap_update_bits(hdptx->regmap, CMN_REG(005e), 0xf, 0);
+
+ regmap_update_bits(hdptx->regmap, CMN_REG(0064), ROPLL_SDM_NUM_SIGN_RBR_MASK,
+ FIELD_PREP(ROPLL_SDM_NUM_SIGN_RBR_MASK, cfg->sdm_num_sign));
+
+ regmap_write(hdptx->regmap, CMN_REG(0060), cfg->sdm_deno);
+ regmap_write(hdptx->regmap, CMN_REG(0065), cfg->sdm_num);
+
+ regmap_update_bits(hdptx->regmap, CMN_REG(0069), ROPLL_SDC_N_RBR_MASK,
+ FIELD_PREP(ROPLL_SDC_N_RBR_MASK, cfg->sdc_n));
+
+ regmap_write(hdptx->regmap, CMN_REG(006c), cfg->sdc_num);
+ regmap_write(hdptx->regmap, CMN_REG(0070), cfg->sdc_deno);
+
+ regmap_update_bits(hdptx->regmap, CMN_REG(0086), PLL_PCG_POSTDIV_SEL_MASK,
+ FIELD_PREP(PLL_PCG_POSTDIV_SEL_MASK, cfg->pms_sdiv));
+ regmap_update_bits(hdptx->regmap, CMN_REG(0086), PLL_PCG_CLK_SEL_MASK,
+ FIELD_PREP(PLL_PCG_CLK_SEL_MASK, color_depth));
+
+ rk_hdptx_multi_reg_write(hdptx, rk_hdtpx_common_sb_init_seq);
+ rk_hdptx_multi_reg_write(hdptx, rk_hdtpx_frl_lntop_init_seq);
+
+ rk_hdptx_multi_reg_write(hdptx, rk_hdtpx_common_lane_init_seq);
+ rk_hdptx_multi_reg_write(hdptx, rk_hdtpx_frl_ropll_lane_init_seq);
+
+ if (hdptx->earc_en)
+ rk_hdptx_earc_config(hdptx);
+
+ return rk_hdptx_post_power_up(hdptx);
+}
+
+static int rk_hdptx_lcpll_frl_mode_config(struct rk_hdptx_phy *hdptx,
+ u32 bus_width)
+{
+ u32 bit_rate = bus_width & DATA_RATE_MASK;
+ u8 color_depth = (bus_width & COLOR_DEPTH_MASK) ? 1 : 0;
+ const struct lcpll_config *cfg = NULL;
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(lcpll_cfg); i++)
+ if (bit_rate == lcpll_cfg[i].bit_rate) {
+ cfg = &lcpll_cfg[i];
+ break;
+ }
+
+ if (!cfg) {
+ dev_err(hdptx->dev, "%s cannot find pll cfg\n", __func__);
+ return -EINVAL;
+ }
+
+ rk_hdptx_pre_power_up(hdptx);
+
+ rk_hdptx_multi_reg_write(hdptx, rk_hdtpx_common_cmn_init_seq);
+ rk_hdptx_multi_reg_write(hdptx, rk_hdtpx_frl_cmn_init_seq);
+ rk_hdptx_multi_reg_write(hdptx, rk_hdtpx_frl_lcpll_cmn_init_seq);
+
+ regmap_update_bits(hdptx->regmap, CMN_REG(0008),
+ LCPLL_EN_MASK | LCPLL_LCVCO_MODE_EN_MASK,
+ FIELD_PREP(LCPLL_EN_MASK, 1) |
+ FIELD_PREP(LCPLL_LCVCO_MODE_EN_MASK, cfg->lcvco_mode_en));
+
+ regmap_update_bits(hdptx->regmap, CMN_REG(001e),
+ LCPLL_PI_EN_MASK | LCPLL_100M_CLK_EN_MASK,
+ FIELD_PREP(LCPLL_PI_EN_MASK, cfg->pi_en) |
+ FIELD_PREP(LCPLL_100M_CLK_EN_MASK, cfg->clk_en_100m));
+
+ regmap_write(hdptx->regmap, CMN_REG(0020), cfg->pms_mdiv);
+ regmap_write(hdptx->regmap, CMN_REG(0021), cfg->pms_mdiv_afc);
+ regmap_write(hdptx->regmap, CMN_REG(0022),
+ (cfg->pms_pdiv << 4) | cfg->pms_refdiv);
+ regmap_write(hdptx->regmap, CMN_REG(0023),
+ (cfg->pms_sdiv << 4) | cfg->pms_sdiv);
+ regmap_write(hdptx->regmap, CMN_REG(002a), cfg->sdm_deno);
+ regmap_write(hdptx->regmap, CMN_REG(002b), cfg->sdm_num_sign);
+ regmap_write(hdptx->regmap, CMN_REG(002c), cfg->sdm_num);
+
+ regmap_update_bits(hdptx->regmap, CMN_REG(002d), LCPLL_SDC_N_MASK,
+ FIELD_PREP(LCPLL_SDC_N_MASK, cfg->sdc_n));
+
+ regmap_update_bits(hdptx->regmap, CMN_REG(0086), PLL_PCG_POSTDIV_SEL_MASK,
+ FIELD_PREP(PLL_PCG_POSTDIV_SEL_MASK, cfg->pms_sdiv));
+ regmap_update_bits(hdptx->regmap, CMN_REG(0086), PLL_PCG_CLK_SEL_MASK,
+ FIELD_PREP(PLL_PCG_CLK_SEL_MASK, color_depth));
+
+ rk_hdptx_multi_reg_write(hdptx, rk_hdtpx_common_sb_init_seq);
+ rk_hdptx_multi_reg_write(hdptx, rk_hdtpx_frl_lntop_init_seq);
+
+ rk_hdptx_multi_reg_write(hdptx, rk_hdtpx_common_lane_init_seq);
+ rk_hdptx_multi_reg_write(hdptx, rk_hdtpx_frl_lcpll_lane_init_seq);
+
+ if (hdptx->earc_en)
+ rk_hdptx_earc_config(hdptx);
+
+ return rk_hdptx_post_power_up(hdptx);
+}
+
static int rk_hdptx_phy_power_on(struct phy *phy)
{
struct rk_hdptx_phy *hdptx = phy_get_drvdata(phy);
@@ -865,7 +1280,7 @@ static int rk_hdptx_phy_power_on(struct phy *phy)
* from the HDMI bridge driver until phy_configure_opts_hdmi
* becomes available in the PHY API.
*/
- unsigned int rate = bus_width & 0xfffffff;
+ unsigned int rate = bus_width & DATA_RATE_MASK;
dev_dbg(hdptx->dev, "%s bus_width=%x rate=%u\n",
__func__, bus_width, rate);
@@ -876,7 +1291,20 @@ static int rk_hdptx_phy_power_on(struct phy *phy)
return ret;
}
- ret = rk_hdptx_ropll_tmds_mode_config(hdptx, rate);
+ if (bus_width & HDMI_EARC_MASK)
+ hdptx->earc_en = true;
+ else
+ hdptx->earc_en = false;
+
+ if (bus_width & HDMI_MODE_MASK) {
+ if (rate > 24000000)
+ ret = rk_hdptx_lcpll_frl_mode_config(hdptx, bus_width);
+ else
+ ret = rk_hdptx_ropll_frl_mode_config(hdptx, bus_width);
+ } else {
+ ret = rk_hdptx_ropll_tmds_mode_config(hdptx, rate);
+ }
+
if (ret)
pm_runtime_put(hdptx->dev);
--
Armbian

@ -0,0 +1,222 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Cristian Ciocaltea <cristian.ciocaltea@collabora.com>
Date: Tue, 16 Jan 2024 19:27:40 +0200
Subject: phy: phy-rockchip-samsung-hdptx: Add clock provider
The HDMI PHY PLL can be used as an alternative dclk source to SoC CRU.
It provides more accurate clock rates required to properly support
various display modes, e.g. those relying on non-integer refresh rates.
Also note this only works for HDMI 2.0 or bellow, e.g. cannot be used to
support HDMI 2.1 4K@120Hz mode.
Signed-off-by: Cristian Ciocaltea <cristian.ciocaltea@collabora.com>
---
drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c | 148 +++++++++-
1 file changed, 143 insertions(+), 5 deletions(-)
diff --git a/drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c b/drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c
index 111111111111..222222222222 100644
--- a/drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c
+++ b/drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c
@@ -8,6 +8,7 @@
*/
#include <linux/bitfield.h>
#include <linux/clk.h>
+#include <linux/clk-provider.h>
#include <linux/delay.h>
#include <linux/mfd/syscon.h>
#include <linux/module.h>
@@ -279,6 +280,12 @@ struct rk_hdptx_phy {
int nr_clks;
struct reset_control_bulk_data rsts[RST_MAX];
bool earc_en;
+
+ /* clk provider */
+ struct clk_hw hw;
+ unsigned long rate;
+ int id;
+ int count;
};
static const struct lcpll_config lcpll_cfg[] = {
@@ -1031,6 +1038,8 @@ static int rk_hdptx_ropll_tmds_cmn_config(struct rk_hdptx_phy *hdptx,
const struct ropll_config *cfg = NULL;
struct ropll_config rc = {0};
+ hdptx->rate = rate * 100;
+
if (color_depth)
rate = rate * 10 / 8;
@@ -1315,11 +1324,13 @@ static int rk_hdptx_phy_power_off(struct phy *phy)
{
struct rk_hdptx_phy *hdptx = phy_get_drvdata(phy);
u32 val;
- int ret;
+ int ret = 0;
- ret = regmap_read(hdptx->grf, GRF_HDPTX_STATUS, &val);
- if (ret == 0 && (val & HDPTX_O_PLL_LOCK_DONE))
- rk_hdptx_phy_disable(hdptx);
+ if (hdptx->count == 0) {
+ ret = regmap_read(hdptx->grf, GRF_HDPTX_STATUS, &val);
+ if (ret == 0 && (val & HDPTX_O_PLL_LOCK_DONE))
+ rk_hdptx_phy_disable(hdptx);
+ }
pm_runtime_put(hdptx->dev);
@@ -1332,6 +1343,129 @@ static const struct phy_ops rk_hdptx_phy_ops = {
.owner = THIS_MODULE,
};
+static struct rk_hdptx_phy *to_rk_hdptx_phy(struct clk_hw *hw)
+{
+ return container_of(hw, struct rk_hdptx_phy, hw);
+}
+
+static int rk_hdptx_phy_clk_prepare(struct clk_hw *hw)
+{
+ struct rk_hdptx_phy *hdptx = to_rk_hdptx_phy(hw);
+ int ret;
+
+ ret = pm_runtime_resume_and_get(hdptx->dev);
+ if (ret) {
+ dev_err(hdptx->dev, "Failed to resume phy clk: %d\n", ret);
+ return ret;
+ }
+
+ if (!hdptx->count && hdptx->rate) {
+ ret = rk_hdptx_ropll_tmds_cmn_config(hdptx, hdptx->rate / 100);
+ if (ret < 0) {
+ dev_err(hdptx->dev, "Failed to init PHY PLL: %d\n", ret);
+ pm_runtime_put(hdptx->dev);
+ return ret;
+ }
+ }
+
+ hdptx->count++;
+
+ return 0;
+}
+
+static void rk_hdptx_phy_clk_unprepare(struct clk_hw *hw)
+{
+ struct rk_hdptx_phy *hdptx = to_rk_hdptx_phy(hw);
+
+ if (hdptx->count == 1) {
+ u32 val;
+ int ret = regmap_read(hdptx->grf, GRF_HDPTX_STATUS, &val);
+ if (ret == 0 && (val & HDPTX_O_PLL_LOCK_DONE))
+ rk_hdptx_phy_disable(hdptx);
+ }
+
+ hdptx->count--;
+ pm_runtime_put(hdptx->dev);
+}
+
+static unsigned long rk_hdptx_phy_clk_recalc_rate(struct clk_hw *hw,
+ unsigned long parent_rate)
+{
+ struct rk_hdptx_phy *hdptx = to_rk_hdptx_phy(hw);
+
+ return hdptx->rate;
+}
+
+static long rk_hdptx_phy_clk_round_rate(struct clk_hw *hw, unsigned long rate,
+ unsigned long *parent_rate)
+{
+ const struct ropll_config *cfg = NULL;
+ u32 bit_rate = rate / 100;
+ int i;
+
+ if (rate > HDMI20_MAX_RATE)
+ return rate;
+
+ for (i = 0; i < ARRAY_SIZE(ropll_tmds_cfg); i++)
+ if (bit_rate == ropll_tmds_cfg[i].bit_rate) {
+ cfg = &ropll_tmds_cfg[i];
+ break;
+ }
+
+ if (!cfg && !rk_hdptx_phy_clk_pll_calc(bit_rate, NULL))
+ return -EINVAL;
+
+ return rate;
+}
+
+static int rk_hdptx_phy_clk_set_rate(struct clk_hw *hw, unsigned long rate,
+ unsigned long parent_rate)
+{
+ struct rk_hdptx_phy *hdptx = to_rk_hdptx_phy(hw);
+ u32 val;
+ int ret = regmap_read(hdptx->grf, GRF_HDPTX_STATUS, &val);
+ if (ret == 0 && (val & HDPTX_O_PLL_LOCK_DONE))
+ rk_hdptx_phy_disable(hdptx);
+
+ return rk_hdptx_ropll_tmds_cmn_config(hdptx, rate / 100);
+}
+
+static const struct clk_ops hdptx_phy_clk_ops = {
+ .prepare = rk_hdptx_phy_clk_prepare,
+ .unprepare = rk_hdptx_phy_clk_unprepare,
+ .recalc_rate = rk_hdptx_phy_clk_recalc_rate,
+ .round_rate = rk_hdptx_phy_clk_round_rate,
+ .set_rate = rk_hdptx_phy_clk_set_rate,
+};
+
+static int rk_hdptx_phy_clk_register(struct rk_hdptx_phy *hdptx)
+{
+ struct device *dev = hdptx->dev;
+ const char *name, *pname;
+ struct clk *refclk;
+ int ret;
+
+ refclk = devm_clk_get(dev, "ref");
+ if (IS_ERR(refclk))
+ return dev_err_probe(dev, PTR_ERR(refclk),
+ "Failed to get ref clock\n");
+
+ pname = __clk_get_name(refclk);
+ name = hdptx->id ? "clk_hdmiphy_pixel1" : "clk_hdmiphy_pixel0";
+ hdptx->hw.init = CLK_HW_INIT(name, pname, &hdptx_phy_clk_ops,
+ CLK_GET_RATE_NOCACHE);
+
+ ret = devm_clk_hw_register(dev, &hdptx->hw);
+ if (ret)
+ return dev_err_probe(dev, ret, "Failed to register clock\n");
+
+ ret = devm_of_clk_add_hw_provider(dev, of_clk_hw_simple_get, &hdptx->hw);
+ if (ret)
+ return dev_err_probe(dev, ret,
+ "Failed to register clk provider\n");
+ return 0;
+}
+
static int rk_hdptx_phy_runtime_suspend(struct device *dev)
{
struct rk_hdptx_phy *hdptx = dev_get_drvdata(dev);
@@ -1367,6 +1501,10 @@ static int rk_hdptx_phy_probe(struct platform_device *pdev)
hdptx->dev = dev;
+ hdptx->id = of_alias_get_id(dev->of_node, "hdptxphy");
+ if (hdptx->id < 0)
+ hdptx->id = 0;
+
regs = devm_platform_ioremap_resource(pdev, 0);
if (IS_ERR(regs))
return dev_err_probe(dev, PTR_ERR(regs),
@@ -1426,7 +1564,7 @@ static int rk_hdptx_phy_probe(struct platform_device *pdev)
reset_control_deassert(hdptx->rsts[RST_CMN].rstc);
reset_control_deassert(hdptx->rsts[RST_INIT].rstc);
- return 0;
+ return rk_hdptx_phy_clk_register(hdptx);
}
static const struct dev_pm_ops rk_hdptx_phy_pm_ops = {
--
Armbian

@ -0,0 +1,679 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Cristian Ciocaltea <cristian.ciocaltea@collabora.com>
Date: Fri, 3 Nov 2023 19:58:02 +0200
Subject: drm/rockchip: vop2: Improve display modes handling on rk3588
The initial vop2 support for rk3588 in mainline is not able to handle
all display modes supported by connected displays, e.g.
2560x1440-75.00Hz, 2048x1152-60.00Hz, 1024x768-60.00Hz.
Additionally, it doesn't cope with non-integer refresh rates like 59.94,
29.97, 23.98, etc.
Improve HDMI0 clocking in order to support the additional display modes.
Fixes: 5a028e8f062f ("drm/rockchip: vop2: Add support for rk3588")
Signed-off-by: Cristian Ciocaltea <cristian.ciocaltea@collabora.com>
---
drivers/gpu/drm/rockchip/rockchip_drm_vop2.c | 553 +++++++++-
1 file changed, 552 insertions(+), 1 deletion(-)
diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop2.c b/drivers/gpu/drm/rockchip/rockchip_drm_vop2.c
index 111111111111..222222222222 100644
--- a/drivers/gpu/drm/rockchip/rockchip_drm_vop2.c
+++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop2.c
@@ -5,6 +5,8 @@
*/
#include <linux/bitfield.h>
#include <linux/clk.h>
+#include <linux/clk-provider.h>
+#include <linux/clkdev.h>
#include <linux/component.h>
#include <linux/delay.h>
#include <linux/iopoll.h>
@@ -212,6 +214,10 @@ struct vop2 {
struct clk *hclk;
struct clk *aclk;
struct clk *pclk;
+ // [CC:] hack to support additional display modes
+ struct clk *hdmi0_phy_pll;
+ /* list_head of internal clk */
+ struct list_head clk_list_head;
/* optional internal rgb encoder */
struct rockchip_rgb *rgb;
@@ -220,6 +226,19 @@ struct vop2 {
struct vop2_win win[];
};
+struct vop2_clk {
+ struct vop2 *vop2;
+ struct list_head list;
+ unsigned long rate;
+ struct clk_hw hw;
+ struct clk_divider div;
+ int div_val;
+ u8 parent_index;
+};
+
+#define to_vop2_clk(_hw) container_of(_hw, struct vop2_clk, hw)
+#define VOP2_MAX_DCLK_RATE 600000 /* kHz */
+
#define vop2_output_if_is_hdmi(x) ((x) == ROCKCHIP_VOP2_EP_HDMI0 || \
(x) == ROCKCHIP_VOP2_EP_HDMI1)
@@ -1476,9 +1495,30 @@ static bool vop2_crtc_mode_fixup(struct drm_crtc *crtc,
const struct drm_display_mode *mode,
struct drm_display_mode *adj_mode)
{
+ struct vop2_video_port *vp = to_vop2_video_port(crtc);
+ struct drm_connector *connector;
+ struct drm_connector_list_iter conn_iter;
+ struct drm_crtc_state *new_crtc_state = container_of(mode, struct drm_crtc_state, mode);
drm_mode_set_crtcinfo(adj_mode, CRTC_INTERLACE_HALVE_V |
CRTC_STEREO_DOUBLE);
+ if (mode->flags & DRM_MODE_FLAG_DBLCLK)
+ adj_mode->crtc_clock *= 2;
+
+ drm_connector_list_iter_begin(crtc->dev, &conn_iter);
+ drm_for_each_connector_iter(connector, &conn_iter) {
+ if ((new_crtc_state->connector_mask & drm_connector_mask(connector)) &&
+ ((connector->connector_type == DRM_MODE_CONNECTOR_DisplayPort) ||
+ (connector->connector_type == DRM_MODE_CONNECTOR_HDMIA))) {
+ drm_connector_list_iter_end(&conn_iter);
+ return true;
+ }
+ }
+ drm_connector_list_iter_end(&conn_iter);
+
+ if (adj_mode->crtc_clock <= VOP2_MAX_DCLK_RATE)
+ adj_mode->crtc_clock = DIV_ROUND_UP(clk_round_rate(vp->dclk,
+ adj_mode->crtc_clock * 1000), 1000);
return true;
}
@@ -1663,6 +1703,31 @@ static unsigned long rk3588_calc_dclk(unsigned long child_clk, unsigned long max
return 0;
}
+static struct vop2_clk *vop2_clk_get(struct vop2 *vop2, const char *name);
+
+static int vop2_cru_set_rate(struct vop2_clk *if_pixclk, struct vop2_clk *if_dclk)
+{
+ int ret = 0;
+
+ if (if_pixclk) {
+ ret = clk_set_rate(if_pixclk->hw.clk, if_pixclk->rate);
+ if (ret < 0) {
+ DRM_DEV_ERROR(if_pixclk->vop2->dev, "set %s to %ld failed: %d\n",
+ clk_hw_get_name(&if_pixclk->hw), if_pixclk->rate, ret);
+ return ret;
+ }
+ }
+
+ if (if_dclk) {
+ ret = clk_set_rate(if_dclk->hw.clk, if_dclk->rate);
+ if (ret < 0)
+ DRM_DEV_ERROR(if_dclk->vop2->dev, "set %s to %ld failed %d\n",
+ clk_hw_get_name(&if_dclk->hw), if_dclk->rate, ret);
+ }
+
+ return ret;
+}
+
/*
* 4 pixclk/cycle on rk3588
* RGB/eDP/HDMI: if_pixclk >= dclk_core
@@ -1686,6 +1751,72 @@ static unsigned long rk3588_calc_cru_cfg(struct vop2_video_port *vp, int id,
int K = 1;
if (vop2_output_if_is_hdmi(id)) {
+ if (vop2->data->soc_id == 3588 && id == ROCKCHIP_VOP2_EP_HDMI0 &&
+ vop2->hdmi0_phy_pll) {
+ const char *clk_src_name = "hdmi_edp0_clk_src";
+ const char *clk_parent_name = "dclk";
+ const char *pixclk_name = "hdmi_edp0_pixclk";
+ const char *dclk_name = "hdmi_edp0_dclk";
+ struct vop2_clk *if_clk_src, *if_clk_parent, *if_pixclk, *if_dclk, *dclk, *dclk_core, *dclk_out;
+ char clk_name[32];
+ int ret;
+
+ if_clk_src = vop2_clk_get(vop2, clk_src_name);
+ snprintf(clk_name, sizeof(clk_name), "%s%d", clk_parent_name, vp->id);
+ if_clk_parent = vop2_clk_get(vop2, clk_name);
+ if_pixclk = vop2_clk_get(vop2, pixclk_name);
+ if_dclk = vop2_clk_get(vop2, dclk_name);
+ if (!if_pixclk || !if_clk_parent) {
+ DRM_DEV_ERROR(vop2->dev, "failed to get connector interface clk\n");
+ return -ENODEV;
+ }
+
+ ret = clk_set_parent(if_clk_src->hw.clk, if_clk_parent->hw.clk);
+ if (ret < 0) {
+ DRM_DEV_ERROR(vop2->dev, "failed to set parent(%s) for %s: %d\n",
+ __clk_get_name(if_clk_parent->hw.clk),
+ __clk_get_name(if_clk_src->hw.clk), ret);
+ return ret;
+ }
+
+ if (output_mode == ROCKCHIP_OUT_MODE_YUV420)
+ K = 2;
+
+ if_pixclk->rate = (dclk_core_rate << 1) / K;
+ if_dclk->rate = dclk_core_rate / K;
+
+ snprintf(clk_name, sizeof(clk_name), "dclk_core%d", vp->id);
+ dclk_core = vop2_clk_get(vop2, clk_name);
+
+ snprintf(clk_name, sizeof(clk_name), "dclk_out%d", vp->id);
+ dclk_out = vop2_clk_get(vop2, clk_name);
+
+ snprintf(clk_name, sizeof(clk_name), "dclk%d", vp->id);
+ dclk = vop2_clk_get(vop2, clk_name);
+ if (v_pixclk <= (VOP2_MAX_DCLK_RATE * 1000)) {
+ if (output_mode == ROCKCHIP_OUT_MODE_YUV420)
+ v_pixclk = v_pixclk >> 1;
+ } else {
+ v_pixclk = v_pixclk >> 2;
+ }
+ clk_set_rate(dclk->hw.clk, v_pixclk);
+
+ if (dclk_core_rate > if_pixclk->rate) {
+ clk_set_rate(dclk_core->hw.clk, dclk_core_rate);
+ ret = vop2_cru_set_rate(if_pixclk, if_dclk);
+ } else {
+ ret = vop2_cru_set_rate(if_pixclk, if_dclk);
+ clk_set_rate(dclk_core->hw.clk, dclk_core_rate);
+ }
+
+ *dclk_core_div = dclk_core->div_val;
+ *dclk_out_div = dclk_out->div_val;
+ *if_pixclk_div = if_pixclk->div_val;
+ *if_dclk_div = if_dclk->div_val;
+
+ return dclk->rate;
+ }
+
/*
* K = 2: dclk_core = if_pixclk_rate > if_dclk_rate
* K = 1: dclk_core = hdmie_edp_dclk > if_pixclk_rate
@@ -1917,6 +2048,22 @@ static int us_to_vertical_line(struct drm_display_mode *mode, int us)
return us * mode->clock / mode->htotal / 1000;
}
+// [CC:] rework virtual clock
+static struct vop2_clk *vop2_clk_get(struct vop2 *vop2, const char *name)
+{
+ struct vop2_clk *clk, *n;
+
+ if (!name)
+ return NULL;
+
+ list_for_each_entry_safe(clk, n, &vop2->clk_list_head, list) {
+ if (!strcmp(clk_hw_get_name(&clk->hw), name))
+ return clk;
+ }
+
+ return NULL;
+}
+
static void vop2_crtc_atomic_enable(struct drm_crtc *crtc,
struct drm_atomic_state *state)
{
@@ -1944,6 +2091,8 @@ static void vop2_crtc_atomic_enable(struct drm_crtc *crtc,
u32 val, polflags;
int ret;
struct drm_encoder *encoder;
+ char clk_name[32];
+ struct vop2_clk *dclk;
drm_dbg(vop2->drm, "Update mode to %dx%d%s%d, type: %d for vp%d\n",
hdisplay, vdisplay, mode->flags & DRM_MODE_FLAG_INTERLACE ? "i" : "p",
@@ -2044,11 +2193,38 @@ static void vop2_crtc_atomic_enable(struct drm_crtc *crtc,
if (mode->flags & DRM_MODE_FLAG_DBLCLK) {
dsp_ctrl |= RK3568_VP_DSP_CTRL__CORE_DCLK_DIV;
- clock *= 2;
+ // [CC:] done via mode_fixup
+ // clock *= 2;
}
vop2_vp_write(vp, RK3568_VP_MIPI_CTRL, 0);
+ snprintf(clk_name, sizeof(clk_name), "dclk%d", vp->id);
+ dclk = vop2_clk_get(vop2, clk_name);
+ if (dclk) {
+ /*
+ * use HDMI_PHY_PLL as dclk source under 4K@60 if it is available,
+ * otherwise use system cru as dclk source.
+ */
+ drm_for_each_encoder_mask(encoder, crtc->dev, crtc_state->encoder_mask) {
+ struct rockchip_encoder *rkencoder = to_rockchip_encoder(encoder);
+
+ // [CC:] Using PHY PLL to handle all display modes
+ if (rkencoder->crtc_endpoint_id == ROCKCHIP_VOP2_EP_HDMI0) {
+ clk_get_rate(vop2->hdmi0_phy_pll);
+
+ if (mode->crtc_clock <= VOP2_MAX_DCLK_RATE) {
+ ret = clk_set_parent(vp->dclk, vop2->hdmi0_phy_pll);
+ if (ret < 0)
+ DRM_WARN("failed to set clock parent for %s\n",
+ __clk_get_name(vp->dclk));
+ }
+
+ clock = dclk->rate;
+ }
+ }
+ }
+
clk_set_rate(vp->dclk, clock);
vop2_post_config(crtc);
@@ -2504,7 +2680,43 @@ static void vop2_crtc_atomic_flush(struct drm_crtc *crtc,
spin_unlock_irq(&crtc->dev->event_lock);
}
+static enum drm_mode_status
+vop2_crtc_mode_valid(struct drm_crtc *crtc, const struct drm_display_mode *mode)
+{
+ struct rockchip_crtc_state *vcstate = to_rockchip_crtc_state(crtc->state);
+ struct vop2_video_port *vp = to_vop2_video_port(crtc);
+ struct vop2 *vop2 = vp->vop2;
+ const struct vop2_data *vop2_data = vop2->data;
+ const struct vop2_video_port_data *vp_data = &vop2_data->vp[vp->id];
+ int request_clock = mode->clock;
+ int clock;
+
+ if (mode->hdisplay > vp_data->max_output.width)
+ return MODE_BAD_HVALUE;
+
+ if (mode->flags & DRM_MODE_FLAG_DBLCLK)
+ request_clock *= 2;
+
+ if (request_clock <= VOP2_MAX_DCLK_RATE) {
+ clock = request_clock;
+ } else {
+ request_clock = request_clock >> 2;
+ clock = clk_round_rate(vp->dclk, request_clock * 1000) / 1000;
+ }
+
+ /*
+ * Hdmi or DisplayPort request a Accurate clock.
+ */
+ if (vcstate->output_type == DRM_MODE_CONNECTOR_HDMIA ||
+ vcstate->output_type == DRM_MODE_CONNECTOR_DisplayPort)
+ if (clock != request_clock)
+ return MODE_CLOCK_RANGE;
+
+ return MODE_OK;
+}
+
static const struct drm_crtc_helper_funcs vop2_crtc_helper_funcs = {
+ .mode_valid = vop2_crtc_mode_valid,
.mode_fixup = vop2_crtc_mode_fixup,
.atomic_check = vop2_crtc_atomic_check,
.atomic_begin = vop2_crtc_atomic_begin,
@@ -3074,6 +3286,336 @@ static const struct regmap_config vop2_regmap_config = {
.cache_type = REGCACHE_MAPLE,
};
+/*
+ * BEGIN virtual clock
+ */
+#define PLL_RATE_MIN 30000000
+
+#define cru_dbg(format, ...) do { \
+ if (cru_debug) \
+ pr_info("%s: " format, __func__, ## __VA_ARGS__); \
+ } while (0)
+
+#define PNAME(x) static const char *const x[]
+
+enum vop_clk_branch_type {
+ branch_mux,
+ branch_divider,
+ branch_factor,
+ branch_virtual,
+};
+
+#define VIR(cname) \
+ { \
+ .branch_type = branch_virtual, \
+ .name = cname, \
+ }
+
+
+#define MUX(cname, pnames, f) \
+ { \
+ .branch_type = branch_mux, \
+ .name = cname, \
+ .parent_names = pnames, \
+ .num_parents = ARRAY_SIZE(pnames), \
+ .flags = f, \
+ }
+
+#define FACTOR(cname, pname, f) \
+ { \
+ .branch_type = branch_factor, \
+ .name = cname, \
+ .parent_names = (const char *[]){ pname }, \
+ .num_parents = 1, \
+ .flags = f, \
+ }
+
+#define DIV(cname, pname, f, w) \
+ { \
+ .branch_type = branch_divider, \
+ .name = cname, \
+ .parent_names = (const char *[]){ pname }, \
+ .num_parents = 1, \
+ .flags = f, \
+ .div_width = w, \
+ }
+
+struct vop2_clk_branch {
+ enum vop_clk_branch_type branch_type;
+ const char *name;
+ const char *const *parent_names;
+ u8 num_parents;
+ unsigned long flags;
+ u8 div_shift;
+ u8 div_width;
+ u8 div_flags;
+};
+
+PNAME(mux_port0_dclk_src_p) = { "dclk0", "dclk1" };
+PNAME(mux_port2_dclk_src_p) = { "dclk2", "dclk1" };
+PNAME(mux_dp_pixclk_p) = { "dclk_out0", "dclk_out1", "dclk_out2" };
+PNAME(mux_hdmi_edp_clk_src_p) = { "dclk0", "dclk1", "dclk2" };
+PNAME(mux_mipi_clk_src_p) = { "dclk_out1", "dclk_out2", "dclk_out3" };
+PNAME(mux_dsc_8k_clk_src_p) = { "dclk0", "dclk1", "dclk2", "dclk3" };
+PNAME(mux_dsc_4k_clk_src_p) = { "dclk0", "dclk1", "dclk2", "dclk3" };
+
+/*
+ * We only use this clk driver calculate the div
+ * of dclk_core/dclk_out/if_pixclk/if_dclk and
+ * the rate of the dclk from the soc.
+ *
+ * We don't touch the cru in the vop here, as
+ * these registers has special read andy write
+ * limits.
+ */
+static struct vop2_clk_branch rk3588_vop_clk_branches[] = {
+ VIR("dclk0"),
+ VIR("dclk1"),
+ VIR("dclk2"),
+ VIR("dclk3"),
+
+ MUX("port0_dclk_src", mux_port0_dclk_src_p, CLK_SET_RATE_PARENT | CLK_SET_RATE_NO_REPARENT),
+ DIV("dclk_core0", "port0_dclk_src", CLK_SET_RATE_PARENT, 2),
+ DIV("dclk_out0", "port0_dclk_src", CLK_SET_RATE_PARENT, 2),
+
+ FACTOR("port1_dclk_src", "dclk1", CLK_SET_RATE_PARENT),
+ DIV("dclk_core1", "port1_dclk_src", CLK_SET_RATE_PARENT, 2),
+ DIV("dclk_out1", "port1_dclk_src", CLK_SET_RATE_PARENT, 2),
+
+ MUX("port2_dclk_src", mux_port2_dclk_src_p, CLK_SET_RATE_PARENT | CLK_SET_RATE_NO_REPARENT),
+ DIV("dclk_core2", "port2_dclk_src", CLK_SET_RATE_PARENT, 2),
+ DIV("dclk_out2", "port2_dclk_src", CLK_SET_RATE_PARENT, 2),
+
+ FACTOR("port3_dclk_src", "dclk3", CLK_SET_RATE_PARENT),
+ DIV("dclk_core3", "port3_dclk_src", CLK_SET_RATE_PARENT, 2),
+ DIV("dclk_out3", "port3_dclk_src", CLK_SET_RATE_PARENT, 2),
+
+ MUX("dp0_pixclk", mux_dp_pixclk_p, CLK_SET_RATE_PARENT | CLK_SET_RATE_NO_REPARENT),
+ MUX("dp1_pixclk", mux_dp_pixclk_p, CLK_SET_RATE_PARENT | CLK_SET_RATE_NO_REPARENT),
+
+ MUX("hdmi_edp0_clk_src", mux_hdmi_edp_clk_src_p,
+ CLK_SET_RATE_PARENT | CLK_SET_RATE_NO_REPARENT),
+ DIV("hdmi_edp0_dclk", "hdmi_edp0_clk_src", 0, 2),
+ DIV("hdmi_edp0_pixclk", "hdmi_edp0_clk_src", CLK_SET_RATE_PARENT, 1),
+
+ MUX("hdmi_edp1_clk_src", mux_hdmi_edp_clk_src_p,
+ CLK_SET_RATE_PARENT | CLK_SET_RATE_NO_REPARENT),
+ DIV("hdmi_edp1_dclk", "hdmi_edp1_clk_src", 0, 2),
+ DIV("hdmi_edp1_pixclk", "hdmi_edp1_clk_src", CLK_SET_RATE_PARENT, 1),
+
+ MUX("mipi0_clk_src", mux_mipi_clk_src_p, CLK_SET_RATE_PARENT | CLK_SET_RATE_NO_REPARENT),
+ DIV("mipi0_pixclk", "mipi0_clk_src", CLK_SET_RATE_PARENT, 2),
+
+ MUX("mipi1_clk_src", mux_mipi_clk_src_p, CLK_SET_RATE_PARENT | CLK_SET_RATE_NO_REPARENT),
+ DIV("mipi1_pixclk", "mipi1_clk_src", CLK_SET_RATE_PARENT, 2),
+
+ FACTOR("rgb_pixclk", "port3_dclk_src", CLK_SET_RATE_PARENT),
+
+ MUX("dsc_8k_txp_clk_src", mux_dsc_8k_clk_src_p, CLK_SET_RATE_PARENT | CLK_SET_RATE_NO_REPARENT),
+ DIV("dsc_8k_txp_clk", "dsc_8k_txp_clk_src", 0, 2),
+ DIV("dsc_8k_pxl_clk", "dsc_8k_txp_clk_src", 0, 2),
+ DIV("dsc_8k_cds_clk", "dsc_8k_txp_clk_src", 0, 2),
+
+ MUX("dsc_4k_txp_clk_src", mux_dsc_4k_clk_src_p, CLK_SET_RATE_PARENT | CLK_SET_RATE_NO_REPARENT),
+ DIV("dsc_4k_txp_clk", "dsc_4k_txp_clk_src", 0, 2),
+ DIV("dsc_4k_pxl_clk", "dsc_4k_txp_clk_src", 0, 2),
+ DIV("dsc_4k_cds_clk", "dsc_4k_txp_clk_src", 0, 2),
+};
+
+static unsigned long clk_virtual_recalc_rate(struct clk_hw *hw,
+ unsigned long parent_rate)
+{
+ struct vop2_clk *vop2_clk = to_vop2_clk(hw);
+
+ return (unsigned long)vop2_clk->rate;
+}
+
+static long clk_virtual_round_rate(struct clk_hw *hw, unsigned long rate,
+ unsigned long *prate)
+{
+ struct vop2_clk *vop2_clk = to_vop2_clk(hw);
+
+ vop2_clk->rate = rate;
+
+ return rate;
+}
+
+static int clk_virtual_set_rate(struct clk_hw *hw, unsigned long rate,
+ unsigned long parent_rate)
+{
+ return 0;
+}
+
+const struct clk_ops clk_virtual_ops = {
+ .round_rate = clk_virtual_round_rate,
+ .set_rate = clk_virtual_set_rate,
+ .recalc_rate = clk_virtual_recalc_rate,
+};
+
+static u8 vop2_mux_get_parent(struct clk_hw *hw)
+{
+ struct vop2_clk *vop2_clk = to_vop2_clk(hw);
+
+ // cru_dbg("%s index: %d\n", clk_hw_get_name(hw), vop2_clk->parent_index);
+ return vop2_clk->parent_index;
+}
+
+static int vop2_mux_set_parent(struct clk_hw *hw, u8 index)
+{
+ struct vop2_clk *vop2_clk = to_vop2_clk(hw);
+
+ vop2_clk->parent_index = index;
+
+ // cru_dbg("%s index: %d\n", clk_hw_get_name(hw), index);
+ return 0;
+}
+
+static int vop2_clk_mux_determine_rate(struct clk_hw *hw,
+ struct clk_rate_request *req)
+{
+ // cru_dbg("%s %ld(min: %ld max: %ld)\n",
+ // clk_hw_get_name(hw), req->rate, req->min_rate, req->max_rate);
+ return __clk_mux_determine_rate(hw, req);
+}
+
+static const struct clk_ops vop2_mux_clk_ops = {
+ .get_parent = vop2_mux_get_parent,
+ .set_parent = vop2_mux_set_parent,
+ .determine_rate = vop2_clk_mux_determine_rate,
+};
+
+#define div_mask(width) ((1 << (width)) - 1)
+
+static int vop2_div_get_val(unsigned long rate, unsigned long parent_rate)
+{
+ unsigned int div, value;
+
+ div = DIV_ROUND_UP_ULL((u64)parent_rate, rate);
+
+ value = ilog2(div);
+
+ return value;
+}
+
+static unsigned long vop2_clk_div_recalc_rate(struct clk_hw *hw,
+ unsigned long parent_rate)
+{
+ struct vop2_clk *vop2_clk = to_vop2_clk(hw);
+ unsigned long rate;
+ unsigned int div;
+
+ div = 1 << vop2_clk->div_val;
+ rate = parent_rate / div;
+
+ // cru_dbg("%s rate: %ld(prate: %ld)\n", clk_hw_get_name(hw), rate, parent_rate);
+ return rate;
+}
+
+static long vop2_clk_div_round_rate(struct clk_hw *hw, unsigned long rate,
+ unsigned long *prate)
+{
+ struct vop2_clk *vop2_clk = to_vop2_clk(hw);
+
+ if (clk_hw_get_flags(hw) & CLK_SET_RATE_PARENT) {
+ if (*prate < rate)
+ *prate = rate;
+ if ((*prate >> vop2_clk->div.width) > rate)
+ *prate = rate;
+
+ if ((*prate % rate))
+ *prate = rate;
+
+ /* SOC PLL can't output a too low pll freq */
+ if (*prate < PLL_RATE_MIN)
+ *prate = rate << vop2_clk->div.width;
+ }
+
+ // cru_dbg("%s rate: %ld(prate: %ld)\n", clk_hw_get_name(hw), rate, *prate);
+ return rate;
+}
+
+static int vop2_clk_div_set_rate(struct clk_hw *hw, unsigned long rate, unsigned long parent_rate)
+{
+ struct vop2_clk *vop2_clk = to_vop2_clk(hw);
+ int div_val;
+
+ div_val = vop2_div_get_val(rate, parent_rate);
+ vop2_clk->div_val = div_val;
+
+ // cru_dbg("%s prate: %ld rate: %ld div_val: %d\n",
+ // clk_hw_get_name(hw), parent_rate, rate, div_val);
+ return 0;
+}
+
+static const struct clk_ops vop2_div_clk_ops = {
+ .recalc_rate = vop2_clk_div_recalc_rate,
+ .round_rate = vop2_clk_div_round_rate,
+ .set_rate = vop2_clk_div_set_rate,
+};
+
+static struct clk *vop2_clk_register(struct vop2 *vop2, struct vop2_clk_branch *branch)
+{
+ struct clk_init_data init = {};
+ struct vop2_clk *vop2_clk;
+ struct clk *clk;
+
+ vop2_clk = devm_kzalloc(vop2->dev, sizeof(*vop2_clk), GFP_KERNEL);
+ if (!vop2_clk)
+ return ERR_PTR(-ENOMEM);
+
+ vop2_clk->vop2 = vop2;
+ vop2_clk->hw.init = &init;
+ vop2_clk->div.shift = branch->div_shift;
+ vop2_clk->div.width = branch->div_width;
+
+ init.name = branch->name;
+ init.flags = branch->flags;
+ init.num_parents = branch->num_parents;
+ init.parent_names = branch->parent_names;
+ if (branch->branch_type == branch_divider) {
+ init.ops = &vop2_div_clk_ops;
+ } else if (branch->branch_type == branch_virtual) {
+ init.ops = &clk_virtual_ops;
+ init.num_parents = 0;
+ init.parent_names = NULL;
+ } else {
+ init.ops = &vop2_mux_clk_ops;
+ }
+
+ clk = devm_clk_register(vop2->dev, &vop2_clk->hw);
+ if (!IS_ERR(clk))
+ list_add_tail(&vop2_clk->list, &vop2->clk_list_head);
+ else
+ DRM_DEV_ERROR(vop2->dev, "Register %s failed\n", branch->name);
+
+ return clk;
+}
+
+static int vop2_clk_init(struct vop2 *vop2)
+{
+ struct vop2_clk_branch *branch = rk3588_vop_clk_branches;
+ unsigned int nr_clk = ARRAY_SIZE(rk3588_vop_clk_branches);
+ unsigned int idx;
+ struct vop2_clk *clk, *n;
+
+ INIT_LIST_HEAD(&vop2->clk_list_head);
+
+ if (vop2->data->soc_id < 3588 || vop2->hdmi0_phy_pll == NULL)
+ return 0;
+
+ list_for_each_entry_safe(clk, n, &vop2->clk_list_head, list) {
+ list_del(&clk->list);
+ }
+
+ for (idx = 0; idx < nr_clk; idx++, branch++)
+ vop2_clk_register(vop2, branch);
+
+ return 0;
+}
+/*
+ * END virtual clock
+ */
+
static int vop2_bind(struct device *dev, struct device *master, void *data)
{
struct platform_device *pdev = to_platform_device(dev);
@@ -3167,6 +3709,12 @@ static int vop2_bind(struct device *dev, struct device *master, void *data)
return PTR_ERR(vop2->pclk);
}
+ vop2->hdmi0_phy_pll = devm_clk_get_optional(vop2->drm->dev, "hdmi0_phy_pll");
+ if (IS_ERR(vop2->hdmi0_phy_pll)) {
+ DRM_DEV_ERROR(vop2->dev, "failed to get hdmi0_phy_pll source\n");
+ return PTR_ERR(vop2->hdmi0_phy_pll);
+ }
+
vop2->irq = platform_get_irq(pdev, 0);
if (vop2->irq < 0) {
drm_err(vop2->drm, "cannot find irq for vop2\n");
@@ -3183,6 +3731,9 @@ static int vop2_bind(struct device *dev, struct device *master, void *data)
if (ret)
return ret;
+ // [CC:] rework virtual clock
+ vop2_clk_init(vop2);
+
ret = vop2_find_rgb_encoder(vop2);
if (ret >= 0) {
vop2->rgb = rockchip_rgb_init(dev, &vop2->vps[ret].crtc,
--
Armbian

@ -0,0 +1,34 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Muhammed Efe Cetin <efectn@protonmail.com>
Date: Mon, 13 May 2024 20:29:49 +0300
Subject: arm64: dts: rockchip: rk3588: add VDPU and RGA2 nodes
---
arch/arm64/boot/dts/rockchip/rk3588s.dtsi | 11 ++++++++++
1 file changed, 11 insertions(+)
diff --git a/arch/arm64/boot/dts/rockchip/rk3588s.dtsi b/arch/arm64/boot/dts/rockchip/rk3588s.dtsi
index 111111111111..222222222222 100644
--- a/arch/arm64/boot/dts/rockchip/rk3588s.dtsi
+++ b/arch/arm64/boot/dts/rockchip/rk3588s.dtsi
@@ -726,6 +726,17 @@ mmu600_php: iommu@fcb00000 {
status = "disabled";
};
+ rga: rga@fdb80000 {
+ compatible = "rockchip,rk3568-rga", "rockchip,rk3288-rga";
+ reg = <0x0 0xfdb80000 0x0 0x1000>;
+ interrupts = <GIC_SPI 116 IRQ_TYPE_LEVEL_HIGH 0>;
+ clocks = <&cru ACLK_RGA2>, <&cru HCLK_RGA2>, <&cru CLK_RGA2_CORE>;
+ clock-names = "aclk", "hclk", "sclk";
+ resets = <&cru SRST_RGA2_CORE>, <&cru SRST_A_RGA2>, <&cru SRST_H_RGA2>;
+ reset-names = "core", "axi", "ahb";
+ power-domains = <&power RK3588_PD_VDPU>;
+ };
+
pmu1grf: syscon@fd58a000 {
compatible = "rockchip,rk3588-pmugrf", "syscon", "simple-mfd";
reg = <0x0 0xfd58a000 0x0 0x10000>;
--
Armbian

File diff suppressed because it is too large Load Diff

@ -0,0 +1,25 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: ColorfulRhino <unknown-email@domain.tld>
Date: Wed, 12 Jun 2024 12:17:18 +0200
Subject: Fix HDMI controller patch at
drivers/gpu/drm/bridge/synopsys/dw-hdmi-qp.c
---
drivers/gpu/drm/bridge/synopsys/dw-hdmi-qp.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi-qp.c b/drivers/gpu/drm/bridge/synopsys/dw-hdmi-qp.c
index 111111111111..222222222222 100644
--- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi-qp.c
+++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi-qp.c
@@ -5,6 +5,7 @@
* Algea Cao <algea.cao@rock-chips.com>
*/
#include <linux/clk.h>
+#include <linux/debugfs.h>
#include <linux/delay.h>
#include <linux/dma-mapping.h>
#include <linux/err.h>
--
Armbian

@ -0,0 +1,190 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Detlev Casanova <detlev.casanova@collabora.com>
Date: Fri, 3 May 2024 14:27:39 -0400
Subject: vop2: Add clock resets support
At the end of initialization, each VP clock needs to be reset before
they can be used.
Failing to do so can put the VOP in an undefined state where the
generated HDMI signal is either lost or not matching the selected mode.
Signed-off-by: Detlev Casanova <detlev.casanova@collabora.com>
---
drivers/gpu/drm/rockchip/rockchip_drm_vop2.c | 30 ++++++++++
1 file changed, 30 insertions(+)
diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop2.c b/drivers/gpu/drm/rockchip/rockchip_drm_vop2.c
index 111111111111..222222222222 100644
--- a/drivers/gpu/drm/rockchip/rockchip_drm_vop2.c
+++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop2.c
@@ -19,6 +19,7 @@
#include <linux/platform_device.h>
#include <linux/pm_runtime.h>
#include <linux/regmap.h>
+#include <linux/reset.h>
#include <linux/swab.h>
#include <drm/drm.h>
@@ -159,6 +160,7 @@ struct vop2_win {
struct vop2_video_port {
struct drm_crtc crtc;
struct vop2 *vop2;
+ struct reset_control *dclk_rst;
struct clk *dclk;
unsigned int id;
const struct vop2_video_port_data *data;
@@ -2064,6 +2066,26 @@ static struct vop2_clk *vop2_clk_get(struct vop2 *vop2, const char *name)
return NULL;
}
+static int vop2_clk_reset(struct vop2_video_port *vp)
+{
+ struct reset_control *rstc = vp->dclk_rst;
+ struct vop2 *vop2 = vp->vop2;
+ int ret;
+
+ if (!rstc)
+ return 0;
+
+ ret = reset_control_assert(rstc);
+ if (ret < 0)
+ drm_warn(vop2->drm, "failed to assert reset\n");
+ udelay(10);
+ ret = reset_control_deassert(rstc);
+ if (ret < 0)
+ drm_warn(vop2->drm, "failed to deassert reset\n");
+
+ return ret;
+}
+
static void vop2_crtc_atomic_enable(struct drm_crtc *crtc,
struct drm_atomic_state *state)
{
@@ -2233,6 +2255,8 @@ static void vop2_crtc_atomic_enable(struct drm_crtc *crtc,
vop2_vp_write(vp, RK3568_VP_DSP_CTRL, dsp_ctrl);
+ vop2_clk_reset(vp);
+
drm_crtc_vblank_on(crtc);
vop2_unlock(vop2);
@@ -2920,6 +2944,12 @@ static int vop2_create_crtcs(struct vop2 *vop2)
vp->data = vp_data;
snprintf(dclk_name, sizeof(dclk_name), "dclk_vp%d", vp->id);
+ vp->dclk_rst = devm_reset_control_get_optional(vop2->dev, dclk_name);
+ if (IS_ERR(vp->dclk_rst)) {
+ drm_err(vop2->drm, "failed to get %s reset\n", dclk_name);
+ return PTR_ERR(vp->dclk_rst);
+ }
+
vp->dclk = devm_clk_get(vop2->dev, dclk_name);
if (IS_ERR(vp->dclk)) {
drm_err(vop2->drm, "failed to get %s\n", dclk_name);
--
Armbian
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Detlev Casanova <detlev.casanova@collabora.com>
Date: Fri, 3 May 2024 14:28:12 -0400
Subject: arm64: dts: rockchip: Add VOP clock resets for rk3588s
This adds the needed clock resets for all rk3588(s) based SOCs.
Signed-off-by: Detlev Casanova <detlev.casanova@collabora.com>
---
arch/arm64/boot/dts/rockchip/rk3588s.dtsi | 8 ++++++++
1 file changed, 8 insertions(+)
diff --git a/arch/arm64/boot/dts/rockchip/rk3588s.dtsi b/arch/arm64/boot/dts/rockchip/rk3588s.dtsi
index 111111111111..222222222222 100644
--- a/arch/arm64/boot/dts/rockchip/rk3588s.dtsi
+++ b/arch/arm64/boot/dts/rockchip/rk3588s.dtsi
@@ -1429,6 +1429,14 @@ vop: vop@fdd90000 {
"pclk_vop";
iommus = <&vop_mmu>;
power-domains = <&power RK3588_PD_VOP>;
+ resets = <&cru SRST_D_VOP0>,
+ <&cru SRST_D_VOP1>,
+ <&cru SRST_D_VOP2>,
+ <&cru SRST_D_VOP3>;
+ reset-names = "dclk_vp0",
+ "dclk_vp1",
+ "dclk_vp2",
+ "dclk_vp3";
rockchip,grf = <&sys_grf>;
rockchip,vop-grf = <&vop_grf>;
rockchip,vo1-grf = <&vo1_grf>;
--
Armbian
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Detlev Casanova <detlev.casanova@collabora.com>
Date: Mon, 6 May 2024 13:54:01 -0400
Subject: dt-bindings: display: vop2: Add VP clock resets
Add the documentation for VOP2 video ports reset clocks.
One reset can be set per video port.
Signed-off-by: Detlev Casanova <detlev.casanova@collabora.com>
---
Documentation/devicetree/bindings/display/rockchip/rockchip-vop2.yaml | 27 ++++++++++
1 file changed, 27 insertions(+)
diff --git a/Documentation/devicetree/bindings/display/rockchip/rockchip-vop2.yaml b/Documentation/devicetree/bindings/display/rockchip/rockchip-vop2.yaml
index 111111111111..222222222222 100644
--- a/Documentation/devicetree/bindings/display/rockchip/rockchip-vop2.yaml
+++ b/Documentation/devicetree/bindings/display/rockchip/rockchip-vop2.yaml
@@ -65,6 +65,22 @@ properties:
- const: dclk_vp3
- const: pclk_vop
+ resets:
+ minItems: 3
+ items:
+ - description: Pixel clock reset for video port 0.
+ - description: Pixel clock reset for video port 1.
+ - description: Pixel clock reset for video port 2.
+ - description: Pixel clock reset for video port 3.
+
+ reset-names:
+ minItems: 3
+ items:
+ - const: dclk_vp0
+ - const: dclk_vp1
+ - const: dclk_vp2
+ - const: dclk_vp3
+
rockchip,grf:
$ref: /schemas/types.yaml#/definitions/phandle
description:
@@ -128,6 +144,11 @@ allOf:
clock-names:
minItems: 7
+ resets:
+ minItems: 4
+ reset-names:
+ minItems: 4
+
ports:
required:
- port@0
@@ -183,6 +204,12 @@ examples:
"dclk_vp0",
"dclk_vp1",
"dclk_vp2";
+ resets = <&cru SRST_VOP0>,
+ <&cru SRST_VOP1>,
+ <&cru SRST_VOP2>;
+ reset-names = "dclk_vp0",
+ "dclk_vp1",
+ "dclk_vp2";
power-domains = <&power RK3568_PD_VO>;
iommus = <&vop_mmu>;
vop_out: ports {
--
Armbian

@ -0,0 +1,74 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Ondrej Jirman <unknown-email@domain.tld>
Date: Wed, 28 Feb 2024 20:59:15 +0100
Subject: net: wireless: brcmfmac: Add support for AP6275P
This module features BCM43752A2 chipset. The firmware requires
randomness seeding, so enabled it.
Signed-off-by: Ondrej Jirman <megi@xff.cz>
---
drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c | 5 ++++-
drivers/net/wireless/broadcom/brcm80211/include/brcm_hw_ids.h | 2 ++
2 files changed, 6 insertions(+), 1 deletion(-)
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c
index 111111111111..222222222222 100644
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c
@@ -70,6 +70,7 @@ BRCMF_FW_CLM_DEF(4377B3, "brcmfmac4377b3-pcie");
BRCMF_FW_CLM_DEF(4378B1, "brcmfmac4378b1-pcie");
BRCMF_FW_CLM_DEF(4378B3, "brcmfmac4378b3-pcie");
BRCMF_FW_CLM_DEF(4387C2, "brcmfmac4387c2-pcie");
+BRCMF_FW_CLM_DEF(43752, "brcmfmac43752-pcie");
/* firmware config files */
MODULE_FIRMWARE(BRCMF_FW_DEFAULT_PATH "brcmfmac*-pcie.txt");
@@ -104,6 +105,7 @@ static const struct brcmf_firmware_mapping brcmf_pcie_fwnames[] = {
BRCMF_FW_ENTRY(BRCM_CC_43664_CHIP_ID, 0xFFFFFFF0, 4366C),
BRCMF_FW_ENTRY(BRCM_CC_43666_CHIP_ID, 0xFFFFFFF0, 4366C),
BRCMF_FW_ENTRY(BRCM_CC_4371_CHIP_ID, 0xFFFFFFFF, 4371),
+ BRCMF_FW_ENTRY(BRCM_CC_43752_CHIP_ID, 0xFFFFFFFF, 43752),
BRCMF_FW_ENTRY(BRCM_CC_4377_CHIP_ID, 0xFFFFFFFF, 4377B3), /* revision ID 4 */
BRCMF_FW_ENTRY(BRCM_CC_4378_CHIP_ID, 0x0000000F, 4378B1), /* revision ID 3 */
BRCMF_FW_ENTRY(BRCM_CC_4378_CHIP_ID, 0xFFFFFFE0, 4378B3), /* revision ID 5 */
@@ -1720,7 +1722,7 @@ static int brcmf_pcie_download_fw_nvram(struct brcmf_pciedev_info *devinfo,
memcpy_toio(devinfo->tcm + address, nvram, nvram_len);
brcmf_fw_nvram_free(nvram);
- if (devinfo->otp.valid) {
+ if (devinfo->otp.valid || devinfo->ci->chip == BRCM_CC_43752_CHIP_ID) {
size_t rand_len = BRCMF_RANDOM_SEED_LENGTH;
struct brcmf_random_seed_footer footer = {
.length = cpu_to_le32(rand_len),
@@ -2700,6 +2702,7 @@ static const struct pci_device_id brcmf_pcie_devid_table[] = {
BRCMF_PCIE_DEVICE(BRCM_PCIE_4366_5G_DEVICE_ID, BCA),
BRCMF_PCIE_DEVICE(BRCM_PCIE_4371_DEVICE_ID, WCC),
BRCMF_PCIE_DEVICE(BRCM_PCIE_43596_DEVICE_ID, CYW),
+ BRCMF_PCIE_DEVICE(BRCM_PCIE_43752_DEVICE_ID, WCC),
BRCMF_PCIE_DEVICE(BRCM_PCIE_4377_DEVICE_ID, WCC),
BRCMF_PCIE_DEVICE(BRCM_PCIE_4378_DEVICE_ID, WCC),
BRCMF_PCIE_DEVICE(BRCM_PCIE_4387_DEVICE_ID, WCC),
diff --git a/drivers/net/wireless/broadcom/brcm80211/include/brcm_hw_ids.h b/drivers/net/wireless/broadcom/brcm80211/include/brcm_hw_ids.h
index 111111111111..222222222222 100644
--- a/drivers/net/wireless/broadcom/brcm80211/include/brcm_hw_ids.h
+++ b/drivers/net/wireless/broadcom/brcm80211/include/brcm_hw_ids.h
@@ -52,6 +52,7 @@
#define BRCM_CC_43664_CHIP_ID 43664
#define BRCM_CC_43666_CHIP_ID 43666
#define BRCM_CC_4371_CHIP_ID 0x4371
+#define BRCM_CC_43752_CHIP_ID 43752
#define BRCM_CC_4377_CHIP_ID 0x4377
#define BRCM_CC_4378_CHIP_ID 0x4378
#define BRCM_CC_4387_CHIP_ID 0x4387
@@ -94,6 +95,7 @@
#define BRCM_PCIE_4366_5G_DEVICE_ID 0x43c5
#define BRCM_PCIE_4371_DEVICE_ID 0x440d
#define BRCM_PCIE_43596_DEVICE_ID 0x4415
+#define BRCM_PCIE_43752_DEVICE_ID 0x449d
#define BRCM_PCIE_4377_DEVICE_ID 0x4488
#define BRCM_PCIE_4378_DEVICE_ID 0x4425
#define BRCM_PCIE_4387_DEVICE_ID 0x4433
--
Armbian

@ -0,0 +1,51 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Ondrej Jirman <unknown-email@domain.tld>
Date: Wed, 28 Feb 2024 21:09:51 +0100
Subject: net: wireless: brcmfmac: Add optional 32k clock enable support
WiFi modules often require 32kHz clock to function. Add support to
enable the clock to pcie driver.
Signed-off-by: Ondrej Jirman <megi@xff.cz>
---
drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c | 10 ++++++++++
1 file changed, 10 insertions(+)
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c
index 111111111111..222222222222 100644
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c
@@ -3,6 +3,7 @@
* Copyright (c) 2014 Broadcom Corporation
*/
+#include <linux/clk.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/firmware.h>
@@ -2413,6 +2414,7 @@ brcmf_pcie_probe(struct pci_dev *pdev, const struct pci_device_id *id)
struct brcmf_pciedev *pcie_bus_dev;
struct brcmf_core *core;
struct brcmf_bus *bus;
+ struct clk *clk;
if (!id) {
id = pci_match_id(brcmf_pcie_devid_table, pdev);
@@ -2424,6 +2426,14 @@ brcmf_pcie_probe(struct pci_dev *pdev, const struct pci_device_id *id)
brcmf_dbg(PCIE, "Enter %x:%x\n", pdev->vendor, pdev->device);
+ clk = devm_clk_get_optional_enabled(&pdev->dev, "32k");
+ if (IS_ERR(clk))
+ return PTR_ERR(clk);
+ if (clk) {
+ dev_info(&pdev->dev, "enabling 32kHz clock\n");
+ clk_set_rate(clk, 32768);
+ }
+
ret = -ENOMEM;
devinfo = kzalloc(sizeof(*devinfo), GFP_KERNEL);
if (devinfo == NULL)
--
Armbian

@ -0,0 +1,37 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: amazingfate <liujianfeng1994@gmail.com>
Date: Wed, 27 Dec 2023 15:03:57 +0800
Subject: arm64: dts: rock-5b: Slow down emmc to hs200 and add tsadc node
---
arch/arm64/boot/dts/rockchip/rk3588-rock-5b.dts | 7 +++++--
1 file changed, 5 insertions(+), 2 deletions(-)
diff --git a/arch/arm64/boot/dts/rockchip/rk3588-rock-5b.dts b/arch/arm64/boot/dts/rockchip/rk3588-rock-5b.dts
index 111111111111..222222222222 100644
--- a/arch/arm64/boot/dts/rockchip/rk3588-rock-5b.dts
+++ b/arch/arm64/boot/dts/rockchip/rk3588-rock-5b.dts
@@ -371,8 +371,7 @@ &sdhci {
no-sdio;
no-sd;
non-removable;
- mmc-hs400-1_8v;
- mmc-hs400-enhanced-strobe;
+ mmc-hs200-1_8v;
status = "okay";
};
@@ -412,6 +411,10 @@ &sdio {
status = "okay";
};
+&tsadc {
+ status = "okay";
+};
+
&uart6 {
pinctrl-names = "default";
pinctrl-0 = <&uart6m1_xfer &uart6m1_ctsn &uart6m1_rtsn>;
--
Armbian

@ -0,0 +1,52 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: lanefu <lane@lane-fu.com>
Date: Sat, 20 Jan 2024 17:16:20 +0000
Subject: rock-5b enable SPI flash in device tree
arch/arm64/boot/dts/rockchip/rk3588-rock-5b.dts
Signed-off-by: lanefu <lane@lane-fu.com>
---
arch/arm64/boot/dts/rockchip/rk3588-rock-5b.dts | 27 ++++++++++
1 file changed, 27 insertions(+)
diff --git a/arch/arm64/boot/dts/rockchip/rk3588-rock-5b.dts b/arch/arm64/boot/dts/rockchip/rk3588-rock-5b.dts
index 111111111111..222222222222 100644
--- a/arch/arm64/boot/dts/rockchip/rk3588-rock-5b.dts
+++ b/arch/arm64/boot/dts/rockchip/rk3588-rock-5b.dts
@@ -421,6 +421,33 @@ &uart6 {
status = "okay";
};
+&sfc {
+ status = "okay";
+
+ spi_flash: spi-flash@0 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ compatible = "jedec,spi-nor";
+ reg = <0x0>;
+ spi-max-frequency = <50000000>;
+ spi-tx-bus-width = <1>;
+ spi-rx-bus-width = <4>;
+ status = "okay";
+
+ partitions {
+ compatible = "fixed-partitions";
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ loader@0 {
+ label = "loader";
+ reg = <0x0 0x1000000>;
+ };
+ };
+ };
+
+};
+
&spi2 {
status = "okay";
assigned-clocks = <&cru CLK_SPI2>;
--
Armbian

@ -0,0 +1,67 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Cristian Ciocaltea <cristian.ciocaltea@collabora.com>
Date: Mon, 15 Jan 2024 22:51:17 +0200
Subject: arm64: dts: rockchip: Enable HDMI0 on rock-5b
Add the necessary DT changes to enable HDMI0 on Rock 5B.
Signed-off-by: Cristian Ciocaltea <cristian.ciocaltea@collabora.com>
---
arch/arm64/boot/dts/rockchip/rk3588-rock-5b.dts | 30 ++++++++++
1 file changed, 30 insertions(+)
diff --git a/arch/arm64/boot/dts/rockchip/rk3588-rock-5b.dts b/arch/arm64/boot/dts/rockchip/rk3588-rock-5b.dts
index 111111111111..222222222222 100644
--- a/arch/arm64/boot/dts/rockchip/rk3588-rock-5b.dts
+++ b/arch/arm64/boot/dts/rockchip/rk3588-rock-5b.dts
@@ -4,6 +4,7 @@
#include <dt-bindings/gpio/gpio.h>
#include <dt-bindings/leds/common.h>
+#include <dt-bindings/soc/rockchip,vop2.h>
#include "rk3588.dtsi"
/ {
@@ -185,6 +186,20 @@ &gpu {
status = "okay";
};
+&hdmi0 {
+ status = "okay";
+};
+
+&hdmi0_in {
+ hdmi0_in_vp0: endpoint {
+ remote-endpoint = <&vp0_out_hdmi0>;
+ };
+};
+
+&hdptxphy_hdmi0 {
+ status = "okay";
+};
+
&i2c0 {
pinctrl-names = "default";
pinctrl-0 = <&i2c0m2_xfer>;
@@ -837,3 +852,18 @@ &usb_host1_xhci {
&usb_host2_xhci {
status = "okay";
};
+
+&vop_mmu {
+ status = "okay";
+};
+
+&vop {
+ status = "okay";
+};
+
+&vp0 {
+ vp0_out_hdmi0: endpoint@ROCKCHIP_VOP2_EP_HDMI0 {
+ reg = <ROCKCHIP_VOP2_EP_HDMI0>;
+ remote-endpoint = <&hdmi0_in_vp0>;
+ };
+};
--
Armbian

@ -0,0 +1,41 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Cristian Ciocaltea <cristian.ciocaltea@collabora.com>
Date: Fri, 3 Nov 2023 20:05:05 +0200
Subject: arm64: dts: rockchip: Make use of HDMI0 PHY PLL on rock-5b
The initial vop2 support for rk3588 in mainline is not able to handle
all display modes supported by connected displays, e.g.
2560x1440-75.00Hz, 2048x1152-60.00Hz, 1024x768-60.00Hz.
Additionally, it doesn't cope with non-integer refresh rates like 59.94,
29.97, 23.98, etc.
Make use of the HDMI0 PHY PLL to support the additional display modes.
Note this requires commit "drm/rockchip: vop2: Improve display modes
handling on rk3588", which needs a rework to be upstreamable.
Signed-off-by: Cristian Ciocaltea <cristian.ciocaltea@collabora.com>
---
arch/arm64/boot/dts/rockchip/rk3588-rock-5b.dts | 5 +++++
1 file changed, 5 insertions(+)
diff --git a/arch/arm64/boot/dts/rockchip/rk3588-rock-5b.dts b/arch/arm64/boot/dts/rockchip/rk3588-rock-5b.dts
index 111111111111..222222222222 100644
--- a/arch/arm64/boot/dts/rockchip/rk3588-rock-5b.dts
+++ b/arch/arm64/boot/dts/rockchip/rk3588-rock-5b.dts
@@ -186,6 +186,11 @@ &gpu {
status = "okay";
};
+&display_subsystem {
+ clocks = <&hdptxphy_hdmi0>;
+ clock-names = "hdmi0_phy_pll";
+};
+
&hdmi0 {
status = "okay";
};
--
Armbian

@ -0,0 +1,68 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Alexey Charkov <alchark@gmail.com>
Date: Mon, 6 May 2024 13:36:35 +0400
Subject: arm64: dts: rockchip: enable automatic fan control on Rock 5B
This links the PWM fan on Radxa Rock 5B as an active cooling device
managed automatically by the thermal subsystem, with a target SoC
temperature of 65C and a minimum-spin interval from 55C to 65C to
ensure airflow when the system gets warm
Helped-by: Dragan Simic <dsimic@manjaro.org>
Reviewed-by: Dragan Simic <dsimic@manjaro.org>
Signed-off-by: Alexey Charkov <alchark@gmail.com>
---
arch/arm64/boot/dts/rockchip/rk3588-rock-5b.dts | 30 +++++++++-
1 file changed, 29 insertions(+), 1 deletion(-)
diff --git a/arch/arm64/boot/dts/rockchip/rk3588-rock-5b.dts b/arch/arm64/boot/dts/rockchip/rk3588-rock-5b.dts
index 111111111111..222222222222 100644
--- a/arch/arm64/boot/dts/rockchip/rk3588-rock-5b.dts
+++ b/arch/arm64/boot/dts/rockchip/rk3588-rock-5b.dts
@@ -53,7 +53,7 @@ led_rgb_b {
fan: pwm-fan {
compatible = "pwm-fan";
- cooling-levels = <0 95 145 195 255>;
+ cooling-levels = <0 120 150 180 210 240 255>;
fan-supply = <&vcc5v0_sys>;
pwms = <&pwm1 0 50000 0>;
#cooling-cells = <2>;
@@ -299,6 +299,34 @@ i2s0_8ch_p0_0: endpoint {
};
};
+&package_thermal {
+ polling-delay = <1000>;
+
+ trips {
+ package_fan0: package-fan0 {
+ temperature = <55000>;
+ hysteresis = <2000>;
+ type = "active";
+ };
+ package_fan1: package-fan1 {
+ temperature = <65000>;
+ hysteresis = <2000>;
+ type = "active";
+ };
+ };
+
+ cooling-maps {
+ map1 {
+ trip = <&package_fan0>;
+ cooling-device = <&fan THERMAL_NO_LIMIT 1>;
+ };
+ map2 {
+ trip = <&package_fan1>;
+ cooling-device = <&fan 2 THERMAL_NO_LIMIT>;
+ };
+ };
+};
+
&pcie2x1l0 {
pinctrl-names = "default";
pinctrl-0 = <&pcie2_0_rst>;
--
Armbian

@ -0,0 +1,57 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Muhammed Efe Cetin <efectn@protonmail.com>
Date: Tue, 27 Feb 2024 16:04:42 +0300
Subject: Add HDMI and VOP2 to Rock 5A
---
arch/arm64/boot/dts/rockchip/rk3588s-rock-5a.dts | 30 ++++++++++
1 file changed, 30 insertions(+)
diff --git a/arch/arm64/boot/dts/rockchip/rk3588s-rock-5a.dts b/arch/arm64/boot/dts/rockchip/rk3588s-rock-5a.dts
index 111111111111..222222222222 100644
--- a/arch/arm64/boot/dts/rockchip/rk3588s-rock-5a.dts
+++ b/arch/arm64/boot/dts/rockchip/rk3588s-rock-5a.dts
@@ -5,6 +5,7 @@
#include <dt-bindings/gpio/gpio.h>
#include <dt-bindings/leds/common.h>
#include <dt-bindings/pinctrl/rockchip.h>
+#include <dt-bindings/soc/rockchip,vop2.h>
#include "rk3588s.dtsi"
/ {
@@ -765,3 +766,32 @@ &usb_host1_ohci {
&usb_host2_xhci {
status = "okay";
};
+
+&hdmi0 {
+ status = "okay";
+};
+
+&hdptxphy_hdmi0 {
+ status = "okay";
+};
+
+&vop_mmu {
+ status = "okay";
+};
+
+&hdmi0_in {
+ hdmi0_in_vp0: endpoint {
+ remote-endpoint = <&vp0_out_hdmi0>;
+ };
+};
+
+&vop {
+ status = "okay";
+};
+
+&vp0 {
+ vp0_out_hdmi0: endpoint@ROCKCHIP_VOP2_EP_HDMI0 {
+ reg = <ROCKCHIP_VOP2_EP_HDMI0>;
+ remote-endpoint = <&hdmi0_in_vp0>;
+ };
+};
--
Armbian

@ -0,0 +1,36 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: amazingfate <liujianfeng1994@gmail.com>
Date: Thu, 28 Mar 2024 00:41:34 +0800
Subject: arch: arm64: dts: enable gpu node for rock-5a
---
arch/arm64/boot/dts/rockchip/rk3588s-rock-5a.dts | 6 ++++++
1 file changed, 6 insertions(+)
diff --git a/arch/arm64/boot/dts/rockchip/rk3588s-rock-5a.dts b/arch/arm64/boot/dts/rockchip/rk3588s-rock-5a.dts
index 111111111111..222222222222 100644
--- a/arch/arm64/boot/dts/rockchip/rk3588s-rock-5a.dts
+++ b/arch/arm64/boot/dts/rockchip/rk3588s-rock-5a.dts
@@ -281,6 +281,11 @@ &gmac1_rgmii_clk
status = "okay";
};
+&gpu {
+ mali-supply = <&vdd_gpu_s0>;
+ status = "okay";
+};
+
&mdio1 {
rgmii_phy1: ethernet-phy@1 {
/* RTL8211F */
@@ -434,6 +439,7 @@ rk806_dvs3_null: dvs3-null-pins {
regulators {
vdd_gpu_s0: vdd_gpu_mem_s0: dcdc-reg1 {
regulator-name = "vdd_gpu_s0";
+ regulator-always-on;
regulator-boot-on;
regulator-min-microvolt = <550000>;
regulator-max-microvolt = <950000>;
--
Armbian

@ -0,0 +1,265 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Muhammed Efe Cetin <efectn@protonmail.com>
Date: Thu, 16 Nov 2023 18:15:09 +0300
Subject: arm64: dts: Add missing nodes to Orange Pi 5 Plus
---
arch/arm64/boot/dts/rockchip/rk3588-orangepi-5-plus.dts | 182 +++++++++-
1 file changed, 181 insertions(+), 1 deletion(-)
diff --git a/arch/arm64/boot/dts/rockchip/rk3588-orangepi-5-plus.dts b/arch/arm64/boot/dts/rockchip/rk3588-orangepi-5-plus.dts
index 111111111111..222222222222 100644
--- a/arch/arm64/boot/dts/rockchip/rk3588-orangepi-5-plus.dts
+++ b/arch/arm64/boot/dts/rockchip/rk3588-orangepi-5-plus.dts
@@ -10,6 +10,7 @@
#include <dt-bindings/input/input.h>
#include <dt-bindings/pinctrl/rockchip.h>
#include <dt-bindings/usb/pd.h>
+#include <dt-bindings/soc/rockchip,vop2.h>
#include "rk3588.dtsi"
/ {
@@ -158,6 +159,20 @@ daicodec: simple-audio-card,codec {
};
};
+ wlan-rfkill {
+ compatible = "rfkill-gpio";
+ label = "rfkill-wlan";
+ radio-type = "wlan";
+ shutdown-gpios = <&gpio0 RK_PC4 GPIO_ACTIVE_HIGH>;
+ };
+
+ bluetooth-rfkill {
+ compatible = "rfkill-gpio";
+ label = "rfkill-bluetooth";
+ radio-type = "bluetooth";
+ shutdown-gpios = <&gpio0 RK_PC5 GPIO_ACTIVE_HIGH>;
+ };
+
vcc3v3_pcie30: vcc3v3-pcie30-regulator {
compatible = "regulator-fixed";
enable-active-high;
@@ -199,6 +214,18 @@ vcc5v0_sys: vcc5v0-sys-regulator {
regulator-max-microvolt = <5000000>;
};
+ vbus5v0_typec: vbus5v0-typec-regulator {
+ compatible = "regulator-fixed";
+ enable-active-high;
+ gpio = <&gpio4 RK_PB0 GPIO_ACTIVE_HIGH>;
+ regulator-name = "vbus5v0_typec";
+ regulator-min-microvolt = <5000000>;
+ regulator-max-microvolt = <5000000>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&typec5v_pwren>;
+ vin-supply = <&vcc5v0_sys>;
+ };
+
vcc5v0_usb20: vcc5v0-usb20-regulator {
compatible = "regulator-fixed";
enable-active-high;
@@ -311,6 +338,53 @@ hym8563: rtc@51 {
pinctrl-0 = <&hym8563_int>;
wakeup-source;
};
+
+ usbc0: usb-typec@22 {
+ compatible = "fcs,fusb302";
+ reg = <0x22>;
+ interrupt-parent = <&gpio0>;
+ interrupts = <RK_PD3 IRQ_TYPE_LEVEL_LOW>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&usbc0_int>;
+ vbus-supply = <&vbus5v0_typec>;
+
+ usb_con: connector {
+ compatible = "usb-c-connector";
+ label = "USB-C";
+ data-role = "dual";
+ power-role = "dual";
+ try-power-role = "source";
+ op-sink-microwatt = <1000000>;
+ sink-pdos = <PDO_FIXED(5000, 2000, PDO_FIXED_USB_COMM)>;
+ source-pdos = <PDO_FIXED(5000, 1500, PDO_FIXED_USB_COMM)>;
+
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ port@0 {
+ reg = <0>;
+ usbc0_hs: endpoint {
+ remote-endpoint = <&usb_host0_xhci_drd_sw>;
+ };
+ };
+
+ port@1 {
+ reg = <1>;
+ usbc0_ss: endpoint {
+ remote-endpoint = <&usbdp_phy0_typec_ss>;
+ };
+ };
+
+ port@2 {
+ reg = <2>;
+ usbc0_sbu: endpoint {
+ remote-endpoint = <&usbdp_phy0_typec_sbu>;
+ };
+ };
+ };
+ };
+ };
};
&i2c7 {
@@ -385,7 +459,7 @@ &pcie3x4 {
&pinctrl {
hym8563 {
hym8563_int: hym8563-int {
- rockchip,pins = <0 RK_PB0 RK_FUNC_GPIO &pcfg_pull_none>;
+ rockchip,pins = <0 RK_PB0 RK_FUNC_GPIO &pcfg_pull_up>;
};
};
@@ -408,6 +482,14 @@ hp_detect: hp-detect {
};
usb {
+ typec5v_pwren: typec5v-pwren {
+ rockchip,pins = <4 RK_PB0 RK_FUNC_GPIO &pcfg_pull_none>;
+ };
+
+ usbc0_int: usbc0-int {
+ rockchip,pins = <0 RK_PD3 RK_FUNC_GPIO &pcfg_pull_up>;
+ };
+
vcc5v0_usb20_en: vcc5v0-usb20-en {
rockchip,pins = <3 RK_PB7 RK_FUNC_GPIO &pcfg_pull_none>;
};
@@ -803,6 +885,22 @@ &tsadc {
status = "okay";
};
+&u2phy0 {
+ status = "okay";
+};
+
+&u2phy0_otg {
+ status = "okay";
+};
+
+&u2phy1 {
+ status = "okay";
+};
+
+&u2phy1_otg {
+ status = "okay";
+};
+
&u2phy2 {
status = "okay";
};
@@ -831,6 +929,35 @@ &uart9 {
status = "okay";
};
+&usbdp_phy0 {
+ orientation-switch;
+ mode-switch;
+ sbu1-dc-gpios = <&gpio4 RK_PA6 GPIO_ACTIVE_HIGH>;
+ sbu2-dc-gpios = <&gpio4 RK_PA7 GPIO_ACTIVE_HIGH>;
+ status = "okay";
+ svid = <0xff01>;
+
+ port {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ usbdp_phy0_typec_ss: endpoint@0 {
+ reg = <0>;
+ remote-endpoint = <&usbc0_ss>;
+ };
+
+ usbdp_phy0_typec_sbu: endpoint@1 {
+ reg = <1>;
+ remote-endpoint = <&usbc0_sbu>;
+ };
+ };
+};
+
+&usbdp_phy1 {
+ rockchip,dp-lane-mux = <2 3>;
+ status = "okay";
+};
+
&usb_host0_ehci {
status = "okay";
};
@@ -839,6 +966,20 @@ &usb_host0_ohci {
status = "okay";
};
+&usb_host0_xhci {
+ dr_mode = "otg";
+ usb-role-switch;
+ status = "okay";
+
+ port {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ usb_host0_xhci_drd_sw: endpoint {
+ remote-endpoint = <&usbc0_hs>;
+ };
+ };
+};
+
&usb_host1_ehci {
status = "okay";
};
@@ -846,3 +987,42 @@ &usb_host1_ehci {
&usb_host1_ohci {
status = "okay";
};
+
+&usb_host1_xhci {
+ dr_mode = "host";
+ status = "okay";
+};
+
+&gpu {
+ mali-supply = <&vdd_gpu_s0>;
+ status = "okay";
+};
+
+&hdmi0 {
+ status = "okay";
+};
+
+&hdptxphy_hdmi0 {
+ status = "okay";
+};
+
+&vop_mmu {
+ status = "okay";
+};
+
+&hdmi0_in {
+ hdmi0_in_vp0: endpoint {
+ remote-endpoint = <&vp0_out_hdmi0>;
+ };
+};
+
+&vop {
+ status = "okay";
+};
+
+&vp0 {
+ vp0_out_hdmi0: endpoint@ROCKCHIP_VOP2_EP_HDMI0 {
+ reg = <ROCKCHIP_VOP2_EP_HDMI0>;
+ remote-endpoint = <&hdmi0_in_vp0>;
+ };
+};
--
Armbian

@ -0,0 +1,39 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: amazingfate <liujianfeng1994@gmail.com>
Date: Thu, 28 Mar 2024 16:07:18 +0800
Subject: arm64: dts: rockchip: add PCIe for M.2 E-Key to rock-5a
---
arch/arm64/boot/dts/rockchip/rk3588s-rock-5a.dts | 9 +++++++++
1 file changed, 9 insertions(+)
diff --git a/arch/arm64/boot/dts/rockchip/rk3588s-rock-5a.dts b/arch/arm64/boot/dts/rockchip/rk3588s-rock-5a.dts
index 111111111111..222222222222 100644
--- a/arch/arm64/boot/dts/rockchip/rk3588s-rock-5a.dts
+++ b/arch/arm64/boot/dts/rockchip/rk3588s-rock-5a.dts
@@ -115,6 +115,10 @@ vcc_1v1_nldo_s3: vcc-1v1-nldo-s3-regulator {
};
};
+&combphy0_ps {
+ status = "okay";
+};
+
&combphy2_psu {
status = "okay";
};
@@ -299,6 +303,11 @@ rgmii_phy1: ethernet-phy@1 {
};
};
+&pcie2x1l2 {
+ status = "okay";
+ reset-gpios = <&gpio3 RK_PD1 GPIO_ACTIVE_HIGH>;
+};
+
&pinctrl {
leds {
io_led: io-led {
--
Armbian

@ -0,0 +1,64 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Jianfeng Liu <liujianfeng1994@gmail.com>
Date: Thu, 6 Jun 2024 23:28:01 +0800
Subject: arm64: dts: rockchip: Add HDMI support to ArmSoM Sige7
---
arch/arm64/boot/dts/rockchip/rk3588-armsom-sige7.dts | 30 ++++++++++
1 file changed, 30 insertions(+)
diff --git a/arch/arm64/boot/dts/rockchip/rk3588-armsom-sige7.dts b/arch/arm64/boot/dts/rockchip/rk3588-armsom-sige7.dts
index 111111111111..222222222222 100644
--- a/arch/arm64/boot/dts/rockchip/rk3588-armsom-sige7.dts
+++ b/arch/arm64/boot/dts/rockchip/rk3588-armsom-sige7.dts
@@ -4,6 +4,7 @@
#include <dt-bindings/gpio/gpio.h>
#include <dt-bindings/leds/common.h>
+#include <dt-bindings/soc/rockchip,vop2.h>
#include "rk3588.dtsi"
/ {
@@ -164,6 +165,20 @@ &gpu {
status = "okay";
};
+&hdmi0 {
+ status = "okay";
+};
+
+&hdmi0_in {
+ hdmi0_in_vp0: endpoint {
+ remote-endpoint = <&vp0_out_hdmi0>;
+ };
+};
+
+&hdptxphy_hdmi0 {
+ status = "okay";
+};
+
&i2c0 {
pinctrl-names = "default";
pinctrl-0 = <&i2c0m2_xfer>;
@@ -723,3 +738,18 @@ &usb_host1_xhci {
dr_mode = "host";
status = "okay";
};
+
+&vop {
+ status = "okay";
+};
+
+&vop_mmu {
+ status = "okay";
+};
+
+&vp0 {
+ vp0_out_hdmi0: endpoint@ROCKCHIP_VOP2_EP_HDMI0 {
+ reg = <ROCKCHIP_VOP2_EP_HDMI0>;
+ remote-endpoint = <&hdmi0_in_vp0>;
+ };
+};
--
Armbian

@ -0,0 +1,39 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Jianfeng Liu <liujianfeng1994@gmail.com>
Date: Thu, 6 Jun 2024 23:29:39 +0800
Subject: arm64: dts: rockchip: Add ap6275p wireless support to ArmSoM Sige7
---
arch/arm64/boot/dts/rockchip/rk3588-armsom-sige7.dts | 16 ++++++++++
1 file changed, 16 insertions(+)
diff --git a/arch/arm64/boot/dts/rockchip/rk3588-armsom-sige7.dts b/arch/arm64/boot/dts/rockchip/rk3588-armsom-sige7.dts
index 111111111111..222222222222 100644
--- a/arch/arm64/boot/dts/rockchip/rk3588-armsom-sige7.dts
+++ b/arch/arm64/boot/dts/rockchip/rk3588-armsom-sige7.dts
@@ -283,6 +283,22 @@ &pcie2x1l0 {
&pcie2x1l1 {
reset-gpios = <&gpio3 RK_PD4 GPIO_ACTIVE_HIGH>;
status = "okay";
+
+ pcie@0,0 {
+ reg = <0x300000 0 0 0 0>;
+ #address-cells = <3>;
+ #size-cells = <2>;
+ ranges;
+ device_type = "pci";
+ bus-range = <0x30 0x3f>;
+
+ wifi: wifi@0,0 {
+ compatible = "pci14e4,449d";
+ reg = <0x310000 0 0 0 0>;
+ clocks = <&hym8563>;
+ clock-names = "32k";
+ };
+ };
};
/* phy0 - left ethernet port */
--
Armbian

@ -0,0 +1,325 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Muhammed Efe Cetin <efectn@protonmail.com>
Date: Mon, 12 Feb 2024 17:35:13 +0300
Subject: arm64: dts: rockchip: Add USB-C to Khadas Edge 2
Khadas Edge 2 has 2x Type-C port. One just supports PD and
controlled by MCU. The other one supports PD, DP Alt mode and DRD. This
commit adds support for DRD.
Signed-off-by: Muhammed Efe Cetin <efectn@protonmail.com>
---
arch/arm64/boot/dts/rockchip/rk3588s-khadas-edge2.dts | 120 ++++++++++
1 file changed, 120 insertions(+)
diff --git a/arch/arm64/boot/dts/rockchip/rk3588s-khadas-edge2.dts b/arch/arm64/boot/dts/rockchip/rk3588s-khadas-edge2.dts
index 111111111111..222222222222 100644
--- a/arch/arm64/boot/dts/rockchip/rk3588s-khadas-edge2.dts
+++ b/arch/arm64/boot/dts/rockchip/rk3588s-khadas-edge2.dts
@@ -6,6 +6,7 @@
#include <dt-bindings/input/input.h>
#include <dt-bindings/pinctrl/rockchip.h>
#include <dt-bindings/leds/common.h>
+#include <dt-bindings/usb/pd.h>
#include "rk3588s.dtsi"
/ {
@@ -76,6 +77,18 @@ blue_led: led-2 {
};
};
+ vbus5v0_typec: vbus5v0-typec-regulator {
+ compatible = "regulator-fixed";
+ regulator-name = "vbus5v0_typec";
+ regulator-min-microvolt = <5000000>;
+ regulator-max-microvolt = <5000000>;
+ enable-active-high;
+ gpio = <&gpio3 RK_PA4 GPIO_ACTIVE_HIGH>;
+ vin-supply = <&vcc5v0_sys>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&typec5v_pwren>;
+ };
+
vcc3v3_pcie_wl: vcc3v3-pcie-wl-regulator {
compatible = "regulator-fixed";
enable-active-high;
@@ -224,6 +237,56 @@ regulator-state-mem {
&i2c2 {
status = "okay";
+ usbc0: usb-typec@22 {
+ compatible = "fcs,fusb302";
+ reg = <0x22>;
+ interrupt-parent = <&gpio1>;
+ interrupts = <RK_PB5 IRQ_TYPE_LEVEL_LOW>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&usbc0_int>;
+ vbus-supply = <&vbus5v0_typec>;
+ status = "okay";
+
+ usb_con: connector {
+ compatible = "usb-c-connector";
+ label = "USB-C";
+ data-role = "dual";
+ power-role = "dual";
+ try-power-role = "source";
+ op-sink-microwatt = <1000000>;
+ sink-pdos = <PDO_FIXED(5000, 3000, PDO_FIXED_USB_COMM)
+ PDO_FIXED(9000, 3000, PDO_FIXED_USB_COMM)
+ PDO_FIXED(12000, 3000, PDO_FIXED_USB_COMM)>;
+ source-pdos = <PDO_FIXED(5000, 3000, PDO_FIXED_USB_COMM)>;
+
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ port@0 {
+ reg = <0>;
+ usbc0_orien_sw: endpoint {
+ remote-endpoint = <&usbdp_phy0_orientation_switch>;
+ };
+ };
+
+ port@1 {
+ reg = <1>;
+ usbc0_role_sw: endpoint {
+ remote-endpoint = <&dwc3_0_role_switch>;
+ };
+ };
+
+ port@2 {
+ reg = <2>;
+ dp_altmode_mux: endpoint {
+ remote-endpoint = <&usbdp_phy0_dp_altmode_mux>;
+ };
+ };
+ };
+ };
+ };
+
hym8563: rtc@51 {
compatible = "haoyu,hym8563";
reg = <0x51>;
@@ -256,6 +319,16 @@ vcc5v0_host_en: vcc5v0-host-en {
};
};
+ usb-typec {
+ usbc0_int: usbc0-int {
+ rockchip,pins = <1 RK_PB5 RK_FUNC_GPIO &pcfg_pull_up>;
+ };
+
+ typec5v_pwren: typec5v-pwren {
+ rockchip,pins = <3 RK_PA4 RK_FUNC_GPIO &pcfg_pull_none>;
+ };
+ };
+
ir-receiver {
ir_receiver_pin: ir-receiver-pin {
rockchip,pins = <1 RK_PA7 RK_FUNC_GPIO &pcfg_pull_none>;
@@ -681,6 +754,15 @@ &uart9 {
status = "okay";
};
+&u2phy0 {
+ status = "okay";
+};
+
+&u2phy0_otg {
+ status = "okay";
+};
+
+
&u2phy2 {
status = "okay";
};
@@ -707,6 +789,44 @@ &usb_host0_ohci {
status = "okay";
};
+&usbdp_phy0 {
+ orientation-switch;
+ mode-switch;
+ svid = <0xff01>;
+ sbu1-dc-gpios = <&gpio4 RK_PA0 GPIO_ACTIVE_HIGH>;
+ sbu2-dc-gpios = <&gpio4 RK_PA1 GPIO_ACTIVE_HIGH>;
+ status = "okay";
+
+ port {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ usbdp_phy0_orientation_switch: endpoint@0 {
+ reg = <0>;
+ remote-endpoint = <&usbc0_orien_sw>;
+ };
+
+ usbdp_phy0_dp_altmode_mux: endpoint@1 {
+ reg = <1>;
+ remote-endpoint = <&dp_altmode_mux>;
+ };
+ };
+};
+
+&usb_host0_xhci {
+ usb-role-switch;
+ status = "okay";
+
+ port {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ dwc3_0_role_switch: endpoint@0 {
+ reg = <0>;
+ remote-endpoint = <&usbc0_role_sw>;
+ };
+ };
+};
+
&usb_host1_ehci {
status = "okay";
};
--
Armbian
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Muhammed Efe Cetin <efectn@protonmail.com>
Date: Mon, 12 Feb 2024 17:35:13 +0300
Subject: arm64: dts: rockchip: Add bluetooth rfkill to Khadas Edge 2
---
arch/arm64/boot/dts/rockchip/rk3588s-khadas-edge2.dts | 9 +++++++++
1 file changed, 9 insertions(+)
diff --git a/arch/arm64/boot/dts/rockchip/rk3588s-khadas-edge2.dts b/arch/arm64/boot/dts/rockchip/rk3588s-khadas-edge2.dts
index 111111111111..222222222222 100644
--- a/arch/arm64/boot/dts/rockchip/rk3588s-khadas-edge2.dts
+++ b/arch/arm64/boot/dts/rockchip/rk3588s-khadas-edge2.dts
@@ -116,6 +116,15 @@ vcc5v0_host: vcc5v0-host-regulator {
vin-supply = <&vcc5v0_sys>;
};
+ bluetooth-rfkill {
+ compatible = "rfkill-gpio";
+ label = "rfkill-bluetooth";
+ radio-type = "bluetooth";
+ shutdown-gpios = <&gpio0 RK_PD4 GPIO_ACTIVE_LOW>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&bt_reset_pin>;
+ };
+
vcc5v0_sys: vcc5v0-sys-regulator {
compatible = "regulator-fixed";
regulator-name = "vcc5v0_sys";
--
Armbian
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Muhammed Efe Cetin <efectn@protonmail.com>
Date: Mon, 19 Feb 2024 23:32:11 +0300
Subject: arm64: dts: rockchip: Add HDMI & VOP2 to Khadas Edge 2
---
arch/arm64/boot/dts/rockchip/rk3588s-khadas-edge2.dts | 36 ++++++++++
1 file changed, 36 insertions(+)
diff --git a/arch/arm64/boot/dts/rockchip/rk3588s-khadas-edge2.dts b/arch/arm64/boot/dts/rockchip/rk3588s-khadas-edge2.dts
index 111111111111..222222222222 100644
--- a/arch/arm64/boot/dts/rockchip/rk3588s-khadas-edge2.dts
+++ b/arch/arm64/boot/dts/rockchip/rk3588s-khadas-edge2.dts
@@ -7,6 +7,7 @@
#include <dt-bindings/pinctrl/rockchip.h>
#include <dt-bindings/leds/common.h>
#include <dt-bindings/usb/pd.h>
+#include <dt-bindings/soc/rockchip,vop2.h>
#include "rk3588s.dtsi"
/ {
@@ -823,6 +824,7 @@ usbdp_phy0_dp_altmode_mux: endpoint@1 {
};
&usb_host0_xhci {
+ dr-mode = "otg";
usb-role-switch;
status = "okay";
@@ -847,3 +849,37 @@ &usb_host1_ohci {
&usb_host2_xhci {
status = "okay";
};
+
+&hdmi0 {
+ status = "okay";
+};
+
+&hdptxphy_hdmi0 {
+ status = "okay";
+};
+
+&display_subsystem {
+ clocks = <&hdptxphy_hdmi0>;
+ clock-names = "hdmi0_phy_pll";
+};
+
+&vop_mmu {
+ status = "okay";
+};
+
+&hdmi0_in {
+ hdmi0_in_vp0: endpoint {
+ remote-endpoint = <&vp0_out_hdmi0>;
+ };
+};
+
+&vop {
+ status = "okay";
+};
+
+&vp0 {
+ vp0_out_hdmi0: endpoint@ROCKCHIP_VOP2_EP_HDMI0 {
+ reg = <ROCKCHIP_VOP2_EP_HDMI0>;
+ remote-endpoint = <&hdmi0_in_vp0>;
+ };
+};
--
Armbian
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Muhammed Efe Cetin <efectn@protonmail.com>
Date: Sat, 2 Mar 2024 19:13:59 +0300
Subject: arm64: dts: rockchip: Add AP6275P wireless support to Khadas Edge 2
---
arch/arm64/boot/dts/rockchip/rk3588s-khadas-edge2.dts | 17 ++++++++++
1 file changed, 17 insertions(+)
diff --git a/arch/arm64/boot/dts/rockchip/rk3588s-khadas-edge2.dts b/arch/arm64/boot/dts/rockchip/rk3588s-khadas-edge2.dts
index 111111111111..222222222222 100644
--- a/arch/arm64/boot/dts/rockchip/rk3588s-khadas-edge2.dts
+++ b/arch/arm64/boot/dts/rockchip/rk3588s-khadas-edge2.dts
@@ -366,6 +366,23 @@ &pcie2x1l2 {
reset-gpios = <&gpio3 RK_PD1 GPIO_ACTIVE_HIGH>;
vpcie3v3-supply = <&vcc3v3_pcie_wl>;
status = "okay";
+
+ pcie@0,0 {
+ reg = <0x400000 0 0 0 0>;
+ #address-cells = <3>;
+ #size-cells = <2>;
+ ranges;
+ device_type = "pci";
+ bus-range = <0x40 0x4f>;
+
+ wifi: wifi@0,0 {
+ compatible = "pci14e4,449d";
+ reg = <0x410000 0 0 0 0>;
+ clocks = <&hym8563>;
+ clock-names = "32k";
+ };
+ };
+
};
&pwm11 {
--
Armbian

@ -0,0 +1,441 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Muhammed Efe Cetin <efectn@protonmail.com>
Date: Wed, 6 Mar 2024 00:09:25 +0300
Subject: mfd: khadas-mcu: add Edge2 registers
---
drivers/mfd/khadas-mcu.c | 8 +++-
include/linux/mfd/khadas-mcu.h | 24 ++++++++++
2 files changed, 30 insertions(+), 2 deletions(-)
diff --git a/drivers/mfd/khadas-mcu.c b/drivers/mfd/khadas-mcu.c
index 111111111111..222222222222 100644
--- a/drivers/mfd/khadas-mcu.c
+++ b/drivers/mfd/khadas-mcu.c
@@ -26,6 +26,10 @@ static bool khadas_mcu_reg_volatile(struct device *dev, unsigned int reg)
case KHADAS_MCU_CHECK_USER_PASSWD_REG:
case KHADAS_MCU_WOL_INIT_START_REG:
case KHADAS_MCU_CMD_FAN_STATUS_CTRL_REG:
+ case KHADAS_MCU_LED_ON_RAM_REG:
+ case KHADAS_MCU_CMD_FAN_STATUS_CTRL_REG_V2:
+ case KHADAS_MCU_WDT_EN_REG:
+ case KHADAS_MCU_SYS_RST_REG:
return true;
default:
return false;
@@ -69,14 +73,14 @@ static const struct regmap_config khadas_mcu_regmap_config = {
.reg_bits = 8,
.reg_stride = 1,
.val_bits = 8,
- .max_register = KHADAS_MCU_CMD_FAN_STATUS_CTRL_REG,
+ .max_register = KHADAS_MCU_SYS_RST_REG,
.volatile_reg = khadas_mcu_reg_volatile,
.writeable_reg = khadas_mcu_reg_writeable,
.cache_type = REGCACHE_MAPLE,
};
static struct mfd_cell khadas_mcu_fan_cells[] = {
- /* VIM1/2 Rev13+ and VIM3 only */
+ /* VIM1/2 Rev13+, VIM3 and Edge2 only */
{ .name = "khadas-mcu-fan-ctrl", },
};
diff --git a/include/linux/mfd/khadas-mcu.h b/include/linux/mfd/khadas-mcu.h
index 111111111111..222222222222 100644
--- a/include/linux/mfd/khadas-mcu.h
+++ b/include/linux/mfd/khadas-mcu.h
@@ -35,26 +35,45 @@
#define KHADAS_MCU_FACTORY_TEST_REG 0x16 /* R */
#define KHADAS_MCU_BOOT_MODE_REG 0x20 /* RW */
#define KHADAS_MCU_BOOT_EN_WOL_REG 0x21 /* RW */
+#define KHADAS_MCU_BOOT_EN_DCIN_REG_V2 0x21 /* RW */
#define KHADAS_MCU_BOOT_EN_RTC_REG 0x22 /* RW */
#define KHADAS_MCU_BOOT_EN_EXP_REG 0x23 /* RW */
+#define KHADAS_MCU_LED_MODE_ON_REG_V2 0x23 /* RW */
+#define KHADAS_MCU_LED_MODE_OFF_REG_V2 0x24 /* RW */
#define KHADAS_MCU_BOOT_EN_IR_REG 0x24 /* RW */
#define KHADAS_MCU_BOOT_EN_DCIN_REG 0x25 /* RW */
+#define KHADAS_MCU_RGB_ON_R_REG 0x25 /* RW */
+#define KHADAS_MCU_RGB_ON_G_REG 0x26 /* RW */
#define KHADAS_MCU_BOOT_EN_KEY_REG 0x26 /* RW */
+#define KHADAS_MCU_RGB_ON_B_REG 0x27 /* RW */
#define KHADAS_MCU_KEY_MODE_REG 0x27 /* RW */
+#define KHADAS_MCU_RGB_OFF_R_REG 0x28 /* RW */
#define KHADAS_MCU_LED_MODE_ON_REG 0x28 /* RW */
+#define KHADAS_MCU_RGB_OFF_G_REG 0x29 /* RW */
#define KHADAS_MCU_LED_MODE_OFF_REG 0x29 /* RW */
+#define KHADAS_MCU_RGB_OFF_B_REG 0x2a /* RW */
#define KHADAS_MCU_SHUTDOWN_NORMAL_REG 0x2c /* RW */
#define KHADAS_MCU_MAC_SWITCH_REG 0x2d /* RW */
+#define KHADAS_MCU_REST_CONF_REG 0x2e /* RW */
#define KHADAS_MCU_MCU_SLEEP_MODE_REG 0x2e /* RW */
+#define KHADAS_MCU_BOOT_EN_IR_REG_V2 0x2f /* RW */
#define KHADAS_MCU_IR_CODE1_0_REG 0x2f /* RW */
#define KHADAS_MCU_IR_CODE1_1_REG 0x30 /* RW */
+#define KHADAS_MCU_IR1_CUST1_REG 0x30 /* RW */
#define KHADAS_MCU_IR_CODE1_2_REG 0x31 /* RW */
+#define KHADAS_MCU_IR1_CUST2_REG 0x31 /* RW */
#define KHADAS_MCU_IR_CODE1_3_REG 0x32 /* RW */
+#define KHADAS_MCU_IR1_ORDER1_REG 0x32 /* RW */
#define KHADAS_MCU_USB_PCIE_SWITCH_REG 0x33 /* RW */
+#define KHADAS_MCU_IR1_ORDER2_REG 0x33 /* RW */
+#define KHADAS_MCU_IR2_CUST1_REG 0x34 /* RW */
#define KHADAS_MCU_IR_CODE2_0_REG 0x34 /* RW */
#define KHADAS_MCU_IR_CODE2_1_REG 0x35 /* RW */
+#define KHADAS_MCU_IR2_CUST2_REG 0x35 /* RW */
#define KHADAS_MCU_IR_CODE2_2_REG 0x36 /* RW */
+#define KHADAS_MCU_IR2_ORDER1_REG 0x36 /* RW */
#define KHADAS_MCU_IR_CODE2_3_REG 0x37 /* RW */
+#define KHADAS_MCU_IR2_ORDER2_REG 0x36 /* RW */
#define KHADAS_MCU_PASSWD_USER_0_REG 0x40 /* RW */
#define KHADAS_MCU_PASSWD_USER_1_REG 0x41 /* RW */
#define KHADAS_MCU_PASSWD_USER_2_REG 0x42 /* RW */
@@ -69,6 +88,10 @@
#define KHADAS_MCU_SHUTDOWN_NORMAL_STATUS_REG 0x86 /* RO */
#define KHADAS_MCU_WOL_INIT_START_REG 0x87 /* WO */
#define KHADAS_MCU_CMD_FAN_STATUS_CTRL_REG 0x88 /* WO */
+#define KHADAS_MCU_LED_ON_RAM_REG 0x89 /* WO */
+#define KHADAS_MCU_CMD_FAN_STATUS_CTRL_REG_V2 0x8A /* WO */
+#define KHADAS_MCU_WDT_EN_REG 0x8B /* WO */
+#define KHADAS_MCU_SYS_RST_REG 0x91 /* WO */
enum {
KHADAS_BOARD_VIM1 = 0x1,
@@ -76,6 +99,7 @@ enum {
KHADAS_BOARD_VIM3,
KHADAS_BOARD_EDGE = 0x11,
KHADAS_BOARD_EDGE_V,
+ KHADAS_BOARD_EDGE2,
};
/**
--
Armbian
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Muhammed Efe Cetin <efectn@protonmail.com>
Date: Wed, 6 Mar 2024 00:09:58 +0300
Subject: mfd: khadas-mcu: drop unused code
---
drivers/mfd/khadas-mcu.c | 11 ----------
1 file changed, 11 deletions(-)
diff --git a/drivers/mfd/khadas-mcu.c b/drivers/mfd/khadas-mcu.c
index 111111111111..222222222222 100644
--- a/drivers/mfd/khadas-mcu.c
+++ b/drivers/mfd/khadas-mcu.c
@@ -84,10 +84,6 @@ static struct mfd_cell khadas_mcu_fan_cells[] = {
{ .name = "khadas-mcu-fan-ctrl", },
};
-static struct mfd_cell khadas_mcu_cells[] = {
- { .name = "khadas-mcu-user-mem", },
-};
-
static int khadas_mcu_probe(struct i2c_client *client)
{
struct device *dev = &client->dev;
@@ -109,13 +105,6 @@ static int khadas_mcu_probe(struct i2c_client *client)
return ret;
}
- ret = devm_mfd_add_devices(dev, PLATFORM_DEVID_NONE,
- khadas_mcu_cells,
- ARRAY_SIZE(khadas_mcu_cells),
- NULL, 0, NULL);
- if (ret)
- return ret;
-
if (of_property_present(dev->of_node, "#cooling-cells"))
return devm_mfd_add_devices(dev, PLATFORM_DEVID_NONE,
khadas_mcu_fan_cells,
--
Armbian
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Muhammed Efe Cetin <efectn@protonmail.com>
Date: Wed, 6 Mar 2024 00:13:10 +0300
Subject: thermal: khadas_mcu_fan: add support for Khadas Edge 2
---
drivers/thermal/khadas_mcu_fan.c | 77 +++++++++-
1 file changed, 73 insertions(+), 4 deletions(-)
diff --git a/drivers/thermal/khadas_mcu_fan.c b/drivers/thermal/khadas_mcu_fan.c
index 111111111111..222222222222 100644
--- a/drivers/thermal/khadas_mcu_fan.c
+++ b/drivers/thermal/khadas_mcu_fan.c
@@ -15,10 +15,16 @@
#include <linux/thermal.h>
#define MAX_LEVEL 3
+#define MAX_SPEED 0x64
struct khadas_mcu_fan_ctx {
struct khadas_mcu *mcu;
unsigned int level;
+
+ unsigned int fan_max_level;
+ unsigned int fan_register;
+ unsigned int *fan_cooling_levels;
+
struct thermal_cooling_device *cdev;
};
@@ -26,9 +32,21 @@ static int khadas_mcu_fan_set_level(struct khadas_mcu_fan_ctx *ctx,
unsigned int level)
{
int ret;
+ unsigned int write_level = level;
+
+ if (level > ctx->fan_max_level)
+ return -EINVAL;
+
+ if (ctx->fan_cooling_levels != NULL) {
+ write_level = ctx->fan_cooling_levels[level];
+
+ if (write_level > MAX_SPEED)
+ return -EINVAL;
+ }
+
+ ret = regmap_write(ctx->mcu->regmap, ctx->fan_register,
+ write_level);
- ret = regmap_write(ctx->mcu->regmap, KHADAS_MCU_CMD_FAN_STATUS_CTRL_REG,
- level);
if (ret)
return ret;
@@ -40,7 +58,9 @@ static int khadas_mcu_fan_set_level(struct khadas_mcu_fan_ctx *ctx,
static int khadas_mcu_fan_get_max_state(struct thermal_cooling_device *cdev,
unsigned long *state)
{
- *state = MAX_LEVEL;
+ struct khadas_mcu_fan_ctx *ctx = cdev->devdata;
+
+ *state = ctx->fan_max_level;
return 0;
}
@@ -61,7 +81,7 @@ khadas_mcu_fan_set_cur_state(struct thermal_cooling_device *cdev,
{
struct khadas_mcu_fan_ctx *ctx = cdev->devdata;
- if (state > MAX_LEVEL)
+ if (state > ctx->fan_max_level)
return -EINVAL;
if (state == ctx->level)
@@ -76,6 +96,48 @@ static const struct thermal_cooling_device_ops khadas_mcu_fan_cooling_ops = {
.set_cur_state = khadas_mcu_fan_set_cur_state,
};
+// Khadas Edge 2 sets fan level by passing fan speed(0-100). So we need different logic here like pwm-fan cooling-levels.
+// This is optional and just necessary for Edge 2.
+static int khadas_mcu_fan_get_cooling_data_edge2(struct khadas_mcu_fan_ctx *ctx, struct device *dev) {
+ struct device_node *np = ctx->mcu->dev->of_node;
+ int num, i, ret;
+
+ if (!of_property_present(np, "cooling-levels"))
+ return 0;
+
+ ret = of_property_count_u32_elems(np, "cooling-levels");
+ if (ret <= 0) {
+ dev_err(dev, "Wrong data!\n");
+ return ret ? : -EINVAL;
+ }
+
+ num = ret;
+ ctx->fan_cooling_levels = devm_kcalloc(dev, num, sizeof(u32),
+ GFP_KERNEL);
+ if (!ctx->fan_cooling_levels)
+ return -ENOMEM;
+
+ ret = of_property_read_u32_array(np, "cooling-levels",
+ ctx->fan_cooling_levels, num);
+ if (ret) {
+ dev_err(dev, "Property 'cooling-levels' cannot be read!\n");
+ return ret;
+ }
+
+ for (i = 0; i < num; i++) {
+ if (ctx->fan_cooling_levels[i] > MAX_SPEED) {
+ dev_err(dev, "PWM fan state[%d]:%d > %d\n", i,
+ ctx->fan_cooling_levels[i], MAX_SPEED);
+ return -EINVAL;
+ }
+ }
+
+ ctx->fan_max_level = num - 1;
+ ctx->fan_register = KHADAS_MCU_CMD_FAN_STATUS_CTRL_REG_V2;
+
+ return 0;
+}
+
static int khadas_mcu_fan_probe(struct platform_device *pdev)
{
struct khadas_mcu *mcu = dev_get_drvdata(pdev->dev.parent);
@@ -90,6 +152,13 @@ static int khadas_mcu_fan_probe(struct platform_device *pdev)
ctx->mcu = mcu;
platform_set_drvdata(pdev, ctx);
+ ctx->fan_max_level = MAX_LEVEL;
+ ctx->fan_register = KHADAS_MCU_CMD_FAN_STATUS_CTRL_REG;
+
+ ret = khadas_mcu_fan_get_cooling_data_edge2(ctx, dev);
+ if (ret)
+ return ret;
+
cdev = devm_thermal_of_cooling_device_register(dev->parent,
dev->parent->of_node, "khadas-mcu-fan", ctx,
&khadas_mcu_fan_cooling_ops);
--
Armbian
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Muhammed Efe Cetin <efectn@protonmail.com>
Date: Wed, 6 Mar 2024 00:14:58 +0300
Subject: dt-bindings: mfd: khadas-mcu: add cooling-levels property
---
Documentation/devicetree/bindings/mfd/khadas,mcu.yaml | 7 ++++++-
1 file changed, 6 insertions(+), 1 deletion(-)
diff --git a/Documentation/devicetree/bindings/mfd/khadas,mcu.yaml b/Documentation/devicetree/bindings/mfd/khadas,mcu.yaml
index 111111111111..222222222222 100644
--- a/Documentation/devicetree/bindings/mfd/khadas,mcu.yaml
+++ b/Documentation/devicetree/bindings/mfd/khadas,mcu.yaml
@@ -11,7 +11,7 @@ maintainers:
description: |
Khadas embeds a microcontroller on their VIM and Edge boards adding some
- system feature as PWM Fan control (for VIM2 rev14 or VIM3), User memory
+ system feature as PWM Fan control (for VIM2 rev14, VIM3, Edge2), User memory
storage, IR/Key resume control, system power LED control and more.
properties:
@@ -22,6 +22,11 @@ properties:
"#cooling-cells": # Only needed for boards having FAN control feature
const: 2
+ cooling-levels:
+ description: Max speed of PWM fan. This property is necessary for Khadas Edge 2.
+ items:
+ maximum: 100
+
reg:
maxItems: 1
--
Armbian
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Muhammed Efe Cetin <efectn@protonmail.com>
Date: Wed, 6 Mar 2024 00:17:58 +0300
Subject: arm64: dts: rockchip: Add MCU to Khadas Edge 2
---
arch/arm64/boot/dts/rockchip/rk3588s-khadas-edge2.dts | 7 +++++++
1 file changed, 7 insertions(+)
diff --git a/arch/arm64/boot/dts/rockchip/rk3588s-khadas-edge2.dts b/arch/arm64/boot/dts/rockchip/rk3588s-khadas-edge2.dts
index 111111111111..222222222222 100644
--- a/arch/arm64/boot/dts/rockchip/rk3588s-khadas-edge2.dts
+++ b/arch/arm64/boot/dts/rockchip/rk3588s-khadas-edge2.dts
@@ -304,6 +304,13 @@ hym8563: rtc@51 {
clock-output-names = "hym8563";
wakeup-source;
};
+
+ khadas_mcu: system-controller@18 {
+ compatible = "khadas,mcu";
+ reg = <0x18>;
+ cooling-levels = <0 50 72 100>;
+ #cooling-cells = <2>;
+ };
};
&pinctrl {
--
Armbian
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Muhammed Efe Cetin <efectn@protonmail.com>
Date: Mon, 25 Mar 2024 22:41:26 +0300
Subject: arm64: dts: rockchip: Add automatic fan control to Khadas Edge 2
---
arch/arm64/boot/dts/rockchip/rk3588s-khadas-edge2.dts | 56 ++++++++++
1 file changed, 56 insertions(+)
diff --git a/arch/arm64/boot/dts/rockchip/rk3588s-khadas-edge2.dts b/arch/arm64/boot/dts/rockchip/rk3588s-khadas-edge2.dts
index 111111111111..222222222222 100644
--- a/arch/arm64/boot/dts/rockchip/rk3588s-khadas-edge2.dts
+++ b/arch/arm64/boot/dts/rockchip/rk3588s-khadas-edge2.dts
@@ -313,6 +313,62 @@ khadas_mcu: system-controller@18 {
};
};
+&package_thermal {
+ polling-delay = <1000>;
+
+ trips {
+ package_fan0: package-fan0 {
+ temperature = <45000>;
+ hysteresis = <5000>;
+ type = "active";
+ };
+
+ package_fan1: package-fan1 {
+ temperature = <55000>;
+ hysteresis = <5000>;
+ type = "active";
+ };
+
+ package_fan2: package-fan2 {
+ temperature = <60000>;
+ hysteresis = <5000>;
+ type = "active";
+ };
+
+ package_fan3: package-fan3 {
+ temperature = <70000>;
+ hysteresis = <5000>;
+ type = "active";
+ };
+ };
+
+ cooling-maps {
+ map0 {
+ trip = <&package_fan0>;
+ cooling-device = <&khadas_mcu 0 1>;
+ contribution = <1024>;
+ };
+
+ map1 {
+ trip = <&package_fan1>;
+ cooling-device = <&khadas_mcu 1 2>;
+ contribution = <1024>;
+ };
+
+ map2 {
+ trip = <&package_fan2>;
+ cooling-device = <&khadas_mcu 2 3>;
+ contribution = <1024>;
+ };
+
+ map3 {
+ trip = <&package_fan3>;
+ cooling-device = <&khadas_mcu 3 THERMAL_NO_LIMIT>;
+ contribution = <1024>;
+ };
+ };
+};
+
&pinctrl {
vdd_sd {
vdd_sd_en: vdd-sd-en {
--
Armbian

@ -0,0 +1,38 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Ricardo Pardini <ricardo@pardini.net>
Date: Thu, 6 Jun 2024 23:00:05 +0200
Subject: arm64: dts: rockchip: Add NanoPC T6 SPI Flash
Signed-off-by: Ricardo Pardini <ricardo@pardini.net>
---
arch/arm64/boot/dts/rockchip/rk3588-nanopc-t6.dts | 14 ++++++++++
1 file changed, 14 insertions(+)
diff --git a/arch/arm64/boot/dts/rockchip/rk3588-nanopc-t6.dts b/arch/arm64/boot/dts/rockchip/rk3588-nanopc-t6.dts
index 111111111111..222222222222 100644
--- a/arch/arm64/boot/dts/rockchip/rk3588-nanopc-t6.dts
+++ b/arch/arm64/boot/dts/rockchip/rk3588-nanopc-t6.dts
@@ -576,6 +576,20 @@ &sdmmc {
status = "okay";
};
+&sfc {
+ pinctrl-names = "default";
+ pinctrl-0 = <&fspim1_pins>;
+ status = "okay";
+
+ flash@0 {
+ compatible = "jedec,spi-nor";
+ reg = <0x0>;
+ spi-max-frequency = <50000000>;
+ spi-rx-bus-width = <4>;
+ spi-tx-bus-width = <1>;
+ };
+};
+
&spi2 {
status = "okay";
assigned-clocks = <&cru CLK_SPI2>;
--
Armbian

Binary file not shown.

Binary file not shown.

Binary file not shown.

@ -16,7 +16,7 @@ setexpr.s bootargs *${ramdisk_addr_r}
echo "Boot args: ${bootargs}"
# Load dtb
setenv fdtfile rk3328-rock64.dtb
setenv fdtfile rk3588-friendlyelec-cm3588-nas.dtb
load ${devtype} ${devnum}:${bootpart} ${fdt_addr_r} ${fdtfile}
# ... and set fdt addr to it.
fdt addr ${fdt_addr_r}

Binary file not shown.

BIN
vmlinuz

Binary file not shown.