BananaPi BPI-F3: Update u-boot and linux patching

Signed-off-by: Patrick Yavitz <pyavitz@gmail.com>
This commit is contained in:
Patrick Yavitz
2024-12-26 10:50:34 -05:00
committed by c0rnelius
parent 7b6fcab372
commit df9ddaf44e
91 changed files with 337 additions and 477249 deletions

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -1,331 +0,0 @@
From 41a15ab971400502e93bbbf0d7336fa81daf25c9 Mon Sep 17 00:00:00 2001
From: James Deng <james.deng@spacemit.com>
Date: Tue, 30 Apr 2024 17:48:07 +0800
Subject: Update for v1.0rc1
---
include/sbi_utils/cache/cacheflush.h | 34 +++++++++-----
lib/sbi/sbi_hsm.c | 2 +-
lib/utils/psci/psci_private.h | 2 +-
.../spacemit/plat/k1x/underly_implement.c | 37 ---------------
lib/utils/psci/spacemit/plat/plat_pm.c | 4 +-
.../generic/include/spacemit/k1x/k1x_evb.h | 44 ++++++++++++++++-
.../generic/include/spacemit/k1x/k1x_fpga.h | 47 +++++++++++++++++--
platform/generic/spacemit/spacemit_k1.c | 13 +++++
8 files changed, 126 insertions(+), 57 deletions(-)
diff --git a/include/sbi_utils/cache/cacheflush.h b/include/sbi_utils/cache/cacheflush.h
index c3e353229f75..126931b25888 100644
--- a/include/sbi_utils/cache/cacheflush.h
+++ b/include/sbi_utils/cache/cacheflush.h
@@ -167,26 +167,34 @@ static inline void __mdelay(void)
cpu_relax();
}
-static inline void csi_flush_l2_cache(void)
+static inline void csi_flush_l2_cache(bool hw)
{
unsigned int hartid = current_hartid();
uintptr_t *cr =(MPIDR_AFFLVL1_VAL(hartid) == 0) ? (uintptr_t *)CLUSTER0_L2_CACHE_FLUSH_REG_BASE :
(uintptr_t *)CLUSTER1_L2_CACHE_FLUSH_REG_BASE;
- /* flush l2 cache */
- writel(readl(cr) | (1 << L2_CACHE_FLUSH_REQUEST_BIT_OFFSET), cr);
- /* k1pro */
- if (L2_CACHE_FLUSH_REQUEST_BIT_OFFSET == L2_CACHE_FLUSH_DONE_BIT_OFFSET)
- while (readl(cr) & (1 << L2_CACHE_FLUSH_DONE_BIT_OFFSET));
- else /* k1x */ {
- /* clear the request */
- while (1) {
- if ((readl(cr) & (1 << L2_CACHE_FLUSH_DONE_BIT_OFFSET)) == 0)
- break;
- __mdelay();
+ if (!hw) {
+ writel(0x0, cr);
+ /* flush l2 cache */
+ writel(readl(cr) | (1 << L2_CACHE_FLUSH_REQUEST_BIT_OFFSET), cr);
+ /* k1pro */
+ if (L2_CACHE_FLUSH_REQUEST_BIT_OFFSET == L2_CACHE_FLUSH_DONE_BIT_OFFSET)
+ while (readl(cr) & (1 << L2_CACHE_FLUSH_DONE_BIT_OFFSET));
+ else /* k1x */ {
+ /* clear the request */
+ while (1) {
+ if ((readl(cr) & (1 << L2_CACHE_FLUSH_DONE_BIT_OFFSET)) == 0)
+ break;
+ __mdelay();
+ }
+ writel(readl(cr) & ~(1 << L2_CACHE_FLUSH_REQUEST_BIT_OFFSET), cr);
}
- writel(readl(cr) & ~(1 << L2_CACHE_FLUSH_REQUEST_BIT_OFFSET), cr);
+ } else {
+ /* k1pro */
+ if (L2_CACHE_FLUSH_REQUEST_BIT_OFFSET == L2_CACHE_FLUSH_DONE_BIT_OFFSET)
+ return /* do nothing */;
+ writel((1 << L2_CACHE_FLUSH_HW_TYPE_BIT_OFFSET) | (1 << L2_CACHE_FLUSH_HW_EN_BIT_OFFSET), cr);
}
}
#endif
diff --git a/lib/sbi/sbi_hsm.c b/lib/sbi/sbi_hsm.c
index acd3c9e04c87..51c982ad7b78 100644
--- a/lib/sbi/sbi_hsm.c
+++ b/lib/sbi/sbi_hsm.c
@@ -183,7 +183,7 @@ void __noreturn sbi_hsm_hart_start_finish(struct sbi_scratch *scratch,
* */
if (cool_boot) {
csi_flush_dcache_all();
- csi_flush_l2_cache();
+ csi_flush_l2_cache(0);
}
sbi_hart_switch_mode(hartid, next_arg1, next_addr, next_mode, false);
diff --git a/lib/utils/psci/psci_private.h b/lib/utils/psci/psci_private.h
index c768d3f379ab..0a3f260f5c39 100644
--- a/lib/utils/psci/psci_private.h
+++ b/lib/utils/psci/psci_private.h
@@ -182,7 +182,7 @@ static inline void psci_do_pwrdown_cache_maintenance(int hartid, uintptr_t scrat
/* disable the tcm */
csr_write(CSR_TCMCFG, 0);
#endif
- csi_flush_l2_cache();
+ csi_flush_l2_cache(0);
}
/* disable dcache */
diff --git a/lib/utils/psci/spacemit/plat/k1x/underly_implement.c b/lib/utils/psci/spacemit/plat/k1x/underly_implement.c
index 279e6d5dc741..73feec440d27 100644
--- a/lib/utils/psci/spacemit/plat/k1x/underly_implement.c
+++ b/lib/utils/psci/spacemit/plat/k1x/underly_implement.c
@@ -5,43 +5,6 @@
#include <sbi/sbi_console.h>
#include <spacemit/spacemit_config.h>
-#define C1_CPU_RESET_BASE_ADDR (0xD4282B24)
-
-#define PMU_CAP_CORE0_IDLE_CFG (0xd4282924)
-#define PMU_CAP_CORE1_IDLE_CFG (0xd4282928)
-#define PMU_CAP_CORE2_IDLE_CFG (0xd4282960)
-#define PMU_CAP_CORE3_IDLE_CFG (0xd4282964)
-#define PMU_CAP_CORE4_IDLE_CFG (0xd4282b04)
-#define PMU_CAP_CORE5_IDLE_CFG (0xd4282b08)
-#define PMU_CAP_CORE6_IDLE_CFG (0xd4282b0c)
-#define PMU_CAP_CORE7_IDLE_CFG (0xd4282b10)
-
-#define PMU_C0_CAPMP_IDLE_CFG0 (0xd4282920)
-#define PMU_C0_CAPMP_IDLE_CFG1 (0xd42828e4)
-#define PMU_C0_CAPMP_IDLE_CFG2 (0xd4282950)
-#define PMU_C0_CAPMP_IDLE_CFG3 (0xd4282954)
-#define PMU_C1_CAPMP_IDLE_CFG0 (0xd4282b14)
-#define PMU_C1_CAPMP_IDLE_CFG1 (0xd4282b18)
-#define PMU_C1_CAPMP_IDLE_CFG2 (0xd4282b1c)
-#define PMU_C1_CAPMP_IDLE_CFG3 (0xd4282b20)
-
-#define PMU_ACPR_CLUSTER0_REG (0xd4051090)
-#define PMU_ACPR_CLUSTER1_REG (0xd4051094)
-#define PMU_ACPR_UNKONW_REG (0xd4050038)
-
-
-#define CPU_PWR_DOWN_VALUE (0x3)
-#define CLUSTER_PWR_DOWN_VALUE (0x3)
-#define CLUSTER_AXISDO_OFFSET (31)
-#define CLUSTER_DDRSD_OFFSET (27)
-#define CLUSTER_APBSD_OFFSET (26)
-#define CLUSTER_VCXOSD_OFFSET (19)
-#define CLUSTER_BIT29_OFFSET (29)
-#define CLUSTER_BIT14_OFFSET (14)
-#define CLUSTER_BIT30_OFFSET (30)
-#define CLUSTER_BIT25_OFFSET (25)
-#define CLUSTER_BIT13_OFFSET (13)
-
struct pmu_cap_wakeup {
unsigned int pmu_cap_core0_wakeup;
unsigned int pmu_cap_core1_wakeup;
diff --git a/lib/utils/psci/spacemit/plat/plat_pm.c b/lib/utils/psci/spacemit/plat/plat_pm.c
index da6f958157fa..a5b91270834f 100644
--- a/lib/utils/psci/spacemit/plat/plat_pm.c
+++ b/lib/utils/psci/spacemit/plat/plat_pm.c
@@ -7,6 +7,7 @@
#include <sbi/sbi_console.h>
#include <sbi_utils/psci/plat/arm/common/arm_def.h>
#include <sbi_utils/irqchip/fdt_irqchip_plic.h>
+#include <sbi_utils/cache/cacheflush.h>
#include "underly_implement.h"
#define CORE_PWR_STATE(state) \
@@ -81,6 +82,7 @@ static void spacemit_pwr_domain_off(const psci_power_state_t *target_state)
#endif
cci_disable_snoop_dvm_reqs(MPIDR_AFFLVL1_VAL(hartid));
spacemit_cluster_off(hartid);
+ csi_flush_l2_cache(1);
}
if (SYSTEM_PWR_STATE(target_state) == ARM_LOCAL_STATE_OFF) {
@@ -180,8 +182,8 @@ static void spacemit_pwr_domain_suspend(const psci_power_state_t *target_state)
csr_write(CSR_TCMCFG, 0);
#endif
cci_disable_snoop_dvm_reqs(clusterid);
-
spacemit_cluster_off(hartid);
+ csi_flush_l2_cache(1);
}
if (SYSTEM_PWR_STATE(target_state) == ARM_LOCAL_STATE_OFF) {
diff --git a/platform/generic/include/spacemit/k1x/k1x_evb.h b/platform/generic/include/spacemit/k1x/k1x_evb.h
index b951105e0c04..5f5b672a61a6 100644
--- a/platform/generic/include/spacemit/k1x/k1x_evb.h
+++ b/platform/generic/include/spacemit/k1x/k1x_evb.h
@@ -24,6 +24,45 @@
#define C1_RVBADDR_LO_ADDR (0xD4282C00 + 0x2B0)
#define C1_RVBADDR_HI_ADDR (0xD4282C00 + 0X2B4)
+#define C1_CPU_RESET_BASE_ADDR (0xD4282B24)
+
+#define PMU_CAP_CORE0_IDLE_CFG (0xd4282924)
+#define PMU_CAP_CORE1_IDLE_CFG (0xd4282928)
+#define PMU_CAP_CORE2_IDLE_CFG (0xd4282960)
+#define PMU_CAP_CORE3_IDLE_CFG (0xd4282964)
+#define PMU_CAP_CORE4_IDLE_CFG (0xd4282b04)
+#define PMU_CAP_CORE5_IDLE_CFG (0xd4282b08)
+#define PMU_CAP_CORE6_IDLE_CFG (0xd4282b0c)
+#define PMU_CAP_CORE7_IDLE_CFG (0xd4282b10)
+
+#define PMU_C0_CAPMP_IDLE_CFG0 (0xd4282920)
+#define PMU_C0_CAPMP_IDLE_CFG1 (0xd42828e4)
+#define PMU_C0_CAPMP_IDLE_CFG2 (0xd4282950)
+#define PMU_C0_CAPMP_IDLE_CFG3 (0xd4282954)
+#define PMU_C1_CAPMP_IDLE_CFG0 (0xd4282b14)
+#define PMU_C1_CAPMP_IDLE_CFG1 (0xd4282b18)
+#define PMU_C1_CAPMP_IDLE_CFG2 (0xd4282b1c)
+#define PMU_C1_CAPMP_IDLE_CFG3 (0xd4282b20)
+
+#define PMU_ACPR_CLUSTER0_REG (0xd4051090)
+#define PMU_ACPR_CLUSTER1_REG (0xd4051094)
+#define PMU_ACPR_UNKONW_REG (0xd4050038)
+
+
+#define CPU_PWR_DOWN_VALUE (0x3)
+#define CLUSTER_PWR_DOWN_VALUE (0x3)
+#define CLUSTER_AXISDO_OFFSET (31)
+#define CLUSTER_DDRSD_OFFSET (27)
+#define CLUSTER_APBSD_OFFSET (26)
+#define CLUSTER_VCXOSD_OFFSET (19)
+#define CLUSTER_BIT29_OFFSET (29)
+#define CLUSTER_BIT14_OFFSET (14)
+#define CLUSTER_BIT30_OFFSET (30)
+#define CLUSTER_BIT25_OFFSET (25)
+#define CLUSTER_BIT13_OFFSET (13)
+
+#define L2_HARDWARE_CACHE_FLUSH_EN (13)
+
/***************************mailbox***************************/
#define SCMI_MAILBOX_SHARE_MEM (0x2f902080)
#define PLAT_MAILBOX_REG_BASE (0x2f824000)
@@ -66,7 +105,10 @@
#define CLUSTER0_L2_CACHE_FLUSH_REG_BASE (0xD84401B0)
#define CLUSTER1_L2_CACHE_FLUSH_REG_BASE (0xD84401B4)
-#define L2_CACHE_FLUSH_REQUEST_BIT_OFFSET (0x1)
+#define L2_CACHE_FLUSH_REQUEST_BIT_OFFSET (0x1) /* sw flush l2 cache */
#define L2_CACHE_FLUSH_DONE_BIT_OFFSET (0x3)
+#define L2_CACHE_FLUSH_HW_TYPE_BIT_OFFSET (0)
+#define L2_CACHE_FLUSH_HW_EN_BIT_OFFSET (0x2)
+
#endif /* __K1X_EVB_CONFIG_H__ */
diff --git a/platform/generic/include/spacemit/k1x/k1x_fpga.h b/platform/generic/include/spacemit/k1x/k1x_fpga.h
index 4748c86b69c2..3d8964c861c4 100644
--- a/platform/generic/include/spacemit/k1x/k1x_fpga.h
+++ b/platform/generic/include/spacemit/k1x/k1x_fpga.h
@@ -24,13 +24,51 @@
#define C1_RVBADDR_LO_ADDR (0xD4282C00 + 0x2B0)
#define C1_RVBADDR_HI_ADDR (0xD4282C00 + 0X2B4)
+#define C1_CPU_RESET_BASE_ADDR (0xD4282B24)
+
+#define PMU_CAP_CORE0_IDLE_CFG (0xd4282924)
+#define PMU_CAP_CORE1_IDLE_CFG (0xd4282928)
+#define PMU_CAP_CORE2_IDLE_CFG (0xd4282960)
+#define PMU_CAP_CORE3_IDLE_CFG (0xd4282964)
+#define PMU_CAP_CORE4_IDLE_CFG (0xd4282b04)
+#define PMU_CAP_CORE5_IDLE_CFG (0xd4282b08)
+#define PMU_CAP_CORE6_IDLE_CFG (0xd4282b0c)
+#define PMU_CAP_CORE7_IDLE_CFG (0xd4282b10)
+
+#define PMU_C0_CAPMP_IDLE_CFG0 (0xd4282920)
+#define PMU_C0_CAPMP_IDLE_CFG1 (0xd42828e4)
+#define PMU_C0_CAPMP_IDLE_CFG2 (0xd4282950)
+#define PMU_C0_CAPMP_IDLE_CFG3 (0xd4282954)
+#define PMU_C1_CAPMP_IDLE_CFG0 (0xd4282b14)
+#define PMU_C1_CAPMP_IDLE_CFG1 (0xd4282b18)
+#define PMU_C1_CAPMP_IDLE_CFG2 (0xd4282b1c)
+#define PMU_C1_CAPMP_IDLE_CFG3 (0xd4282b20)
+
+#define PMU_ACPR_CLUSTER0_REG (0xd4051090)
+#define PMU_ACPR_CLUSTER1_REG (0xd4051094)
+#define PMU_ACPR_UNKONW_REG (0xd4050038)
+
+
+#define CPU_PWR_DOWN_VALUE (0x3)
+#define CLUSTER_PWR_DOWN_VALUE (0x3)
+#define CLUSTER_AXISDO_OFFSET (31)
+#define CLUSTER_DDRSD_OFFSET (27)
+#define CLUSTER_APBSD_OFFSET (26)
+#define CLUSTER_VCXOSD_OFFSET (19)
+#define CLUSTER_BIT29_OFFSET (29)
+#define CLUSTER_BIT14_OFFSET (14)
+#define CLUSTER_BIT30_OFFSET (30)
+#define CLUSTER_BIT25_OFFSET (25)
+#define CLUSTER_BIT13_OFFSET (13)
+
+#define L2_HARDWARE_CACHE_FLUSH_EN (13)
+
/***************************mailbox***************************/
#define SCMI_MAILBOX_SHARE_MEM (0x2f902080)
#define PLAT_MAILBOX_REG_BASE (0x2f824000)
/****************************scmi*****************************/
-#define PLAT_SCMI_SINGLE_CLUSTER_DOMAIN_MAP {0, 1, 2, 3}
-#define PLAT_SCMI_DOUBLE_CLUSTER_DOMAIN_MAP {0, 1, 4, 5}
+#define PLAT_SCMI_DOMAIN_MAP {0, 1, 2, 3}
/*************************cpu topology************************/
#define ARM_SYSTEM_COUNT (1U)
@@ -67,7 +105,10 @@
#define CLUSTER0_L2_CACHE_FLUSH_REG_BASE (0xD84401B0)
#define CLUSTER1_L2_CACHE_FLUSH_REG_BASE (0xD84401B4)
-#define L2_CACHE_FLUSH_REQUEST_BIT_OFFSET (0x1)
+#define L2_CACHE_FLUSH_REQUEST_BIT_OFFSET (0x1) /* sw flush l2 cache */
#define L2_CACHE_FLUSH_DONE_BIT_OFFSET (0x3)
+#define L2_CACHE_FLUSH_HW_TYPE_BIT_OFFSET (0)
+#define L2_CACHE_FLUSH_HW_EN_BIT_OFFSET (0x2)
+
#endif /* __K1X_FPGA_CONFIG_H__ */
diff --git a/platform/generic/spacemit/spacemit_k1.c b/platform/generic/spacemit/spacemit_k1.c
index 38794c2dfbb5..95218846715f 100644
--- a/platform/generic/spacemit/spacemit_k1.c
+++ b/platform/generic/spacemit/spacemit_k1.c
@@ -65,6 +65,19 @@ static void wakeup_other_core(void)
unsigned char *cpu_topology = plat_get_power_domain_tree_desc();
#endif
+#if defined(CONFIG_PLATFORM_SPACEMIT_K1X)
+ /* enable the hw l2 cache flush method for each core */
+ writel(readl((u32 *)PMU_C0_CAPMP_IDLE_CFG0) | (1 << L2_HARDWARE_CACHE_FLUSH_EN), (u32 *)PMU_C0_CAPMP_IDLE_CFG0);
+ writel(readl((u32 *)PMU_C0_CAPMP_IDLE_CFG1) | (1 << L2_HARDWARE_CACHE_FLUSH_EN), (u32 *)PMU_C0_CAPMP_IDLE_CFG1);
+ writel(readl((u32 *)PMU_C0_CAPMP_IDLE_CFG2) | (1 << L2_HARDWARE_CACHE_FLUSH_EN), (u32 *)PMU_C0_CAPMP_IDLE_CFG2);
+ writel(readl((u32 *)PMU_C0_CAPMP_IDLE_CFG3) | (1 << L2_HARDWARE_CACHE_FLUSH_EN), (u32 *)PMU_C0_CAPMP_IDLE_CFG3);
+
+ writel(readl((u32 *)PMU_C1_CAPMP_IDLE_CFG0) | (1 << L2_HARDWARE_CACHE_FLUSH_EN), (u32 *)PMU_C1_CAPMP_IDLE_CFG0);
+ writel(readl((u32 *)PMU_C1_CAPMP_IDLE_CFG1) | (1 << L2_HARDWARE_CACHE_FLUSH_EN), (u32 *)PMU_C1_CAPMP_IDLE_CFG1);
+ writel(readl((u32 *)PMU_C1_CAPMP_IDLE_CFG2) | (1 << L2_HARDWARE_CACHE_FLUSH_EN), (u32 *)PMU_C1_CAPMP_IDLE_CFG2);
+ writel(readl((u32 *)PMU_C1_CAPMP_IDLE_CFG3) | (1 << L2_HARDWARE_CACHE_FLUSH_EN), (u32 *)PMU_C1_CAPMP_IDLE_CFG3);
+#endif
+
// hart0 is already boot up
for (i = 0; i < platform.hart_count; i++) {
hartid = platform.hart_index2id[i];
--
2.35.3

View File

@@ -1,42 +0,0 @@
From ce6e8eec55a62d9e4cb5f5a767e50e9d0c2659ff Mon Sep 17 00:00:00 2001
From: James Deng <james.deng@spacemit.com>
Date: Thu, 30 May 2024 23:19:43 +0800
Subject: Update for v1.0
---
debian/opensbi-spacemit.postinst | 9 ++++++++-
1 file changed, 8 insertions(+), 1 deletion(-)
diff --git a/debian/opensbi-spacemit.postinst b/debian/opensbi-spacemit.postinst
index 1f6feca80674..9ce082ef548b 100755
--- a/debian/opensbi-spacemit.postinst
+++ b/debian/opensbi-spacemit.postinst
@@ -22,9 +22,16 @@ configure)
case $ROOT in
"/dev/mmcblk0"*)
OPENSBI=/dev/mmcblk0p3
+ OPENSBI_SEEK=0
;;
"/dev/mmcblk2"*)
OPENSBI=/dev/mmcblk2p3
+ OPENSBI_SEEK=0
+ ;;
+ "/dev/nvme0n1"*)
+ OPENSBI=/dev/mtdblock0
+ # 以KB为单位
+ OPENSBI_SEEK=448
;;
*)
echo "Unsupported root=$ROOT"
@@ -37,7 +44,7 @@ configure)
fi
if [ -n "$target" ] && [ -e $OPENSBI ]; then
- dd if=/usr/lib/riscv64-linux-gnu/opensbi/generic/fw_dynamic.itb of=$OPENSBI bs=1 && sync
+ dd if=/usr/lib/riscv64-linux-gnu/opensbi/generic/fw_dynamic.itb of=$OPENSBI seek=$OPENSBI_SEEK bs=1K && sync
fi
;;
esac
--
2.35.3

View File

@@ -1,86 +0,0 @@
From 6f1344573d4ce0638d24d960e9a7d5ff1b0426b6 Mon Sep 17 00:00:00 2001
From: James Deng <james.deng@spacemit.com>
Date: Wed, 19 Jun 2024 15:18:09 +0800
Subject: Update for v1.0.3
---
.../spacemit/plat/k1x/underly_implement.c | 24 ++++++++++++++++++-
.../generic/include/spacemit/k1x/k1x_evb.h | 4 ++--
2 files changed, 25 insertions(+), 3 deletions(-)
diff --git a/lib/utils/psci/spacemit/plat/k1x/underly_implement.c b/lib/utils/psci/spacemit/plat/k1x/underly_implement.c
index 73feec440d27..654da2d1a926 100644
--- a/lib/utils/psci/spacemit/plat/k1x/underly_implement.c
+++ b/lib/utils/psci/spacemit/plat/k1x/underly_implement.c
@@ -44,6 +44,12 @@ void spacemit_top_on(u_register_t mpidr)
(1 << CLUSTER_BIT25_OFFSET) |
(1 << CLUSTER_BIT13_OFFSET));
writel(value, cluster1_acpr);
+
+ /* enable the gpio edge detected function again
+ * */
+ value = readl((unsigned int *)0xd4051000);
+ value &= ~(1 << 21);
+ writel(value, (unsigned int *)0xd4051000);
}
/* D1P & D2 ? */
@@ -60,6 +66,7 @@ void spacemit_top_off(u_register_t mpidr)
(1 << CLUSTER_DDRSD_OFFSET) |
(1 << CLUSTER_APBSD_OFFSET) |
(1 << CLUSTER_VCXOSD_OFFSET) |
+ (1 << 3) |
(1 << CLUSTER_BIT29_OFFSET) |
(1 << CLUSTER_BIT14_OFFSET) |
(1 << CLUSTER_BIT30_OFFSET) |
@@ -72,6 +79,7 @@ void spacemit_top_off(u_register_t mpidr)
(1 << CLUSTER_DDRSD_OFFSET) |
(1 << CLUSTER_APBSD_OFFSET) |
(1 << CLUSTER_VCXOSD_OFFSET) |
+ (1 << 3) |
(1 << CLUSTER_BIT29_OFFSET) |
(1 << CLUSTER_BIT14_OFFSET) |
(1 << CLUSTER_BIT30_OFFSET) |
@@ -80,9 +88,23 @@ void spacemit_top_off(u_register_t mpidr)
writel(value, cluster1_acpr);
value = readl((unsigned int *)PMU_ACPR_UNKONW_REG);
- value |= (1 << 2);
+ value |= (1 << 2) | (1 << 0);
writel(value, (unsigned int *)PMU_ACPR_UNKONW_REG);
+ /* disable the gpio edge detect function
+ * this may cause the system cann't enter D2
+ * */
+ value = readl((unsigned int *)0xd4051000);
+ value |= (1 << 21);
+ writel(value, (unsigned int *)0xd4051000);
+
+ /* enable the refbuf function which will enhance the
+ * driving capability of the internal 26M to PLL path
+ * */
+ value = readl((unsigned int *)0xd4090104);
+ value |= (1 << 22);
+ writel(value, (unsigned int *)0xd4090104);
+
/* for wakeup debug */
writel(0xffff, (unsigned int *)0xd4051030);
}
diff --git a/platform/generic/include/spacemit/k1x/k1x_evb.h b/platform/generic/include/spacemit/k1x/k1x_evb.h
index 5f5b672a61a6..10e856965618 100644
--- a/platform/generic/include/spacemit/k1x/k1x_evb.h
+++ b/platform/generic/include/spacemit/k1x/k1x_evb.h
@@ -49,8 +49,8 @@
#define PMU_ACPR_UNKONW_REG (0xd4050038)
-#define CPU_PWR_DOWN_VALUE (0x3)
-#define CLUSTER_PWR_DOWN_VALUE (0x3)
+#define CPU_PWR_DOWN_VALUE (0x1b)
+#define CLUSTER_PWR_DOWN_VALUE (0x7)
#define CLUSTER_AXISDO_OFFSET (31)
#define CLUSTER_DDRSD_OFFSET (27)
#define CLUSTER_APBSD_OFFSET (26)
--
2.35.3

View File

@@ -1,94 +0,0 @@
From 94bf83cc0bd1c86e51f48174fa17e23427903c59 Mon Sep 17 00:00:00 2001
From: James Deng <james.deng@spacemit.com>
Date: Thu, 11 Jul 2024 14:56:36 +0800
Subject: Update for v1.0.7
---
debian/opensbi-spacemit.postinst | 24 ++++++++++++++-----
.../spacemit/plat/k1x/underly_implement.c | 13 ----------
2 files changed, 18 insertions(+), 19 deletions(-)
diff --git a/debian/opensbi-spacemit.postinst b/debian/opensbi-spacemit.postinst
index 9ce082ef548b..dce7154ac8f4 100755
--- a/debian/opensbi-spacemit.postinst
+++ b/debian/opensbi-spacemit.postinst
@@ -4,9 +4,11 @@ set -e
case "$1" in
configure)
target=""
- if grep -q '^spacemit' /sys/firmware/devicetree/base/model; then
+ if grep -q '^spacemit' /sys/firmware/devicetree/base/model || grep -q '^spacemit' /sys/devices/soc0/family; then
target="spacemit"
else
+ echo "Neither /sys/firmware/devicetree/base/model nor /sys/devices/soc0/family starts with 'spacemit'."
+ echo "This may indicate that you are installing this package in a chroot environment."
exit 0
fi
@@ -35,17 +37,27 @@ configure)
;;
*)
echo "Unsupported root=$ROOT"
- exit 0
+ exit 1
;;
esac
else
echo "Missing root= in cmdline"
- exit 0
+ exit 1
fi
- if [ -n "$target" ] && [ -e $OPENSBI ]; then
- dd if=/usr/lib/riscv64-linux-gnu/opensbi/generic/fw_dynamic.itb of=$OPENSBI seek=$OPENSBI_SEEK bs=1K && sync
- fi
+ # 待检查文件/分区列表
+ files="/usr/lib/riscv64-linux-gnu/opensbi/generic/fw_dynamic.itb $OPENSBI"
+ for file in $files; do
+ if [ ! -e "$file" ]; then
+ # 任意不存在则退出
+ echo "Missing $file"
+ exit 1
+ fi
+ done
+
+ # 此前已经做了所有检查
+ dd if=/usr/lib/riscv64-linux-gnu/opensbi/generic/fw_dynamic.itb of=$OPENSBI seek=$OPENSBI_SEEK bs=1K && sync
+
;;
esac
diff --git a/lib/utils/psci/spacemit/plat/k1x/underly_implement.c b/lib/utils/psci/spacemit/plat/k1x/underly_implement.c
index 654da2d1a926..94d53bf51d0f 100644
--- a/lib/utils/psci/spacemit/plat/k1x/underly_implement.c
+++ b/lib/utils/psci/spacemit/plat/k1x/underly_implement.c
@@ -44,12 +44,6 @@ void spacemit_top_on(u_register_t mpidr)
(1 << CLUSTER_BIT25_OFFSET) |
(1 << CLUSTER_BIT13_OFFSET));
writel(value, cluster1_acpr);
-
- /* enable the gpio edge detected function again
- * */
- value = readl((unsigned int *)0xd4051000);
- value &= ~(1 << 21);
- writel(value, (unsigned int *)0xd4051000);
}
/* D1P & D2 ? */
@@ -91,13 +85,6 @@ void spacemit_top_off(u_register_t mpidr)
value |= (1 << 2) | (1 << 0);
writel(value, (unsigned int *)PMU_ACPR_UNKONW_REG);
- /* disable the gpio edge detect function
- * this may cause the system cann't enter D2
- * */
- value = readl((unsigned int *)0xd4051000);
- value |= (1 << 21);
- writel(value, (unsigned int *)0xd4051000);
-
/* enable the refbuf function which will enhance the
* driving capability of the internal 26M to PLL path
* */
--
2.35.3

View File

@@ -1,554 +0,0 @@
From 1600b3620dd8babffcfcc7d780a31723c94270bc Mon Sep 17 00:00:00 2001
From: James Deng <james.deng@spacemit.com>
Date: Thu, 1 Aug 2024 22:09:26 +0800
Subject: Update for v1.0.11
---
debian/control | 1 +
debian/rules | 10 ++
include/sbi_utils/cache/cacheflush.h | 29 ++++
lib/utils/psci/psci_main.c | 8 +-
.../spacemit/plat/k1x/underly_implement.c | 86 +++++++++++-
lib/utils/psci/spacemit/plat/plat_pm.c | 131 ++++++++++++++----
.../psci/spacemit/plat/underly_implement.h | 2 +
lib/utils/serial/fdt_serial_uart8250.c | 1 +
.../generic/include/spacemit/k1x/k1x_evb.h | 1 +
platform/generic/spacemit/spacemit_k1.c | 23 +--
10 files changed, 246 insertions(+), 46 deletions(-)
diff --git a/debian/control b/debian/control
index 6c4a1747b5f3..f0f186707ea7 100644
--- a/debian/control
+++ b/debian/control
@@ -11,6 +11,7 @@ Rules-Requires-Root: no
Vcs-Browser: https://salsa.debian.org/opensbi-team/opensbi
Vcs-Git: https://salsa.debian.org/opensbi-team/opensbi.git
Homepage: https://github.com/riscv-software-src/opensbi
+XBS-Commit-Id:
Package: opensbi-spacemit
Architecture: all
diff --git a/debian/rules b/debian/rules
index ab9cc10c406c..3d44b43fcc38 100755
--- a/debian/rules
+++ b/debian/rules
@@ -10,9 +10,19 @@ else
VERBOSE=0
endif
+# 检查是否在 Git 仓库中,并获取 commit ID
+GIT_INSIDE := $(shell git rev-parse --is-inside-work-tree 2>/dev/null)
+ifeq ($(GIT_INSIDE),true)
+ COMMIT_ID := $(shell git rev-parse --short HEAD)
+endif
+
%:
dh $@
+override_dh_auto_configure:
+ sed -i "s/XBS-Commit-Id:.*/XBS-Commit-Id: $(COMMIT_ID)/" debian/control
+ dh_auto_configure
+
override_dh_auto_build:
make \
V=$(VERBOSE) \
diff --git a/include/sbi_utils/cache/cacheflush.h b/include/sbi_utils/cache/cacheflush.h
index 126931b25888..7887eef949ab 100644
--- a/include/sbi_utils/cache/cacheflush.h
+++ b/include/sbi_utils/cache/cacheflush.h
@@ -197,4 +197,33 @@ static inline void csi_flush_l2_cache(bool hw)
writel((1 << L2_CACHE_FLUSH_HW_TYPE_BIT_OFFSET) | (1 << L2_CACHE_FLUSH_HW_EN_BIT_OFFSET), cr);
}
}
+
+static inline void csi_flush_l2_cache_hart(bool hw, int hartid)
+{
+ uintptr_t *cr =(MPIDR_AFFLVL1_VAL(hartid) == 0) ? (uintptr_t *)CLUSTER0_L2_CACHE_FLUSH_REG_BASE :
+ (uintptr_t *)CLUSTER1_L2_CACHE_FLUSH_REG_BASE;
+
+ if (!hw) {
+ writel(0x0, cr);
+ /* flush l2 cache */
+ writel(readl(cr) | (1 << L2_CACHE_FLUSH_REQUEST_BIT_OFFSET), cr);
+ /* k1pro */
+ if (L2_CACHE_FLUSH_REQUEST_BIT_OFFSET == L2_CACHE_FLUSH_DONE_BIT_OFFSET)
+ while (readl(cr) & (1 << L2_CACHE_FLUSH_DONE_BIT_OFFSET));
+ else /* k1x */ {
+ /* clear the request */
+ while (1) {
+ if ((readl(cr) & (1 << L2_CACHE_FLUSH_DONE_BIT_OFFSET)) == 0)
+ break;
+ __mdelay();
+ }
+ writel(readl(cr) & ~(1 << L2_CACHE_FLUSH_REQUEST_BIT_OFFSET), cr);
+ }
+ } else {
+ /* k1pro */
+ if (L2_CACHE_FLUSH_REQUEST_BIT_OFFSET == L2_CACHE_FLUSH_DONE_BIT_OFFSET)
+ return /* do nothing */;
+ writel((1 << L2_CACHE_FLUSH_HW_TYPE_BIT_OFFSET) | (1 << L2_CACHE_FLUSH_HW_EN_BIT_OFFSET), cr);
+ }
+}
#endif
diff --git a/lib/utils/psci/psci_main.c b/lib/utils/psci/psci_main.c
index a3ce138c00cc..e89bb4ad3f39 100644
--- a/lib/utils/psci/psci_main.c
+++ b/lib/utils/psci/psci_main.c
@@ -81,10 +81,10 @@ int psci_cpu_off(void)
* The only error cpu_off can return is E_DENIED. So check if that's
* indeed the case.
*/
- if (rc != PSCI_E_DENIED) {
- sbi_printf("%s:%d, err\n", __func__, __LINE__);
- sbi_hart_hang();
- }
+// if (rc != PSCI_E_DENIED) {
+// sbi_printf("%s:%d, err\n", __func__, __LINE__);
+// sbi_hart_hang();
+// }
return rc;
}
diff --git a/lib/utils/psci/spacemit/plat/k1x/underly_implement.c b/lib/utils/psci/spacemit/plat/k1x/underly_implement.c
index 94d53bf51d0f..f87bacc7297d 100644
--- a/lib/utils/psci/spacemit/plat/k1x/underly_implement.c
+++ b/lib/utils/psci/spacemit/plat/k1x/underly_implement.c
@@ -30,7 +30,8 @@ void spacemit_top_on(u_register_t mpidr)
(1 << CLUSTER_BIT14_OFFSET) |
(1 << CLUSTER_BIT30_OFFSET) |
(1 << CLUSTER_BIT25_OFFSET) |
- (1 << CLUSTER_BIT13_OFFSET));
+ (1 << CLUSTER_BIT13_OFFSET) |
+ (1 << CLUSTER_VOTE_AP_SLPEN));
writel(value, cluster0_acpr);
value = readl(cluster1_acpr);
@@ -42,7 +43,8 @@ void spacemit_top_on(u_register_t mpidr)
(1 << CLUSTER_BIT14_OFFSET) |
(1 << CLUSTER_BIT30_OFFSET) |
(1 << CLUSTER_BIT25_OFFSET) |
- (1 << CLUSTER_BIT13_OFFSET));
+ (1 << CLUSTER_BIT13_OFFSET) |
+ (1 << CLUSTER_VOTE_AP_SLPEN));
writel(value, cluster1_acpr);
}
@@ -60,7 +62,7 @@ void spacemit_top_off(u_register_t mpidr)
(1 << CLUSTER_DDRSD_OFFSET) |
(1 << CLUSTER_APBSD_OFFSET) |
(1 << CLUSTER_VCXOSD_OFFSET) |
- (1 << 3) |
+ (1 << CLUSTER_VOTE_AP_SLPEN) |
(1 << CLUSTER_BIT29_OFFSET) |
(1 << CLUSTER_BIT14_OFFSET) |
(1 << CLUSTER_BIT30_OFFSET) |
@@ -73,7 +75,7 @@ void spacemit_top_off(u_register_t mpidr)
(1 << CLUSTER_DDRSD_OFFSET) |
(1 << CLUSTER_APBSD_OFFSET) |
(1 << CLUSTER_VCXOSD_OFFSET) |
- (1 << 3) |
+ (1 << CLUSTER_VOTE_AP_SLPEN) |
(1 << CLUSTER_BIT29_OFFSET) |
(1 << CLUSTER_BIT14_OFFSET) |
(1 << CLUSTER_BIT30_OFFSET) |
@@ -279,6 +281,82 @@ void spacemit_wakeup_cpu(u_register_t mpidr)
writel(1 << target_cpu_idx, cpu_reset_base);
}
+int spacemit_core_enter_c2(u_register_t mpidr)
+{
+ unsigned int value;
+
+ /* wait the cpu enter c2 */
+ value = readl((unsigned int *)0xd4282890);
+
+ if (mpidr == 0) {
+ if (value & (1 << 6))
+ return 1;
+ } else if (mpidr == 1) {
+ if (value & (1 << 9))
+ return 1;
+ } else if (mpidr == 2) {
+ if (value & (1 << 12))
+ return 1;
+ } else if (mpidr == 3) {
+ if (value & (1 << 15))
+ return 1;
+ } else if (mpidr == 4) {
+ if (value & (1 << 22))
+ return 1;
+ } else if (mpidr == 5) {
+ if (value & (1 << 25))
+ return 1;
+ } else if (mpidr == 6) {
+ if (value & (1 << 28))
+ return 1;
+ } else if (mpidr == 7) {
+ if (value & (1 << 31))
+ return 1;
+ } else {
+ return 0;
+ }
+
+ return 0;
+}
+
+void spacemit_wait_core_enter_c2(u_register_t mpidr)
+{
+ unsigned int value;
+
+ while (1) {
+ /* wait the cpu enter c2 */
+ value = readl((unsigned int *)0xd4282890);
+
+ if (mpidr == 0) {
+ if (value & (1 << 6))
+ return;
+ } else if (mpidr == 1) {
+ if (value & (1 << 9))
+ return;
+ } else if (mpidr == 2) {
+ if (value & (1 << 12))
+ return;
+ } else if (mpidr == 3) {
+ if (value & (1 << 15))
+ return;
+ } else if (mpidr == 4) {
+ if (value & (1 << 22))
+ return;
+ } else if (mpidr == 5) {
+ if (value & (1 << 25))
+ return;
+ } else if (mpidr == 6) {
+ if (value & (1 << 28))
+ return;
+ } else if (mpidr == 7) {
+ if (value & (1 << 31))
+ return;
+ } else {
+ ;
+ }
+ }
+}
+
void spacemit_assert_cpu(u_register_t mpidr)
{
unsigned int target_cpu_idx;
diff --git a/lib/utils/psci/spacemit/plat/plat_pm.c b/lib/utils/psci/spacemit/plat/plat_pm.c
index a5b91270834f..166bc3c7be1f 100644
--- a/lib/utils/psci/spacemit/plat/plat_pm.c
+++ b/lib/utils/psci/spacemit/plat/plat_pm.c
@@ -1,14 +1,20 @@
#include <sbi/sbi_types.h>
+#include <sbi/riscv_locks.h>
#include <sbi/riscv_asm.h>
#include <sbi_utils/cci/cci.h>
#include <sbi_utils/psci/psci.h>
#include <sbi/sbi_scratch.h>
+#include <sbi/sbi_ipi.h>
#include <sbi/sbi_hart.h>
+#include <sbi/sbi_hsm.h>
+#include <sbi/sbi_domain.h>
#include <sbi/sbi_console.h>
+#include <sbi/sbi_hartmask.h>
#include <sbi_utils/psci/plat/arm/common/arm_def.h>
#include <sbi_utils/irqchip/fdt_irqchip_plic.h>
#include <sbi_utils/cache/cacheflush.h>
#include "underly_implement.h"
+#include "../../psci_private.h"
#define CORE_PWR_STATE(state) \
((state)->pwr_domain_state[MPIDR_AFFLVL0])
@@ -20,17 +26,39 @@
/* reserved for future used */
/* unsigned long __plic_regsave_offset_ptr; */
+static spinlock_t psciipi_lock = SPIN_LOCK_INITIALIZER;
+static struct sbi_hartmask psciipi_wait_hmask = { 0 };
+
+static void wake_idle_harts(struct sbi_scratch *scratch, u32 hartid)
+{
+ spin_lock(&psciipi_lock);
+
+ /* Send an IPI to all HARTs of the cluster that waiting for waked up */
+ for (u32 i = 0; i < PLATFORM_MAX_CPUS_PER_CLUSTER * PLATFORM_CLUSTER_COUNT; i++) {
+ if (i != hartid) {
+ sbi_hartmask_set_hart(i, &psciipi_wait_hmask);
+ sbi_ipi_raw_send(i);
+ }
+ }
+
+ spin_unlock(&psciipi_lock);
+}
+
static int spacemit_pwr_domain_on(u_register_t mpidr)
{
/* wakeup the cpu */
- spacemit_wakeup_cpu(mpidr);
+ if (spacemit_core_enter_c2(mpidr)) {
+ spacemit_wakeup_cpu(mpidr);
+ } else {
+ sbi_ipi_raw_send(mpidr);
+ }
return 0;
}
static void spacemit_pwr_domain_on_finish(const psci_power_state_t *target_state)
{
- unsigned int hartid = current_hartid();
+ unsigned int hartid = current_hartid();
if (SYSTEM_PWR_STATE(target_state) == ARM_LOCAL_STATE_OFF) {
/* D1P */
@@ -42,12 +70,12 @@ static void spacemit_pwr_domain_on_finish(const psci_power_state_t *target_state
* No need for locks as no other cpu is active at the moment.
*/
if (CLUSTER_PWR_STATE(target_state) == PLAT_MAX_OFF_STATE) {
- spacemit_cluster_on(hartid);
+ spacemit_cluster_on(hartid);
#if defined(CONFIG_PLATFORM_SPACEMIT_K1X)
/* disable the tcm */
csr_write(CSR_TCMCFG, 0);
#endif
- cci_enable_snoop_dvm_reqs(MPIDR_AFFLVL1_VAL(hartid));
+ cci_enable_snoop_dvm_reqs(MPIDR_AFFLVL1_VAL(hartid));
#if defined(CONFIG_PLATFORM_SPACEMIT_K1X)
/* enable the tcm */
csr_write(CSR_TCMCFG, 1);
@@ -62,6 +90,7 @@ static int spacemit_pwr_domain_off_early(const psci_power_state_t *target_state)
/* clear the external irq pending */
csr_clear(CSR_MIP, MIP_MEIP);
csr_clear(CSR_MIP, MIP_SEIP);
+ csr_clear(CSR_MIP, MIP_MSIP);
/* here we clear the sstimer pending if this core have */
if (sbi_hart_has_extension(sbi_scratch_thishart_ptr(), SBI_HART_EXT_SSTC)) {
@@ -76,28 +105,65 @@ static void spacemit_pwr_domain_off(const psci_power_state_t *target_state)
unsigned int hartid = current_hartid();
if (CLUSTER_PWR_STATE(target_state) == PLAT_MAX_OFF_STATE) {
-#if defined(CONFIG_PLATFORM_SPACEMIT_K1X)
- /* disable the tcm */
- csr_write(CSR_TCMCFG, 0);
-#endif
- cci_disable_snoop_dvm_reqs(MPIDR_AFFLVL1_VAL(hartid));
- spacemit_cluster_off(hartid);
- csi_flush_l2_cache(1);
+ /* power-off cluster */
+ spacemit_cluster_off(hartid);
}
if (SYSTEM_PWR_STATE(target_state) == ARM_LOCAL_STATE_OFF) {
/* D1P */
spacemit_top_off(hartid);
}
-
- spacemit_assert_cpu(hartid);
}
static void spacemit_pwr_domain_pwr_down_wfi(const psci_power_state_t *target_state)
{
- while (1) {
- asm volatile ("wfi");
+ int hstate;
+ unsigned long saved_mie, cmip;
+ unsigned int hartid = current_hartid();
+
+ hstate = sbi_hsm_hart_get_state(sbi_domain_thishart_ptr(), hartid);
+
+ /* Save MIE CSR */
+ saved_mie = csr_read(CSR_MIE);
+
+ /* Set MSIE and MEIE bits to receive IPI */
+ if (hstate == SBI_HSM_STATE_SUSPENDED) {
+ csr_set(CSR_MIE, MIP_MSIP | MIP_MEIP);
+
+ /* Wait for wakeup source to finish using WFI */
+ do {
+ wfi();
+ cmip = csr_read(CSR_MIP);
+ } while (!(cmip & (MIP_MSIP | MIP_MEIP)));
+ } else {
+ csr_set(CSR_MIE, MIP_MSIP);
+
+ /* Wait for wakeup source to finish using WFI */
+ do {
+ wfi();
+ cmip = csr_read(CSR_MIP);
+ } while (!(cmip & (MIP_MSIP)));
+
+ spin_lock(&psciipi_lock);
+
+ if (sbi_hartmask_test_hart(hartid, &psciipi_wait_hmask)) {
+ sbi_ipi_raw_clear(hartid);
+ /* Restore MIE CSR */
+ csr_write(CSR_MIE, saved_mie);
+
+ spin_unlock(&psciipi_lock);
+
+ spacemit_assert_cpu(hartid);
+
+ while (1)
+ asm volatile ("wfi");
+ }
+
+ spin_unlock(&psciipi_lock);
}
+
+ /* Restore MIE CSR */
+ csr_write(CSR_MIE, saved_mie);
}
static void spacemit_pwr_domain_on_finish_late(const psci_power_state_t *target_state)
@@ -158,9 +224,8 @@ static int spacemit_validate_power_state(unsigned int power_state,
static void spacemit_pwr_domain_suspend(const psci_power_state_t *target_state)
{
- unsigned int clusterid;
unsigned int hartid = current_hartid();
-
+
/*
* CSS currently supports retention only at cpu level. Just return
* as nothing is to be done for retention.
@@ -168,30 +233,40 @@ static void spacemit_pwr_domain_suspend(const psci_power_state_t *target_state)
if (CORE_PWR_STATE(target_state) == ARM_LOCAL_STATE_RET)
return;
-
if (CORE_PWR_STATE(target_state) != ARM_LOCAL_STATE_OFF) {
sbi_printf("%s:%d\n", __func__, __LINE__);
sbi_hart_hang();
}
- /* Cluster is to be turned off, so disable coherency */
- if (CLUSTER_PWR_STATE(target_state) == ARM_LOCAL_STATE_OFF) {
- clusterid = MPIDR_AFFLVL1_VAL(hartid);
+ /* power-off cluster */
+ if (CLUSTER_PWR_STATE(target_state) == PLAT_MAX_OFF_STATE)
+ spacemit_cluster_off(hartid);
+
+ if (SYSTEM_PWR_STATE(target_state) == ARM_LOCAL_STATE_OFF) {
#if defined(CONFIG_PLATFORM_SPACEMIT_K1X)
/* disable the tcm */
csr_write(CSR_TCMCFG, 0);
#endif
- cci_disable_snoop_dvm_reqs(clusterid);
- spacemit_cluster_off(hartid);
- csi_flush_l2_cache(1);
- }
+ wake_idle_harts(NULL, hartid);
- if (SYSTEM_PWR_STATE(target_state) == ARM_LOCAL_STATE_OFF) {
/* D1P & D2 */
+ csi_flush_l2_cache_hart(0, 0);
+ csi_flush_l2_cache_hart(0, PLATFORM_MAX_CPUS_PER_CLUSTER);
+
+ cci_disable_snoop_dvm_reqs(0);
+ cci_disable_snoop_dvm_reqs(1);
+
+ /* assert othter cpu & wait other cpu enter c2 */
+ for (u32 i = 0; i < PLATFORM_MAX_CPUS_PER_CLUSTER * PLATFORM_CLUSTER_COUNT; i++) {
+ if (i != hartid) {
+ spacemit_wait_core_enter_c2(i);
+ }
+ }
+
+ spacemit_assert_cpu(hartid);
+
spacemit_top_off(hartid);
}
-
- spacemit_assert_cpu(hartid);
}
static void spacemit_pwr_domain_suspend_finish(const psci_power_state_t *target_state)
diff --git a/lib/utils/psci/spacemit/plat/underly_implement.h b/lib/utils/psci/spacemit/plat/underly_implement.h
index dd6c972325bb..7c11db518a3f 100644
--- a/lib/utils/psci/spacemit/plat/underly_implement.h
+++ b/lib/utils/psci/spacemit/plat/underly_implement.h
@@ -9,6 +9,8 @@ void spacemit_cluster_on(u_register_t mpidr);
void spacemit_cluster_off(u_register_t mpidr);
void spacemit_wakeup_cpu(u_register_t mpidr);
void spacemit_assert_cpu(u_register_t mpidr);
+int spacemit_core_enter_c2(u_register_t mpidr);
+void spacemit_wait_core_enter_c2(u_register_t mpidr);
void spacemit_deassert_cpu(void);
#endif
diff --git a/lib/utils/serial/fdt_serial_uart8250.c b/lib/utils/serial/fdt_serial_uart8250.c
index 7b5d6a4c2f18..51ea91c7665f 100644
--- a/lib/utils/serial/fdt_serial_uart8250.c
+++ b/lib/utils/serial/fdt_serial_uart8250.c
@@ -30,6 +30,7 @@ static const struct fdt_match serial_uart8250_match[] = {
{ .compatible = "ns16550" },
{ .compatible = "ns16550a" },
{ .compatible = "snps,dw-apb-uart" },
+ { .compatible = "spacemit,pxa-uart" },
{ },
};
diff --git a/platform/generic/include/spacemit/k1x/k1x_evb.h b/platform/generic/include/spacemit/k1x/k1x_evb.h
index 10e856965618..e7381ca245da 100644
--- a/platform/generic/include/spacemit/k1x/k1x_evb.h
+++ b/platform/generic/include/spacemit/k1x/k1x_evb.h
@@ -60,6 +60,7 @@
#define CLUSTER_BIT30_OFFSET (30)
#define CLUSTER_BIT25_OFFSET (25)
#define CLUSTER_BIT13_OFFSET (13)
+#define CLUSTER_VOTE_AP_SLPEN (3)
#define L2_HARDWARE_CACHE_FLUSH_EN (13)
diff --git a/platform/generic/spacemit/spacemit_k1.c b/platform/generic/spacemit/spacemit_k1.c
index 95218846715f..2f9deb1a7940 100644
--- a/platform/generic/spacemit/spacemit_k1.c
+++ b/platform/generic/spacemit/spacemit_k1.c
@@ -67,15 +67,15 @@ static void wakeup_other_core(void)
#if defined(CONFIG_PLATFORM_SPACEMIT_K1X)
/* enable the hw l2 cache flush method for each core */
- writel(readl((u32 *)PMU_C0_CAPMP_IDLE_CFG0) | (1 << L2_HARDWARE_CACHE_FLUSH_EN), (u32 *)PMU_C0_CAPMP_IDLE_CFG0);
- writel(readl((u32 *)PMU_C0_CAPMP_IDLE_CFG1) | (1 << L2_HARDWARE_CACHE_FLUSH_EN), (u32 *)PMU_C0_CAPMP_IDLE_CFG1);
- writel(readl((u32 *)PMU_C0_CAPMP_IDLE_CFG2) | (1 << L2_HARDWARE_CACHE_FLUSH_EN), (u32 *)PMU_C0_CAPMP_IDLE_CFG2);
- writel(readl((u32 *)PMU_C0_CAPMP_IDLE_CFG3) | (1 << L2_HARDWARE_CACHE_FLUSH_EN), (u32 *)PMU_C0_CAPMP_IDLE_CFG3);
-
- writel(readl((u32 *)PMU_C1_CAPMP_IDLE_CFG0) | (1 << L2_HARDWARE_CACHE_FLUSH_EN), (u32 *)PMU_C1_CAPMP_IDLE_CFG0);
- writel(readl((u32 *)PMU_C1_CAPMP_IDLE_CFG1) | (1 << L2_HARDWARE_CACHE_FLUSH_EN), (u32 *)PMU_C1_CAPMP_IDLE_CFG1);
- writel(readl((u32 *)PMU_C1_CAPMP_IDLE_CFG2) | (1 << L2_HARDWARE_CACHE_FLUSH_EN), (u32 *)PMU_C1_CAPMP_IDLE_CFG2);
- writel(readl((u32 *)PMU_C1_CAPMP_IDLE_CFG3) | (1 << L2_HARDWARE_CACHE_FLUSH_EN), (u32 *)PMU_C1_CAPMP_IDLE_CFG3);
+ /* writel(readl((u32 *)PMU_C0_CAPMP_IDLE_CFG0) | (1 << L2_HARDWARE_CACHE_FLUSH_EN), (u32 *)PMU_C0_CAPMP_IDLE_CFG0); */
+ /* writel(readl((u32 *)PMU_C0_CAPMP_IDLE_CFG1) | (1 << L2_HARDWARE_CACHE_FLUSH_EN), (u32 *)PMU_C0_CAPMP_IDLE_CFG1); */
+ /* writel(readl((u32 *)PMU_C0_CAPMP_IDLE_CFG2) | (1 << L2_HARDWARE_CACHE_FLUSH_EN), (u32 *)PMU_C0_CAPMP_IDLE_CFG2); */
+ /* writel(readl((u32 *)PMU_C0_CAPMP_IDLE_CFG3) | (1 << L2_HARDWARE_CACHE_FLUSH_EN), (u32 *)PMU_C0_CAPMP_IDLE_CFG3); */
+
+ /* writel(readl((u32 *)PMU_C1_CAPMP_IDLE_CFG0) | (1 << L2_HARDWARE_CACHE_FLUSH_EN), (u32 *)PMU_C1_CAPMP_IDLE_CFG0); */
+ /* writel(readl((u32 *)PMU_C1_CAPMP_IDLE_CFG1) | (1 << L2_HARDWARE_CACHE_FLUSH_EN), (u32 *)PMU_C1_CAPMP_IDLE_CFG1); */
+ /* writel(readl((u32 *)PMU_C1_CAPMP_IDLE_CFG2) | (1 << L2_HARDWARE_CACHE_FLUSH_EN), (u32 *)PMU_C1_CAPMP_IDLE_CFG2); */
+ /* writel(readl((u32 *)PMU_C1_CAPMP_IDLE_CFG3) | (1 << L2_HARDWARE_CACHE_FLUSH_EN), (u32 *)PMU_C1_CAPMP_IDLE_CFG3); */
#endif
// hart0 is already boot up
@@ -188,7 +188,8 @@ static int spacemit_hart_start(unsigned int hartid, unsigned long saddr)
static int spacemit_hart_stop(void)
{
psci_cpu_off();
- return 0;
+
+ return SBI_ENOTSUPP;
}
static int spacemit_hart_suspend(unsigned int suspend_type)
@@ -265,6 +266,8 @@ static bool spacemit_cold_boot_allowed(u32 hartid, const struct fdt_match *match
static const struct fdt_match spacemit_k1_match[] = {
{ .compatible = "spacemit,k1-pro" },
{ .compatible = "spacemit,k1x" },
+ { .compatible = "spacemit,k1-x" },
+ { .compatible = "spacemit,k1" },
{ },
};
--
2.35.3

View File

@@ -1,26 +0,0 @@
From a26e37daaeb01f027e4753f854716f0f15eb3d13 Mon Sep 17 00:00:00 2001
From: James Deng <james.deng@spacemit.com>
Date: Fri, 16 Aug 2024 23:44:13 +0800
Subject: Update for v1.0.13
---
lib/utils/psci/spacemit/plat/plat_pm.c | 3 +++
1 file changed, 3 insertions(+)
diff --git a/lib/utils/psci/spacemit/plat/plat_pm.c b/lib/utils/psci/spacemit/plat/plat_pm.c
index 166bc3c7be1f..32aec9d308ab 100644
--- a/lib/utils/psci/spacemit/plat/plat_pm.c
+++ b/lib/utils/psci/spacemit/plat/plat_pm.c
@@ -147,6 +147,9 @@ static void spacemit_pwr_domain_pwr_down_wfi(const psci_power_state_t *target_st
spin_lock(&psciipi_lock);
if (sbi_hartmask_test_hart(hartid, &psciipi_wait_hmask)) {
+
+ sbi_hartmask_clear_hart(hartid, &psciipi_wait_hmask);
+
sbi_ipi_raw_clear(hartid);
/* Restore MIE CSR */
csr_write(CSR_MIE, saved_mie);
--
2.35.3

View File

@@ -1,46 +0,0 @@
From 6cf0c8e6ed09841cdbff7b3788efa608ac5b08aa Mon Sep 17 00:00:00 2001
From: James Deng <james.deng@spacemit.com>
Date: Sat, 31 Aug 2024 14:23:34 +0800
Subject: Update for v1.0.14
---
debian/opensbi-spacemit.postinst | 15 +++++++++++----
1 file changed, 11 insertions(+), 4 deletions(-)
diff --git a/debian/opensbi-spacemit.postinst b/debian/opensbi-spacemit.postinst
index dce7154ac8f4..0362a598a14b 100755
--- a/debian/opensbi-spacemit.postinst
+++ b/debian/opensbi-spacemit.postinst
@@ -31,9 +31,15 @@ configure)
OPENSBI_SEEK=0
;;
"/dev/nvme0n1"*)
- OPENSBI=/dev/mtdblock0
- # 以KB为单位
- OPENSBI_SEEK=448
+ if [ ! -e "/dev/mtdblock4" ]; then
+ OPENSBI=/dev/mtdblock0
+ # 以KB为单位
+ OPENSBI_SEEK=448
+ else
+ OPENSBI=/dev/mtdblock4
+ # 以KB为单位
+ OPENSBI_SEEK=0
+ fi
;;
*)
echo "Unsupported root=$ROOT"
@@ -56,8 +62,9 @@ configure)
done
# 此前已经做了所有检查
+ set -x
dd if=/usr/lib/riscv64-linux-gnu/opensbi/generic/fw_dynamic.itb of=$OPENSBI seek=$OPENSBI_SEEK bs=1K && sync
-
+ set +x
;;
esac
--
2.35.3

View File

@@ -1,108 +0,0 @@
From 08916e4fe06451080a8882d6955df9e5947e352e Mon Sep 17 00:00:00 2001
From: James Deng <james.deng@spacemit.com>
Date: Sat, 7 Sep 2024 21:08:45 +0800
Subject: Update for v1.0.15
---
.../spacemit/plat/k1x/underly_implement.c | 20 ++++++++++++++
lib/utils/psci/spacemit/plat/plat_pm.c | 27 +++++++++++--------
.../psci/spacemit/plat/underly_implement.h | 1 +
3 files changed, 37 insertions(+), 11 deletions(-)
diff --git a/lib/utils/psci/spacemit/plat/k1x/underly_implement.c b/lib/utils/psci/spacemit/plat/k1x/underly_implement.c
index f87bacc7297d..825db86dddfe 100644
--- a/lib/utils/psci/spacemit/plat/k1x/underly_implement.c
+++ b/lib/utils/psci/spacemit/plat/k1x/underly_implement.c
@@ -319,6 +319,26 @@ int spacemit_core_enter_c2(u_register_t mpidr)
return 0;
}
+int spacemit_cluster_enter_m2(u_register_t mpidr)
+{
+ unsigned int value;
+
+ /* wait the cpu enter M2 */
+ value = readl((unsigned int *)0xd4282890);
+
+ if (mpidr == 0 || mpidr == 1 || mpidr == 2 || mpidr == 3) {
+ if (value & (1 << 3))
+ return 1;
+ } else if (mpidr == 4 || mpidr == 5 || mpidr == 6 || mpidr == 7) {
+ if (value & (1 << 19))
+ return 1;
+ } else {
+ return 0;
+ }
+
+ return 0;
+}
+
void spacemit_wait_core_enter_c2(u_register_t mpidr)
{
unsigned int value;
diff --git a/lib/utils/psci/spacemit/plat/plat_pm.c b/lib/utils/psci/spacemit/plat/plat_pm.c
index 32aec9d308ab..e3f494065f23 100644
--- a/lib/utils/psci/spacemit/plat/plat_pm.c
+++ b/lib/utils/psci/spacemit/plat/plat_pm.c
@@ -228,7 +228,7 @@ static int spacemit_validate_power_state(unsigned int power_state,
static void spacemit_pwr_domain_suspend(const psci_power_state_t *target_state)
{
unsigned int hartid = current_hartid();
-
+
/*
* CSS currently supports retention only at cpu level. Just return
* as nothing is to be done for retention.
@@ -250,22 +250,27 @@ static void spacemit_pwr_domain_suspend(const psci_power_state_t *target_state)
/* disable the tcm */
csr_write(CSR_TCMCFG, 0);
#endif
- wake_idle_harts(NULL, hartid);
+ if (!spacemit_cluster_enter_m2(PLATFORM_MAX_CPUS_PER_CLUSTER)) {
+ wake_idle_harts(NULL, hartid);
- /* D1P & D2 */
- csi_flush_l2_cache_hart(0, 0);
- csi_flush_l2_cache_hart(0, PLATFORM_MAX_CPUS_PER_CLUSTER);
+ csi_flush_l2_cache_hart(0, 0);
+ csi_flush_l2_cache_hart(0, PLATFORM_MAX_CPUS_PER_CLUSTER);
- cci_disable_snoop_dvm_reqs(0);
- cci_disable_snoop_dvm_reqs(1);
+ cci_disable_snoop_dvm_reqs(0);
+ cci_disable_snoop_dvm_reqs(1);
- /* assert othter cpu & wait other cpu enter c2 */
- for (u32 i = 0; i < PLATFORM_MAX_CPUS_PER_CLUSTER * PLATFORM_CLUSTER_COUNT; i++) {
- if (i != hartid) {
- spacemit_wait_core_enter_c2(i);
+ /* assert othter cpu & wait other cpu enter c2 */
+ for (u32 i = 0; i < PLATFORM_MAX_CPUS_PER_CLUSTER * PLATFORM_CLUSTER_COUNT; i++) {
+ if (i != hartid) {
+ spacemit_wait_core_enter_c2(i);
+ }
}
+ } else {
+ csi_flush_l2_cache_hart(0, 0);
+ cci_disable_snoop_dvm_reqs(0);
}
+
spacemit_assert_cpu(hartid);
spacemit_top_off(hartid);
diff --git a/lib/utils/psci/spacemit/plat/underly_implement.h b/lib/utils/psci/spacemit/plat/underly_implement.h
index 7c11db518a3f..80f1377d1116 100644
--- a/lib/utils/psci/spacemit/plat/underly_implement.h
+++ b/lib/utils/psci/spacemit/plat/underly_implement.h
@@ -10,6 +10,7 @@ void spacemit_cluster_off(u_register_t mpidr);
void spacemit_wakeup_cpu(u_register_t mpidr);
void spacemit_assert_cpu(u_register_t mpidr);
int spacemit_core_enter_c2(u_register_t mpidr);
+int spacemit_cluster_enter_m2(u_register_t mpidr);
void spacemit_wait_core_enter_c2(u_register_t mpidr);
void spacemit_deassert_cpu(void);
--
2.35.3

View File

@@ -1,45 +0,0 @@
config: # This is file 'patch/kernel/spacemit-6.1/0000.patching_config.yaml'
# PATCH NUMBERING INFO
#
# Patches should be ordered in such a way that general kernel patches are applied first, then SoC-related patches and at last board-specific patches
#
# Patch numbers in this folder are sorted by category:
#
# 000* for general patches
# 0** for Bianbu-Linux-related patches
# 1** for other SoC-related patches
# 5** for board specific patches
# Just some info stuff; not used by the patching scripts
name: spacemit-6.1
kind: kernel
type: mainline # or: vendor
branch: linux-6.1.y
last-known-good-tag: v6.1.96
maintainers:
- { github: none, name: none, email: none, armbian-forum: none }
# .dts files in these directories will be copied as-is to the build tree; later ones overwrite earlier ones.
# This is meant to provide a way to "add a board DTS" without having to null-patch them in.
dts-directories:
- { source: "dt", target: "arch/riscv/boot/dts/spacemit" }
# Every file in these directories will be copied as-is to the build tree; later ones overwrite earlier ones
# This is meant as a way to have overlays, bare, in a directory, without having to null-patch them in.
# @TODO need a solution to auto-Makefile the overlays as well
overlay-directories:
- { source: "overlay", target: "arch/riscv/boot/dts/spacemit/overlay" }
# The Makefile in each of these directories will be magically patched to include the dts files copied
# or patched-in; overlay subdir will be included "-y" if it exists.
# No more Makefile patching needed, yay!
auto-patch-dt-makefile:
- { directory: "arch/riscv/boot/dts/spacemit", config-var: "CONFIG_SOC_SPACEMIT_K1X" }
# Configuration for when applying patches to git / auto-rewriting patches (development cycle helpers)
patches-to-git:
do-not-commit-files:
- "MAINTAINERS" # constant churn, drop them. sorry.
do-not-commit-regexes: # Python-style regexes
- "^arch/([a-zA-Z0-9]+)/boot/dts/([a-zA-Z0-9]+)/Makefile$" # ignore DT Makefile patches, we've an auto-patcher now

View File

@@ -1,31 +0,0 @@
From 8a2e5ced1c97d81c3d7cf230a63aac66076e1ca0 Mon Sep 17 00:00:00 2001
From: ColorfulRhino <ColorfulRhino@armbian.com>
Date: Fri, 21 Jun 2024 11:54:06 -0400
Subject: [PATCH] Add SpacemiT subdirectory to dts Makefile
---
arch/riscv/boot/dts/Makefile | 1 +
arch/riscv/boot/dts/spacemit/Makefile | 5 +
diff --git a/arch/riscv/boot/dts/Makefile b/arch/riscv/boot/dts/Makefile
index ff174996cdfd..cc6a06356338 100644
--- a/arch/riscv/boot/dts/Makefile
+++ b/arch/riscv/boot/dts/Makefile
@@ -3,5 +3,6 @@ subdir-y += sifive
subdir-y += starfive
subdir-$(CONFIG_SOC_CANAAN_K210_DTB_BUILTIN) += canaan
subdir-y += microchip
+subdir-y += spacemit
obj-$(CONFIG_BUILTIN_DTB) := $(addsuffix /, $(subdir-y))
diff --git a/arch/riscv/boot/dts/spacemit/Makefile b/arch/riscv/boot/dts/spacemit/Makefile
new file mode 100644
index 000000000000..2be95dbca797
--- /dev/null
+++ b/arch/riscv/boot/dts/spacemit/Makefile
@@ -0,0 +1,5 @@
+# SPDX-License-Identifier: GPL-2.0
+
+dtb-$(CONFIG_SOC_SPACEMIT_K1X) += k1-x_deb1.dtb
+
+obj-$(CONFIG_BUILTIN_DTB) += $(addsuffix .o, $(dtb-y))

File diff suppressed because it is too large Load Diff

View File

@@ -1,32 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Patrick Yavitz <pyavitz@armbian.com>
Date: Fri, 21 Jun 2024 11:54:06 -0400
Subject: add spacemit patch set
source: https://gitee.com/bianbu-linux/linux-6.1
Signed-off-by: Patrick Yavitz <pyavitz@armbian.com>
---
drivers/ata/libata-pmp.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/drivers/ata/libata-pmp.c b/drivers/ata/libata-pmp.c
index 111111111111..222222222222 100644
--- a/drivers/ata/libata-pmp.c
+++ b/drivers/ata/libata-pmp.c
@@ -446,10 +446,11 @@ static void sata_pmp_quirks(struct ata_port *ap)
* otherwise. Don't try hard to recover it.
*/
ap->pmp_link[ap->nr_pmp_links - 1].flags |= ATA_LFLAG_NO_RETRY;
- } else if (vendor == 0x197b && (devid == 0x2352 || devid == 0x0325)) {
+ } else if (vendor == 0x197b && (devid == 0x2352 || devid == 0x0325 || devid == 0x0585)) {
/*
* 0x2352: found in Thermaltake BlackX Duet, jmicron JMB350?
* 0x0325: jmicron JMB394.
+ * 0x0325: jmicron JMB585.
*/
ata_for_each_link(link, ap, EDGE) {
/* SRST breaks detection and disks get misclassified
--
Armbian

View File

@@ -1,28 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Patrick Yavitz <pyavitz@armbian.com>
Date: Fri, 21 Jun 2024 11:54:06 -0400
Subject: add spacemit patch set
source: https://gitee.com/bianbu-linux/linux-6.1
Signed-off-by: Patrick Yavitz <pyavitz@armbian.com>
---
drivers/base/firmware_loader/main.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/base/firmware_loader/main.c b/drivers/base/firmware_loader/main.c
index 111111111111..222222222222 100644
--- a/drivers/base/firmware_loader/main.c
+++ b/drivers/base/firmware_loader/main.c
@@ -1156,7 +1156,7 @@ request_firmware_nowait(
fw_work->device = device;
fw_work->context = context;
fw_work->cont = cont;
- fw_work->opt_flags = FW_OPT_NOWAIT |
+ fw_work->opt_flags = FW_OPT_NOWAIT | FW_OPT_NO_WARN |
(uevent ? FW_OPT_UEVENT : FW_OPT_USERHELPER);
if (!uevent && fw_cache_is_setup(device, name)) {
--
Armbian

File diff suppressed because it is too large Load Diff

View File

@@ -1,938 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Patrick Yavitz <pyavitz@armbian.com>
Date: Fri, 21 Jun 2024 11:54:06 -0400
Subject: add spacemit patch set
source: https://gitee.com/bianbu-linux/linux-6.1
Signed-off-by: Patrick Yavitz <pyavitz@armbian.com>
---
drivers/clocksource/Kconfig | 7 +
drivers/clocksource/Makefile | 1 +
drivers/clocksource/dw_apb_timer.c | 14 +-
drivers/clocksource/timer-k1x.c | 703 ++++++++++
4 files changed, 723 insertions(+), 2 deletions(-)
diff --git a/drivers/clocksource/Kconfig b/drivers/clocksource/Kconfig
index 111111111111..222222222222 100644
--- a/drivers/clocksource/Kconfig
+++ b/drivers/clocksource/Kconfig
@@ -134,6 +134,13 @@ config RDA_TIMER
help
Enables the support for the RDA Micro timer driver.
+config SPACEMIT_K1X_TIMER
+ bool "Spacemit k1x timer driver" if COMPILE_TEST
+ select CLKSRC_MMIO
+ select TIMER_OF
+ help
+ Enables the support for the spacemit k1x timer driver.
+
config SUN4I_TIMER
bool "Sun4i timer driver" if COMPILE_TEST
depends on HAS_IOMEM
diff --git a/drivers/clocksource/Makefile b/drivers/clocksource/Makefile
index 111111111111..222222222222 100644
--- a/drivers/clocksource/Makefile
+++ b/drivers/clocksource/Makefile
@@ -59,6 +59,7 @@ obj-$(CONFIG_MILBEAUT_TIMER) += timer-milbeaut.o
obj-$(CONFIG_SPRD_TIMER) += timer-sprd.o
obj-$(CONFIG_NPCM7XX_TIMER) += timer-npcm7xx.o
obj-$(CONFIG_RDA_TIMER) += timer-rda.o
+obj-$(CONFIG_SPACEMIT_K1X_TIMER) += timer-k1x.o
obj-$(CONFIG_ARC_TIMERS) += arc_timer.o
obj-$(CONFIG_ARM_ARCH_TIMER) += arm_arch_timer.o
diff --git a/drivers/clocksource/dw_apb_timer.c b/drivers/clocksource/dw_apb_timer.c
index 111111111111..222222222222 100644
--- a/drivers/clocksource/dw_apb_timer.c
+++ b/drivers/clocksource/dw_apb_timer.c
@@ -34,6 +34,8 @@
#define APBTMR_CONTROL_MODE_PERIODIC (1 << 1)
#define APBTMR_CONTROL_INT (1 << 2)
+static raw_spinlock_t dw_apb_timer_lock;
+
static inline struct dw_apb_clock_event_device *
ced_to_dw_apb_ced(struct clock_event_device *evt)
{
@@ -102,8 +104,10 @@ static irqreturn_t dw_apb_clockevent_irq(int irq, void *data)
return IRQ_NONE;
}
+ raw_spin_lock(&dw_ced->timer_lock);
if (dw_ced->eoi)
dw_ced->eoi(&dw_ced->timer);
+ raw_spin_unlock(&dw_ced->timer_lock);
evt->event_handler(evt);
return IRQ_HANDLED;
@@ -207,15 +211,20 @@ static int apbt_next_event(unsigned long delta,
u32 ctrl;
struct dw_apb_clock_event_device *dw_ced = ced_to_dw_apb_ced(evt);
+ raw_spin_lock(&dw_ced->timer_lock);
+
/* Disable timer */
ctrl = apbt_readl_relaxed(&dw_ced->timer, APBTMR_N_CONTROL);
ctrl &= ~APBTMR_CONTROL_ENABLE;
apbt_writel_relaxed(&dw_ced->timer, ctrl, APBTMR_N_CONTROL);
+
/* write new count */
apbt_writel_relaxed(&dw_ced->timer, delta, APBTMR_N_LOAD_COUNT);
ctrl |= APBTMR_CONTROL_ENABLE;
apbt_writel_relaxed(&dw_ced->timer, ctrl, APBTMR_N_CONTROL);
+ raw_spin_unlock(&dw_ced->timer_lock);
+
return 0;
}
@@ -248,6 +257,8 @@ dw_apb_clockevent_init(int cpu, const char *name, unsigned rating,
if (!dw_ced)
return NULL;
+ raw_spin_lock_init(&dw_ced->timer_lock);
+
dw_ced->timer.base = base;
dw_ced->timer.irq = irq;
dw_ced->timer.freq = freq;
@@ -272,8 +283,7 @@ dw_apb_clockevent_init(int cpu, const char *name, unsigned rating,
dw_ced->ced.name = name;
dw_ced->eoi = apbt_eoi;
- err = request_irq(irq, dw_apb_clockevent_irq,
- IRQF_TIMER | IRQF_IRQPOLL | IRQF_NOBALANCING,
+ err = request_irq(irq, dw_apb_clockevent_irq, IRQF_ONESHOT,
dw_ced->ced.name, &dw_ced->ced);
if (err) {
pr_err("failed to request timer irq\n");
diff --git a/drivers/clocksource/timer-k1x.c b/drivers/clocksource/timer-k1x.c
new file mode 100644
index 000000000000..111111111111
--- /dev/null
+++ b/drivers/clocksource/timer-k1x.c
@@ -0,0 +1,703 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * spacemit-k1x timer driver
+ *
+ * Copyright (C) 2023 Spacemit
+ */
+
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/interrupt.h>
+#include <linux/clockchips.h>
+
+#include <linux/io.h>
+#include <linux/irq.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/of_irq.h>
+#include <linux/delay.h>
+#include <linux/slab.h>
+#include <linux/cpu.h>
+#include <linux/clockchips.h>
+#include <linux/sched_clock.h>
+#include <linux/stat.h>
+#include <linux/clk.h>
+#include <linux/reset.h>
+
+#define TMR_CCR (0x000c)
+#define TMR_TN_MM(n, m) (0x0010 + ((n) << 4) + ((m) << 2))
+#define TMR_CR(n) (0x0090 + ((n) << 2))
+#define TMR_SR(n) (0x0080 + ((n) << 2))
+#define TMR_IER(n) (0x0060 + ((n) << 2))
+#define TMR_PLVR(n) (0x0040 + ((n) << 2))
+#define TMR_PLCR(n) (0x0050 + ((n) << 2))
+#define TMR_WMER (0x0068)
+#define TMR_WMR (0x006c)
+#define TMR_WVR (0x00cc)
+#define TMR_WSR (0x00c0)
+#define TMR_ICR(n) (0x0070 + ((n) << 2))
+#define TMR_WICR (0x00c4)
+#define TMR_CER (0x0000)
+#define TMR_CMR (0x0004)
+#define TMR_WCR (0x00c8)
+#define TMR_WFAR (0x00b0)
+#define TMR_WSAR (0x00b4)
+#define TMR_CRSR (0x0008)
+
+#define TMR_CCR_CS_0(x) (((x) & 0x3) << 0)
+#define TMR_CCR_CS_1(x) (((x) & 0x3) << 2)
+#define TMR_CCR_CS_2(x) (((x) & 0x3) << 5)
+
+#define MAX_EVT_NUM 5
+
+#define MAX_DELTA (0xfffffffe)
+#define MIN_DELTA (5)
+
+#define SPACEMIT_MAX_COUNTER 3
+#define SPACEMIT_MAX_TIMER 3
+
+#define TMR_CER_COUNTER(cid) (1 << (cid))
+#define SPACEMIT_ALL_COUNTERS ((1 << SPACEMIT_MAX_COUNTER) - 1)
+
+#define SPACEMIT_TIMER_CLOCK_32KHZ 32768
+
+#define SPACEMIT_TIMER_COUNTER_CLKSRC (1 << 0)
+#define SPACEMIT_TIMER_COUNTER_CLKEVT (1 << 1)
+#define SPACEMIT_TIMER_COUNTER_DELAY (1 << 2)
+
+#define SPACEMIT_TIMER_ALL_CPU (0xFFFFFFFF)
+
+struct spacemit_timer;
+
+struct spacemit_timer_evt {
+ struct clock_event_device ced;
+ struct irqaction irqa;
+ unsigned int freq;
+ unsigned int irq;
+ unsigned int cid;
+ unsigned int tid;
+ int cpu;
+ bool timer_enabled;
+ /* 0: timer set; 1: timer timeout(irq comes) */
+ int timer_status;
+ unsigned int timeout;
+ struct spacemit_timer *timer;
+};
+
+struct spacemit_timer {
+ unsigned int id;
+ void __iomem *base;
+ struct spacemit_timer_evt evt[SPACEMIT_MAX_COUNTER];
+ unsigned int flag;
+ int loop_delay_fastclk;
+ unsigned int fc_freq;
+ unsigned int freq;
+ struct clk *clk;
+ /* lock to protect hw operation. */
+ spinlock_t tm_lock;
+};
+
+struct timer_werror_info {
+ u32 reg;
+ u32 target;
+ u32 val;
+ u32 mask;
+};
+
+/* record the last x write failures */
+#define TIMER_ERR_NUM 10
+static struct timer_werror_info werr_info[TIMER_ERR_NUM];
+static int werr_index;
+
+static struct spacemit_timer *spacemit_timers[SPACEMIT_MAX_TIMER];
+static int timer_counter_switch_clock(struct spacemit_timer *tm, unsigned int freq);
+
+void timer_dump_hwinfo(int tid)
+{
+ struct spacemit_timer_evt *t_evt = &spacemit_timers[tid]->evt[0];
+ void __iomem *base = spacemit_timers[tid]->base;
+ unsigned int sr, cid, cer, cmr, ccr, mr, ier, cr;
+
+ cid = t_evt->cid;
+
+ cer = __raw_readl(base + TMR_CER);
+ cmr = __raw_readl(base + TMR_CMR);
+ ccr = __raw_readl(base + TMR_CCR);
+ mr = __raw_readl(base + TMR_TN_MM(cid, 0));
+ ier = __raw_readl(base + TMR_IER(cid));
+ sr = __raw_readl(base + TMR_SR(cid));
+ cr = __raw_readl(base + TMR_CR(cid));
+
+ pr_err("timer enable: %d. timeout: %d cycles. next event: %lld\n", !t_evt->timer_status, t_evt->timeout, t_evt->ced.next_event);
+
+ pr_err("cer/cmr/ccr/mr/ier/sr/cr: (0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x)\n", cer, cmr, ccr, mr, ier, sr, cr);
+
+ return;
+}
+
+static void timer_write_error(u32 reg, u32 target, u32 val, u32 mask)
+{
+ werr_info[werr_index].reg = reg;
+ werr_info[werr_index].target = target;
+ werr_info[werr_index].val = val;
+ werr_info[werr_index].mask = mask;
+ werr_index = (werr_index+1) % TIMER_ERR_NUM;
+
+ pr_err("timer write fail: register = 0x%x: (0x%x, 0x%x, 0x%x)\n", reg, target, val, mask);
+}
+
+static void timer_write_check(struct spacemit_timer *tm, u32 reg, u32 val, u32 mask, bool clr, bool clk_switch)
+{
+ int loop = 3, retry = 100;
+ u32 t_read, t_check = clr ? !val : val;
+
+reg_re_write:
+ __raw_writel(val, tm->base + reg);
+
+ if (clk_switch)
+ timer_counter_switch_clock(tm, tm->fc_freq);
+
+ t_read = __raw_readl(tm->base + reg);
+
+ while (((t_read & mask) != (t_check & mask)) && loop) {
+ /* avoid trying frequently to worsen bus contention */
+ udelay(30);
+ t_read = __raw_readl(tm->base + reg);
+ loop--;
+
+ if (!loop) {
+ timer_write_error(reg, t_check, t_read, mask);
+ loop = 3;
+ if (--retry)
+ goto reg_re_write;
+ else
+ return;
+ }
+ }
+}
+
+static int timer_counter_switch_clock(struct spacemit_timer *tm, unsigned int freq)
+{
+ u32 ccr, val, mask, tid;
+
+ tid = tm->id;
+
+ ccr = __raw_readl(tm->base + TMR_CCR);
+
+ switch (tid) {
+ case 0:
+ mask = TMR_CCR_CS_0(3);
+ break;
+ case 1:
+ mask = TMR_CCR_CS_1(3);
+ break;
+ case 2:
+ mask = TMR_CCR_CS_2(3);
+ break;
+ default:
+ pr_err("wrong timer id: 0x%x\n", tid);
+ return -EINVAL;
+ }
+
+ ccr &= ~mask;
+
+ if (freq == tm->fc_freq)
+ val = 0;
+ else if (freq == SPACEMIT_TIMER_CLOCK_32KHZ)
+ val = 1;
+ else {
+ pr_err("Timer %d: invalid clock rate %d\n", tid, freq);
+ return -EINVAL;
+ }
+
+ switch (tid) {
+ case 0:
+ ccr |= TMR_CCR_CS_0(val);
+ break;
+ case 1:
+ ccr |= TMR_CCR_CS_1(val);
+ break;
+ case 2:
+ ccr |= TMR_CCR_CS_2(val);
+ break;
+ }
+
+ timer_write_check(tm, TMR_CCR, ccr, mask, false, false);
+
+ return 0;
+}
+
+static void timer_counter_disable(struct spacemit_timer_evt *evt)
+{
+ struct spacemit_timer *tm = evt->timer;
+ u32 cer;
+ bool clk_switch = false;
+
+ if (evt->freq != tm->fc_freq)
+ clk_switch = true;
+ /*
+ * Stop the counter will need multiple timer clock to take effect.
+ * Some operations can only be done when counter is disabled. So
+ * add delay here.
+ */
+ /* Step1: disable counter */
+ cer = __raw_readl(tm->base + TMR_CER);
+ timer_write_check(tm, TMR_CER, (cer & ~(1 << evt->cid)), (1 << evt->cid), false, clk_switch);
+
+ /* remove unnecesary write, check explicitly: 2 cycles (32k) */
+
+ evt->timer_status = 1;
+}
+
+static void timer_counter_enable(struct spacemit_timer_evt *evt)
+{
+ struct spacemit_timer *tm = evt->timer;
+ u32 cer;
+
+ /* Switch to original clock */
+ if (evt->freq != tm->fc_freq)
+ timer_counter_switch_clock(tm, evt->freq);
+
+ /* Enable timer */
+ cer = __raw_readl(tm->base + TMR_CER);
+
+ timer_write_check(tm, TMR_CER, (cer | (1 << evt->cid)), (1 << evt->cid), false, false);
+
+ evt->timer_status = 0;
+}
+
+static irqreturn_t timer_interrupt(int irq, void *dev_id)
+{
+ struct clock_event_device *c = dev_id;
+ struct spacemit_timer_evt *evt;
+ unsigned int cnt;
+ unsigned long flags;
+ void __iomem *base;
+
+ evt = container_of(c, struct spacemit_timer_evt, ced);
+ cnt = evt->cid;
+ base = evt->timer->base;
+
+ spin_lock_irqsave(&(evt->timer->tm_lock), flags);
+ /* We only use match #0 for the counter. */
+ if (__raw_readl(base + TMR_SR(cnt)) & 0x1) {
+ timer_counter_disable(evt);
+
+ /* Disable the interrupt. */
+ timer_write_check(evt->timer, TMR_IER(cnt), 0, 0x7, false, false);
+ /* Clear interrupt status */
+ timer_write_check(evt->timer, TMR_ICR(cnt), 0x1, 0x7, true, false);
+
+ spin_unlock_irqrestore(&(evt->timer->tm_lock), flags);
+
+ c->event_handler(c);
+
+ return IRQ_HANDLED;
+ }
+
+ spin_unlock_irqrestore(&(evt->timer->tm_lock), flags);
+ return IRQ_NONE;
+}
+
+static int timer_shutdown(struct clock_event_device *dev)
+{
+ struct spacemit_timer_evt *evt;
+ unsigned long flags;
+
+ evt = container_of(dev, struct spacemit_timer_evt, ced);
+
+ spin_lock_irqsave(&(evt->timer->tm_lock), flags);
+
+ evt->timer_enabled = !evt->timer_status;
+
+ /* disable counter */
+ timer_counter_disable(evt);
+
+ spin_unlock_irqrestore(&(evt->timer->tm_lock), flags);
+
+ return 0;
+}
+
+static int timer_resume(struct clock_event_device *dev)
+{
+ struct spacemit_timer_evt *evt;
+ unsigned long flags;
+
+ evt = container_of(dev, struct spacemit_timer_evt, ced);
+
+ spin_lock_irqsave(&(evt->timer->tm_lock), flags);
+
+ /* check whether need to enable timer */
+ if (evt->timer_enabled)
+ timer_counter_enable(evt);
+
+ spin_unlock_irqrestore(&(evt->timer->tm_lock), flags);
+
+ return 0;
+}
+
+static int timer_set_next_event(unsigned long delta,
+ struct clock_event_device *dev)
+{
+ struct spacemit_timer_evt *evt;
+ unsigned int cid;
+ unsigned long flags;
+ u32 cer;
+ void __iomem *base;
+
+ evt = container_of(dev, struct spacemit_timer_evt, ced);
+ cid = evt->cid;
+ base = evt->timer->base;
+
+ spin_lock_irqsave(&(evt->timer->tm_lock), flags);
+
+ cer = __raw_readl(base + TMR_CER);
+
+ /* If the timer counter is enabled, first disable it. */
+ if (cer & (1 << cid))
+ timer_counter_disable(evt);
+
+ /* Setup new counter value */
+ timer_write_check(evt->timer, TMR_TN_MM(cid, 0), (delta - 1), (u32)(-1), false, false);
+
+ /* enable the matching interrupt */
+ timer_write_check(evt->timer, TMR_IER(cid), 0x1, 0x1, false, false);
+
+ timer_counter_enable(evt);
+
+ evt->timeout = delta - 1;
+
+ spin_unlock_irqrestore(&(evt->timer->tm_lock), flags);
+ return 0;
+}
+
+int __init spacemit_timer_init(struct device_node *np, int tid, void __iomem *base,
+ unsigned int flag, unsigned int fc_freq,
+ unsigned int apb_freq, unsigned int freq)
+{
+ struct spacemit_timer *tm = spacemit_timers[tid];
+ struct clk *clk;
+ struct reset_control *resets;
+ u32 tmp, delay;
+
+ if (tm)
+ return -EINVAL;
+
+ tm = kzalloc(sizeof(*tm), GFP_KERNEL);
+ if (!tm)
+ return -ENOMEM;
+
+ clk = of_clk_get(np, 0);
+ if (!clk) {
+ pr_err("%s: get clk failed! %s\n", __func__, np->name);
+ goto out;
+ }
+
+ if (IS_ERR(clk)) {
+ pr_err("Timer %d: fail to get clock!\n", tid);
+ goto out;
+ }
+
+ if (clk_prepare_enable(clk)) {
+ pr_err("Timer %d: fail to enable clock!\n", tid);
+ goto out;
+ }
+
+ if (clk_set_rate(clk, fc_freq)) {
+ pr_err("Timer %d: fail to set clock rate to %uHz!\n", tid, fc_freq);
+ goto out;
+ }
+
+ resets = of_reset_control_get(np, 0);
+ if(IS_ERR(resets)) {
+ clk_disable_unprepare(clk);
+ return PTR_ERR(resets);
+ }
+ reset_control_deassert(resets);
+ /*
+ * The calculation formula for the loop cycle is:
+ *
+ * (1) need wait for 2 timer's clock cycle:
+ * 1 2
+ * ------- x 2 = -------
+ * fc_freq fc_freq
+ *
+ * (2) convert to apb clock cycle:
+ * 2 1 apb_freq * 2
+ * ------- / -------- = ----------------
+ * fc_freq apb_freq fc_freq
+ *
+ * (3) every apb register's accessing will take 8 apb clock cycle,
+ * also consider add extral one more time for safe way;
+ * so finally need loop times for the apb register accessing:
+ *
+ * (apb_freq * 2)
+ * ------------------ / 8 + 1
+ * fc_freq
+ */
+ delay = ((apb_freq * 2) / fc_freq / 8) + 1;
+ pr_err("Timer %d: loop_delay_fastclk is %d\n", tid, delay);
+
+ tm->id = tid;
+ tm->base = base;
+ tm->flag = flag;
+ tm->loop_delay_fastclk = delay;
+ tm->fc_freq = fc_freq;
+ tm->freq = freq;
+ spin_lock_init(&(tm->tm_lock));
+
+ spacemit_timers[tid] = tm;
+
+ /* We will disable all counters. Switch to fastclk first. */
+ timer_counter_switch_clock(tm, fc_freq);
+
+ /* disalbe all counters */
+ tmp = __raw_readl(base + TMR_CER) & ~SPACEMIT_ALL_COUNTERS;
+ __raw_writel(tmp, base + TMR_CER);
+
+ /* disable matching interrupt */
+ __raw_writel(0x00, base + TMR_IER(0));
+ __raw_writel(0x00, base + TMR_IER(1));
+ __raw_writel(0x00, base + TMR_IER(2));
+
+ while (delay--) {
+ /* Clear pending interrupt status */
+ __raw_writel(0x1, base + TMR_ICR(0));
+ __raw_writel(0x1, base + TMR_ICR(1));
+ __raw_writel(0x1, base + TMR_ICR(2));
+ __raw_writel(tmp, base + TMR_CER);
+ }
+
+ return 0;
+out:
+ kfree(tm);
+ return -EINVAL;
+}
+
+static int __init spacemit_timer_hw_init(struct spacemit_timer_evt *evt)
+{
+ struct spacemit_timer *tm = evt->timer;
+ unsigned int tmp, delay, freq, cid, ratio;
+ int ret;
+
+ cid = evt->cid;
+ freq = evt->freq;
+
+ ret = timer_counter_switch_clock(tm, freq);
+ if (ret)
+ return ret;
+
+ ratio = tm->fc_freq / freq;
+ delay = tm->loop_delay_fastclk * ratio;
+
+ /* set timer to free-running mode */
+ tmp = __raw_readl(tm->base + TMR_CMR) | TMR_CER_COUNTER(cid);
+ __raw_writel(tmp, tm->base + TMR_CMR);
+
+ /* free-running */
+ __raw_writel(0x0, tm->base + TMR_PLCR(cid));
+ /* clear status */
+ __raw_writel(0x7, tm->base + TMR_ICR(cid));
+
+ /* enable counter */
+ tmp = __raw_readl(tm->base + TMR_CER) | TMR_CER_COUNTER(cid);
+ __raw_writel(tmp, tm->base + TMR_CER);
+
+ while (delay--)
+ __raw_writel(tmp, tm->base + TMR_CER);
+
+ return 0;
+}
+
+
+int __init spacemit_timer_setup(struct spacemit_timer_evt *evt)
+{
+ int broadcast = 0;
+ int ret;
+
+ if (evt->cpu == SPACEMIT_TIMER_ALL_CPU)
+ broadcast = 1;
+ else if (evt->cpu >= num_possible_cpus())
+ return -EINVAL;
+
+ evt->ced.name = "timer-spacemit";
+ evt->ced.features = CLOCK_EVT_FEAT_ONESHOT;
+ evt->ced.rating = 200;
+ evt->ced.set_next_event = timer_set_next_event;
+ evt->ced.set_state_shutdown = timer_shutdown;
+ evt->ced.tick_resume = timer_resume;
+ evt->ced.irq = evt->irq;
+
+ evt->irqa.flags = IRQF_TIMER | IRQF_IRQPOLL;
+ evt->irqa.handler = timer_interrupt;
+ evt->irqa.dev_id = &(evt->ced);
+
+ ret = spacemit_timer_hw_init(evt);
+ if (ret)
+ return ret;
+
+ if (broadcast) {
+ evt->irqa.name = "broadcast-timer";
+ /* evt->ced.features |= CLOCK_EVT_FEAT_DYNIRQ; */
+ evt->ced.cpumask = cpu_possible_mask;
+ ret = request_irq(evt->ced.irq, timer_interrupt, IRQF_TIMER | IRQF_IRQPOLL | IRQF_ONESHOT, "broadcast-timer", evt->irqa.dev_id);
+ if (ret < 0)
+ return ret;
+ clockevents_config_and_register(&evt->ced,
+ evt->freq, MIN_DELTA, MAX_DELTA);
+ } else {
+ evt->irqa.name = "local-timer";
+ evt->ced.cpumask = cpumask_of(evt->cpu);
+ evt->irqa.flags |= IRQF_PERCPU;
+ ret = request_irq(evt->ced.irq, timer_interrupt, IRQF_TIMER | IRQF_IRQPOLL, "local-timer", evt->irqa.dev_id);
+ if (ret < 0)
+ return ret;
+ /* Enable clock event device for boot CPU. */
+ if (evt->cpu == smp_processor_id()) {
+ clockevents_config_and_register(&evt->ced,
+ evt->freq, MIN_DELTA,
+ MAX_DELTA);
+ /* Only online CPU can be set affinity. */
+ irq_set_affinity_hint(evt->ced.irq, cpumask_of(evt->cpu));
+ } else {
+ /* disable none boot CPU's irq at first */
+ disable_irq(evt->ced.irq);
+ }
+ }
+
+ return 0;
+}
+
+#ifdef CONFIG_OF
+
+const struct of_device_id spacemit_counter_of_id[] = {
+ {
+ .compatible = "spacemit,timer-match",
+ },
+ { },
+};
+
+static int __init spacemit_of_counter_init(struct device_node *np, int tid)
+{
+ int irq, ret;
+ unsigned int cid, cpu;
+ struct spacemit_timer_evt *evt;
+
+ if (!np)
+ return -EINVAL;
+
+ ret = of_property_read_u32(np, "spacemit,timer-counter-id", &cid);
+ if (ret || cid >= SPACEMIT_MAX_TIMER) {
+ pr_err("Timer %d: fail to get counter id 0x%x\n", tid, cid);
+ return ret;
+ }
+
+ if (of_property_read_bool(np, "spacemit,timer-broadcast"))
+ cpu = SPACEMIT_TIMER_ALL_CPU;
+ else {
+ ret = of_property_read_u32(np,
+ "spacemit,timer-counter-cpu",
+ &cpu);
+ if (ret) {
+ pr_err("Timer %d:%d: fail to get cpu\n",
+ tid, cid);
+ return ret;
+ }
+ }
+ irq = irq_of_parse_and_map(np, 0);
+ evt = &spacemit_timers[tid]->evt[cid];
+ evt->timer = spacemit_timers[tid];
+ evt->freq = spacemit_timers[tid]->freq;
+ evt->irq = irq;
+ evt->cpu = cpu;
+ evt->cid = cid;
+ evt->tid = tid;
+ ret = spacemit_timer_setup(evt);
+ if (ret) {
+ pr_err("Timer %d:%d: fail to create clkevt\n",
+ tid, cid);
+ return ret;
+ }
+
+ return 0;
+}
+
+static int __init spacemit_of_timer_init(struct device_node *np)
+{
+ unsigned int flag, tid, fc_freq, apb_freq, freq;
+ void __iomem *base;
+ struct device_node *child_np;
+ const struct of_device_id *match;
+ int ret = 0;
+
+ /* timer initialization */
+ base = of_iomap(np, 0);
+ if (!base) {
+ pr_err("Timer: fail to map register space\n");
+ ret = -EINVAL;
+ goto out;
+ }
+
+ flag = 0;
+
+ /* get timer id */
+ ret = of_property_read_u32(np, "spacemit,timer-id", &tid);
+ if (ret || tid >= SPACEMIT_MAX_TIMER) {
+ pr_err("Timer %d: fail to get timer-id with err %d\n", tid, ret);
+ goto out;
+ }
+
+ /* timer's fast clock and apb frequency */
+ ret = of_property_read_u32(np, "spacemit,timer-fastclk-frequency", &fc_freq);
+ if (ret) {
+ pr_err("Timer %d: fail to get fastclk-frequency with err %d\n",
+ tid, ret);
+ goto out;
+ }
+
+ ret = of_property_read_u32(np, "spacemit,timer-apb-frequency", &apb_freq);
+ if (ret) {
+ pr_err("Timer %d: fail to get apb-frequency with err %d\n",
+ tid, ret);
+ goto out;
+ }
+
+ ret = of_property_read_u32(np, "spacemit,timer-frequency", &freq);
+ if (ret) {
+ pr_err("Timer %d: fail to get timer frequency with err %d\n",
+ tid, ret);
+ goto out;
+ }
+
+ /*
+ * Need use loop for more safe register's accessing,
+ * so at here dynamically calculate the loop time.
+ */
+ if (!fc_freq || !apb_freq) {
+ pr_err("mmp timer's fast clock or apb freq are incorrect!\n");
+ ret = -EINVAL;
+ goto out;
+ }
+
+ ret = spacemit_timer_init(np, tid, base, flag, fc_freq, apb_freq, freq);
+ if (ret)
+ goto out;
+
+ /* counter initialization */
+ for_each_child_of_node(np, child_np) {
+ match = of_match_node(spacemit_counter_of_id, child_np);
+ if (!of_device_is_available(child_np))
+ continue;
+ ret = spacemit_of_counter_init(child_np, tid);
+ if (ret)
+ goto out;
+ }
+ return 0;
+out:
+ if (ret)
+ pr_err("Failed to get timer from dtb with error:%d\n", ret);
+ return ret;
+}
+
+TIMER_OF_DECLARE(spacemit_timer, "spacemit,soc-timer", spacemit_of_timer_init);
+#endif
--
Armbian
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Patrick Yavitz <pyavitz@xxxxx.com>
Date: Sat, 22 Jun 2024 09:59:12 -0400
Subject: drivers: clocksource: timer-riscv.c: fixups
Signed-off-by: Patrick Yavitz <pyavitz@xxxxx.com>
---
drivers/clocksource/timer-riscv.c | 61 +++++++++-
1 file changed, 55 insertions(+), 6 deletions(-)
diff --git a/drivers/clocksource/timer-riscv.c b/drivers/clocksource/timer-riscv.c
index 111111111111..222222222222 100644
--- a/drivers/clocksource/timer-riscv.c
+++ b/drivers/clocksource/timer-riscv.c
@@ -33,8 +33,46 @@ static int riscv_clock_next_event(unsigned long delta,
struct clock_event_device *ce)
{
u64 next_tval = get_cycles64() + delta;
+ csr_set(CSR_IE, IE_TIE);
+
+ if (static_branch_likely(&riscv_sstc_available)) {
+#if defined(CONFIG_32BIT)
+ csr_write(CSR_STIMECMP, next_tval & 0xFFFFFFFF);
+ csr_write(CSR_STIMECMPH, next_tval >> 32);
+#else
+ csr_write(CSR_STIMECMP, next_tval);
+#endif
+ } else
+ sbi_set_timer(next_tval);
+
+ return 0;
+}
+
+static int riscv_set_state_shutdown(struct clock_event_device *ce)
+{
+ u64 next_tval = 0xffffffffffffffff;
+
+ csr_clear(CSR_IE, IE_TIE);
+
+ if (static_branch_likely(&riscv_sstc_available)) {
+#if defined(CONFIG_32BIT)
+ csr_write(CSR_STIMECMP, next_tval & 0xFFFFFFFF);
+ csr_write(CSR_STIMECMPH, next_tval >> 32);
+#else
+ csr_write(CSR_STIMECMP, next_tval);
+#endif
+ } else
+ sbi_set_timer(next_tval);
+
+ return 0;
+}
+
+static int riscv_set_state_oneshot(struct clock_event_device *ce)
+{
+ u64 next_tval = 0xffffffffffffffff;
csr_set(CSR_IE, IE_TIE);
+
if (static_branch_likely(&riscv_sstc_available)) {
#if defined(CONFIG_32BIT)
csr_write(CSR_STIMECMP, next_tval & 0xFFFFFFFF);
@@ -51,9 +89,12 @@ static int riscv_clock_next_event(unsigned long delta,
static unsigned int riscv_clock_event_irq;
static DEFINE_PER_CPU(struct clock_event_device, riscv_clock_event) = {
.name = "riscv_timer_clockevent",
- .features = CLOCK_EVT_FEAT_ONESHOT,
+ .features = CLOCK_EVT_FEAT_ONESHOT | CLOCK_EVT_FEAT_C3STOP,
.rating = 100,
.set_next_event = riscv_clock_next_event,
+ .set_state_shutdown = riscv_set_state_shutdown,
+ .set_state_oneshot_stopped = riscv_set_state_shutdown,
+ .set_state_oneshot = riscv_set_state_oneshot,
};
/*
@@ -158,6 +199,13 @@ static int __init riscv_timer_init_dt(struct device_node *n)
return -ENODEV;
}
+#ifdef CONFIG_SOC_SPACEMIT
+ if (riscv_isa_extension_available(NULL, SSTC)) {
+ pr_info("Timer interrupt in S-mode is available via sstc extension\n");
+ static_branch_enable(&riscv_sstc_available);
+ }
+#endif
+
pr_info("%s: Registering clocksource cpuid [%d] hartid [%lu]\n",
__func__, cpuid, hartid);
error = clocksource_register_hz(&riscv_clocksource, riscv_timebase);
@@ -177,11 +225,6 @@ static int __init riscv_timer_init_dt(struct device_node *n)
return error;
}
- if (riscv_isa_extension_available(NULL, SSTC)) {
- pr_info("Timer interrupt in S-mode is available via sstc extension\n");
- static_branch_enable(&riscv_sstc_available);
- }
-
error = cpuhp_setup_state(CPUHP_AP_RISCV_TIMER_STARTING,
"clockevents/riscv/timer:starting",
riscv_timer_starting_cpu, riscv_timer_dying_cpu);
@@ -189,6 +232,12 @@ static int __init riscv_timer_init_dt(struct device_node *n)
pr_err("cpu hp setup state failed for RISCV timer [%d]\n",
error);
+#ifndef CONFIG_SOC_SPACEMIT
+ if (riscv_isa_extension_available(NULL, SSTC)) {
+ pr_info("Timer interrupt in S-mode is available via sstc extension\n");
+ static_branch_enable(&riscv_sstc_available);
+ }
+#endif
return error;
}
--
Armbian

View File

@@ -1,314 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Patrick Yavitz <pyavitz@armbian.com>
Date: Fri, 21 Jun 2024 11:54:06 -0400
Subject: add spacemit patch set
source: https://gitee.com/bianbu-linux/linux-6.1
Signed-off-by: Patrick Yavitz <pyavitz@armbian.com>
---
drivers/cpufreq/Kconfig | 11 +-
drivers/cpufreq/Makefile | 1 +
drivers/cpufreq/cpufreq-dt-platdev.c | 4 +
drivers/cpufreq/spacemit-cpufreq.c | 215 ++++++++++
drivers/cpuidle/cpuidle-riscv-sbi.c | 4 +
5 files changed, 234 insertions(+), 1 deletion(-)
diff --git a/drivers/cpufreq/Kconfig b/drivers/cpufreq/Kconfig
index 111111111111..222222222222 100644
--- a/drivers/cpufreq/Kconfig
+++ b/drivers/cpufreq/Kconfig
@@ -231,7 +231,7 @@ if X86
source "drivers/cpufreq/Kconfig.x86"
endif
-if ARM || ARM64
+if ARM || ARM64 || RISCV
source "drivers/cpufreq/Kconfig.arm"
endif
@@ -321,5 +321,14 @@ config QORIQ_CPUFREQ
This adds the CPUFreq driver support for Freescale QorIQ SoCs
which are capable of changing the CPU's frequency dynamically.
+config SPACEMIT_K1X_CPUFREQ
+ tristate "CPU frequency scaling driver for Spacemit K1X"
+ depends on OF && COMMON_CLK
+ select CPUFREQ_DT
+ select CPUFREQ_DT_PLATDEV
+ help
+ This adds the CPUFreq driver support for Freescale QorIQ SoCs
+ which are capable of changing the CPU's frequency dynamically.
+
endif
endmenu
diff --git a/drivers/cpufreq/Makefile b/drivers/cpufreq/Makefile
index 111111111111..222222222222 100644
--- a/drivers/cpufreq/Makefile
+++ b/drivers/cpufreq/Makefile
@@ -114,3 +114,4 @@ obj-$(CONFIG_LOONGSON1_CPUFREQ) += loongson1-cpufreq.o
obj-$(CONFIG_SH_CPU_FREQ) += sh-cpufreq.o
obj-$(CONFIG_SPARC_US2E_CPUFREQ) += sparc-us2e-cpufreq.o
obj-$(CONFIG_SPARC_US3_CPUFREQ) += sparc-us3-cpufreq.o
+obj-$(CONFIG_SPACEMIT_K1X_CPUFREQ) += spacemit-cpufreq.o
diff --git a/drivers/cpufreq/cpufreq-dt-platdev.c b/drivers/cpufreq/cpufreq-dt-platdev.c
index 111111111111..222222222222 100644
--- a/drivers/cpufreq/cpufreq-dt-platdev.c
+++ b/drivers/cpufreq/cpufreq-dt-platdev.c
@@ -93,6 +93,8 @@ static const struct of_device_id allowlist[] __initconst = {
{ .compatible = "xlnx,zynq-7000", },
{ .compatible = "xlnx,zynqmp", },
+ { .compatible = "spacemit,k1-x", },
+
{ }
};
@@ -168,6 +170,8 @@ static const struct of_device_id blocklist[] __initconst = {
{ .compatible = "qcom,msm8974", },
{ .compatible = "qcom,msm8960", },
+ { .compatible = "spacemit,k1-x", },
+
{ }
};
diff --git a/drivers/cpufreq/spacemit-cpufreq.c b/drivers/cpufreq/spacemit-cpufreq.c
new file mode 100644
index 000000000000..111111111111
--- /dev/null
+++ b/drivers/cpufreq/spacemit-cpufreq.c
@@ -0,0 +1,215 @@
+// SPDX-License-Identifier: GPL-2.0-only
+
+#include <linux/cpufreq.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/cpumask.h>
+#include <linux/clk/clk-conf.h>
+#include <linux/pm_qos.h>
+#include <linux/notifier.h>
+#include <linux/regulator/consumer.h>
+#include <linux/mutex.h>
+#include "../opp/opp.h"
+
+struct per_device_qos {
+ struct regulator *regulator;
+ struct freq_qos_request qos;
+};
+
+static DEFINE_MUTEX(regulator_mutex);
+static struct notifier_block vol_constraints_notifier;
+static struct freq_constraints vol_constraints;
+static struct per_device_qos *vol_qos[CONFIG_NR_CPUS];
+
+#ifdef CONFIG_CPU_HOTPLUG_THERMAL
+struct thermal_cooling_device **ghotplug_cooling;
+extern struct thermal_cooling_device **
+of_hotplug_cooling_register(struct cpufreq_policy *policy);
+#endif
+
+static int spacemit_vol_qos_notifier_call(struct notifier_block *nb, unsigned long action, void *data)
+{
+ regulator_set_voltage(vol_qos[0]->regulator, action * 1000, action * 1000);
+
+ return 0;
+}
+
+static int spacemit_policy_notifier(struct notifier_block *nb,
+ unsigned long event, void *data)
+{
+ int cpu, err;
+ u64 rates;
+ static int cci_init;
+ struct clk *cci_clk;
+ struct device *cpu_dev;
+ struct cpufreq_policy *policy = data;
+ struct opp_table *opp_table;
+ const char *strings;
+
+ cpu = cpumask_first(policy->related_cpus);
+ cpu_dev = get_cpu_device(cpu);
+ opp_table = _find_opp_table(cpu_dev);
+
+ if (cci_init == 0) {
+ cci_clk = of_clk_get_by_name(opp_table->np, "cci");
+ of_property_read_u64_array(opp_table->np, "cci-hz", &rates, 1);
+ clk_set_rate(cci_clk, rates);
+ clk_put(cci_clk);
+ cci_init = 1;
+ }
+
+ vol_qos[cpu] = devm_kzalloc(cpu_dev, sizeof(struct per_device_qos), GFP_KERNEL);
+ if (!vol_qos[cpu])
+ return -ENOMEM;
+
+ err = of_property_read_string_array(cpu_dev->of_node, "vin-supply-names",
+ &strings, 1);
+ if (err >= 0) {
+ vol_qos[cpu]->regulator = devm_regulator_get(cpu_dev, strings);
+ if (IS_ERR(vol_qos[cpu]->regulator)) {
+ pr_err("regulator supply %s, get failed\n", strings);
+ return PTR_ERR(vol_qos[cpu]->regulator);
+ }
+
+ err = regulator_enable(vol_qos[cpu]->regulator);
+
+ } else {
+ /* using the same regulator */
+ vol_qos[cpu]->regulator = vol_qos[0]->regulator;
+ }
+
+ if (vol_qos[cpu]->regulator)
+ freq_qos_add_request(&vol_constraints, &vol_qos[cpu]->qos, FREQ_QOS_MIN,
+ regulator_get_voltage(vol_qos[cpu]->regulator) / 1000);
+
+#ifdef CONFIG_CPU_HOTPLUG_THERMAL
+ ghotplug_cooling = of_hotplug_cooling_register(policy);
+ if (!ghotplug_cooling) {
+ pr_err("register hotplug cpu cooling failed\n");
+ return -EINVAL;
+ }
+#endif
+ return 0;
+}
+
+static int spacemit_processor_notifier(struct notifier_block *nb,
+ unsigned long event, void *data)
+{
+ int cpu;
+ struct device *cpu_dev;
+ struct cpufreq_freqs *freqs = (struct cpufreq_freqs *)data;
+ struct cpufreq_policy *policy = ( struct cpufreq_policy *)freqs->policy;
+ struct opp_table *opp_table;
+ struct device_node *np;
+ struct clk *tcm_clk, *ace_clk;
+ u64 rates;
+ u32 microvol;
+
+ cpu = cpumask_first(policy->related_cpus);
+ cpu_dev = get_cpu_device(cpu);
+ opp_table = _find_opp_table(cpu_dev);
+
+ for_each_available_child_of_node(opp_table->np, np) {
+ of_property_read_u64_array(np, "opp-hz", &rates, 1);
+ if (rates == freqs->new * 1000) {
+ of_property_read_u32(np, "opp-microvolt", &microvol);
+ break;
+ }
+ }
+
+ /* get the tcm/ace clk handler */
+ tcm_clk = of_clk_get_by_name(opp_table->np, "tcm");
+ ace_clk = of_clk_get_by_name(opp_table->np, "ace");
+
+ if (event == CPUFREQ_PRECHANGE) {
+
+ mutex_lock(&regulator_mutex);
+
+ if (freqs->new > freqs->old) {
+ /* increase voltage first */
+ if (vol_qos[cpu]->regulator)
+ freq_qos_update_request(&vol_qos[cpu]->qos, microvol / 1000);
+ }
+
+ /**
+ * change the tcm/ace's frequency first.
+ * binary division is safe
+ */
+ if (!IS_ERR(ace_clk)) {
+ clk_set_rate(ace_clk, clk_get_rate(clk_get_parent(ace_clk)) / 2);
+ clk_put(ace_clk);
+ }
+
+ if (!IS_ERR(tcm_clk)) {
+ clk_set_rate(tcm_clk, clk_get_rate(clk_get_parent(tcm_clk)) / 2);
+ clk_put(tcm_clk);
+ }
+ }
+
+ if (event == CPUFREQ_POSTCHANGE) {
+
+ if (!IS_ERR(tcm_clk)) {
+ clk_get_rate(clk_get_parent(tcm_clk));
+ /* get the tcm-hz */
+ of_property_read_u64_array(np, "tcm-hz", &rates, 1);
+ /* then set rate */
+ clk_set_rate(tcm_clk, rates);
+ clk_put(tcm_clk);
+ }
+
+ if (!IS_ERR(ace_clk)) {
+ clk_get_rate(clk_get_parent(ace_clk));
+ /* get the ace-hz */
+ of_property_read_u64_array(np, "ace-hz", &rates, 1);
+ /* then set rate */
+ clk_set_rate(ace_clk, rates);
+ clk_put(ace_clk);
+ }
+
+ if (freqs->new < freqs->old) {
+ /* decrease the voltage last */
+ if (vol_qos[cpu]->regulator)
+ freq_qos_update_request(&vol_qos[cpu]->qos, microvol / 1000);
+ }
+
+ mutex_unlock(&regulator_mutex);
+ }
+
+ dev_pm_opp_put_opp_table(opp_table);
+
+ return 0;
+}
+
+static struct notifier_block spacemit_processor_notifier_block = {
+ .notifier_call = spacemit_processor_notifier,
+};
+
+static struct notifier_block spacemit_policy_notifier_block = {
+ .notifier_call = spacemit_policy_notifier,
+};
+
+static int __init spacemit_processor_driver_init(void)
+{
+ int ret;
+
+ ret = cpufreq_register_notifier(&spacemit_processor_notifier_block, CPUFREQ_TRANSITION_NOTIFIER);
+ if (ret) {
+ pr_err("register cpufreq notifier failed\n");
+ return -EINVAL;
+ }
+
+ ret = cpufreq_register_notifier(&spacemit_policy_notifier_block, CPUFREQ_POLICY_NOTIFIER);
+ if (ret) {
+ pr_err("register cpufreq notifier failed\n");
+ return -EINVAL;
+ }
+
+ vol_constraints_notifier.notifier_call = spacemit_vol_qos_notifier_call;
+ freq_constraints_init(&vol_constraints);
+ freq_qos_add_notifier(&vol_constraints, FREQ_QOS_MIN, &vol_constraints_notifier);
+
+ return 0;
+}
+
+arch_initcall(spacemit_processor_driver_init);
diff --git a/drivers/cpuidle/cpuidle-riscv-sbi.c b/drivers/cpuidle/cpuidle-riscv-sbi.c
index 111111111111..222222222222 100644
--- a/drivers/cpuidle/cpuidle-riscv-sbi.c
+++ b/drivers/cpuidle/cpuidle-riscv-sbi.c
@@ -79,6 +79,10 @@ static int sbi_suspend_finisher(unsigned long suspend_type,
{
struct sbiret ret;
+#if defined(CONFIG_SOC_SPACEMIT_K1PRO) || defined(CONFIG_SOC_SPACEMIT_K1X)
+ /* flush the local cache */
+ sbi_flush_local_dcache_all();
+#endif
ret = sbi_ecall(SBI_EXT_HSM, SBI_EXT_HSM_HART_SUSPEND,
suspend_type, resume_addr, opaque, 0, 0, 0);
--
Armbian

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -1,411 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Patrick Yavitz <pyavitz@armbian.com>
Date: Fri, 21 Jun 2024 11:54:06 -0400
Subject: add spacemit patch set
source: https://gitee.com/bianbu-linux/linux-6.1
Signed-off-by: Patrick Yavitz <pyavitz@armbian.com>
---
drivers/extcon/Kconfig | 7 +
drivers/extcon/Makefile | 1 +
drivers/extcon/extcon-k1xci.c | 358 ++++++++++
3 files changed, 366 insertions(+)
diff --git a/drivers/extcon/Kconfig b/drivers/extcon/Kconfig
index 111111111111..222222222222 100644
--- a/drivers/extcon/Kconfig
+++ b/drivers/extcon/Kconfig
@@ -41,6 +41,13 @@ config EXTCON_FSA9480
I2C and enables USB data, stereo and mono audio, video, microphone
and UART data to use a common connector port.
+config EXTCON_USB_K1XCI
+ tristate "Spacemit K1-x USB extcon support"
+ depends on GPIOLIB || COMPILE_TEST
+ help
+ say Y here to enable spacemit k1-x usb wakeup irq based USB cable detection extcon support.
+ Used typically if wakeup irq is used for USB ID pin detection.
+
config EXTCON_GPIO
tristate "GPIO extcon support"
depends on GPIOLIB || COMPILE_TEST
diff --git a/drivers/extcon/Makefile b/drivers/extcon/Makefile
index 111111111111..222222222222 100644
--- a/drivers/extcon/Makefile
+++ b/drivers/extcon/Makefile
@@ -22,6 +22,7 @@ obj-$(CONFIG_EXTCON_PTN5150) += extcon-ptn5150.o
obj-$(CONFIG_EXTCON_QCOM_SPMI_MISC) += extcon-qcom-spmi-misc.o
obj-$(CONFIG_EXTCON_RT8973A) += extcon-rt8973a.o
obj-$(CONFIG_EXTCON_SM5502) += extcon-sm5502.o
+obj-$(CONFIG_EXTCON_USB_K1XCI) += extcon-k1xci.o
obj-$(CONFIG_EXTCON_USB_GPIO) += extcon-usb-gpio.o
obj-$(CONFIG_EXTCON_USBC_CROS_EC) += extcon-usbc-cros-ec.o
obj-$(CONFIG_EXTCON_USBC_TUSB320) += extcon-usbc-tusb320.o
diff --git a/drivers/extcon/extcon-k1xci.c b/drivers/extcon/extcon-k1xci.c
new file mode 100644
index 000000000000..111111111111
--- /dev/null
+++ b/drivers/extcon/extcon-k1xci.c
@@ -0,0 +1,358 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * extcon-k1xci.c - Driver for usb vbus/id detect
+ *
+ * Copyright (c) 2023, Spacemit Corporation.
+ */
+
+#include <linux/extcon.h>
+#include <linux/extcon-provider.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+#include <linux/workqueue.h>
+#include <linux/of.h>
+#include <linux/pm_qos.h>
+#include <linux/debugfs.h>
+#include <linux/uaccess.h>
+#include <linux/pm_runtime.h>
+
+#define USB_GPIO_DEBOUNCE_MS 200 /* ms */
+
+/* PMU_SD_ROT_WAKE_CLR */
+#define USB_VBUS_WK_MASK BIT(10)
+#define USB_ID_WK_MASK BIT(11)
+
+#define USB_VBUS_WK_CLR BIT(18)
+#define USB_ID_WK_CLR BIT(19)
+
+#define USB_VBUS_WK_STATUS BIT(26)
+#define USB_ID_WK_STATUS BIT(27)
+
+/* PMUA_USB_PHY_READ */
+#define USB_ID BIT(1)
+#define USB_VBUS BIT(2)
+
+struct mv_usb_extcon_info {
+ struct device *dev;
+ struct extcon_dev *edev;
+
+ void __iomem *pmuap_reg;
+ void __iomem *pin_state_reg;
+
+ int irq;
+
+ unsigned long debounce_jiffies;
+ struct delayed_work wq_detcable;
+
+ struct freq_qos_request qos_idle;
+ u32 lpm_qos;
+
+ /* debugfs interface for user-space */
+ struct dentry *dbgfs;
+ char dbgfs_name[32];
+ uint32_t dbgfs_qos_mode;
+};
+
+static const unsigned int usb_extcon_cable[] = {
+ EXTCON_USB,
+ EXTCON_USB_HOST,
+ EXTCON_NONE,
+};
+
+static void mv_enable_wakeup_irqs(struct mv_usb_extcon_info *info)
+{
+ u32 reg;
+ reg = readl(info->pmuap_reg);
+ reg |= (USB_VBUS_WK_MASK | USB_ID_WK_MASK);
+ writel(reg, info->pmuap_reg);
+}
+
+static void mv_disable_wakeup_irqs(struct mv_usb_extcon_info *info)
+{
+ u32 reg;
+ reg = readl(info->pmuap_reg);
+ reg &= ~(USB_VBUS_WK_MASK | USB_ID_WK_MASK);
+ writel(reg, info->pmuap_reg);
+}
+
+/*
+ * "USB" = VBUS and "USB-HOST" = !ID, so we have:
+ * Both "USB" and "USB-HOST" can't be set as active at the
+ * same time so if "USB-HOST" is active (i.e. ID is 0) we keep "USB" inactive
+ * even if VBUS is on.
+ *
+ * State | ID | VBUS
+ * ----------------------------------------
+ * [1] USB | H | H
+ * [2] none | H | L
+ * [3] USB-HOST | L | H
+ * [4] USB-HOST | L | L
+ *
+ * In case we have only one of these signals:
+ * - VBUS only - we want to distinguish between [1] and [2], so ID is always 1.
+ * - ID only - we want to distinguish between [1] and [4], so VBUS = ID.
+*/
+
+static void usb_detect_cable(struct work_struct *work)
+{
+ int id, vbus;
+ int id_state, vbus_state;
+ u32 reg;
+ u32 state;
+
+ struct mv_usb_extcon_info *info = container_of(
+ to_delayed_work(work), struct mv_usb_extcon_info, wq_detcable);
+
+ reg = readl(info->pmuap_reg);
+ id = reg & USB_ID_WK_STATUS;
+ vbus = reg & USB_VBUS_WK_STATUS;
+
+ pr_info("info->pmuap_reg: 0x%x id: %d vbus: %d \n", reg, id, vbus);
+ if (id || vbus) {
+ state = readl(info->pin_state_reg);
+ id_state = state & USB_ID;
+ vbus_state = state & USB_VBUS;
+
+ if (!id_state) {
+ dev_info(info->dev, "USB we as host connected\n");
+ extcon_set_state_sync(info->edev, EXTCON_USB_HOST,
+ true);
+ } else {
+ dev_info(info->dev, "USB we as host disconnected\n");
+ extcon_set_state_sync(info->edev, EXTCON_USB_HOST,
+ false);
+
+ if (!vbus_state) {
+ dev_info(info->dev,
+ "USB we as peripheral disconnected\n");
+ extcon_set_state_sync(info->edev, EXTCON_USB,
+ false);
+ } else {
+ dev_dbg(info->dev, "dbgfs_qos_mode = %d \n",
+ info->dbgfs_qos_mode);
+ dev_info(info->dev,
+ "USB we as peripheral connected\n");
+ extcon_set_state_sync(info->edev, EXTCON_USB,
+ true);
+ }
+ }
+ }
+
+ reg |= (USB_VBUS_WK_CLR | USB_ID_WK_CLR);
+ writel(reg, info->pmuap_reg);
+ mv_enable_wakeup_irqs(info);
+}
+
+static irqreturn_t mv_wakeup_interrupt(int irq, void *_info)
+{
+ struct mv_usb_extcon_info *info = (struct mv_usb_extcon_info *)_info;
+
+ pr_info("extcon_mvci: mv_wakeup_interrupt... \n");
+ mv_disable_wakeup_irqs(info);
+
+ queue_delayed_work(system_power_efficient_wq, &info->wq_detcable,
+ info->debounce_jiffies);
+
+ return IRQ_HANDLED;
+}
+
+static ssize_t extcon_mvci_dbgfs_read(struct file *filp, char __user *user_buf,
+ size_t size, loff_t *ppos)
+{
+ struct mv_usb_extcon_info *info = filp->private_data;
+ char buf[64];
+ int ret, n, copy;
+
+ n = min(sizeof(buf) - 1, size);
+
+ if (info->dbgfs_qos_mode == 1)
+ copy = sprintf(buf, "enable mvci qos_hold\n");
+ else
+ copy = sprintf(buf, "disable mvci qos_hold\n");
+
+ copy = min(n, copy);
+ ret = simple_read_from_buffer(user_buf, size, ppos, buf, copy);
+
+ return ret;
+}
+
+static ssize_t extcon_mvci_dbgfs_write(struct file *filp,
+ const char __user *user_buf, size_t size,
+ loff_t *ppos)
+{
+ struct mv_usb_extcon_info *info = filp->private_data;
+ char buf[32];
+ int buf_size, i = 0;
+
+ buf_size = min(size, sizeof(buf) - 1);
+ if (copy_from_user(buf, user_buf, buf_size))
+ return -EFAULT;
+
+ *(buf + buf_size) = '\0';
+ while (*(buf + i) != '\n' && *(buf + i) != '\0')
+ i++;
+ *(buf + i) = '\0';
+
+ i = 0;
+ while (*(buf + i) == ' ')
+ i++;
+
+ if (!strncmp(buf + i, "enable", 6)) {
+ info->dbgfs_qos_mode = 1;
+ } else if (!strncmp(buf + i, "disable", 7)) {
+ info->dbgfs_qos_mode = 0;
+ dev_info(info->dev, "mvci qos release\n");
+ } else {
+ dev_err(info->dev, "only accept: enable, disable\n");
+ }
+
+ return size;
+}
+
+static const struct file_operations extcon_mvci_dbgfs_ops = {
+ .owner = THIS_MODULE,
+ .open = simple_open,
+ .read = extcon_mvci_dbgfs_read,
+ .write = extcon_mvci_dbgfs_write,
+};
+
+static int mv_usb_extcon_probe(struct platform_device *pdev)
+{
+ struct device *dev = &pdev->dev;
+ struct device_node *np = dev->of_node;
+ struct resource *res;
+ struct mv_usb_extcon_info *info;
+ int ret;
+ u32 property;
+#ifdef CONFIG_PM
+ //struct freq_constraints *idle_qos;
+#endif
+
+ if (!np)
+ return -EINVAL;
+
+ dev_info(dev, "mv_usb_extcon_probe\n");
+ info = devm_kzalloc(&pdev->dev, sizeof(*info), GFP_KERNEL);
+ if (!info)
+ return -ENOMEM;
+
+ info->dev = dev;
+ info->irq = platform_get_irq(pdev, 0);
+ if (info->irq < 0) {
+ dev_err(dev, "missing IRQ resource\n");
+ return -EINVAL;
+ }
+
+ res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "reg_pmuap");
+ if (!res) {
+ dev_err(dev, "missing memory base resource\n");
+ return -ENODEV;
+ }
+
+ info->pmuap_reg =
+ devm_ioremap(&pdev->dev, res->start, resource_size(res));
+ if (!info->pmuap_reg) {
+ dev_err(dev, "ioremap failed\n");
+ return -ENODEV;
+ }
+
+ res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "pin_state");
+ if (!res) {
+ dev_err(dev, "missing memory base resource\n");
+ return -ENODEV;
+ }
+
+ info->pin_state_reg =
+ devm_ioremap(&pdev->dev, res->start, resource_size(res));
+ if (!info->pin_state_reg) {
+ dev_err(dev, "ioremap failed\n");
+ return -ENODEV;
+ }
+
+ info->edev = devm_extcon_dev_allocate(dev, usb_extcon_cable);
+ if (IS_ERR(info->edev)) {
+ dev_err(dev, "failed to allocate extcon device\n");
+ return -ENOMEM;
+ }
+
+ ret = devm_extcon_dev_register(dev, info->edev);
+ if (ret < 0) {
+ dev_err(dev, "failed to register extcon device\n");
+ return ret;
+ }
+
+ info->dbgfs_qos_mode = 1;
+
+ ret = devm_request_irq(dev, info->irq, mv_wakeup_interrupt,
+ IRQF_NO_SUSPEND, "mv-wakeup", info);
+ if (ret) {
+ dev_err(dev, "failed to request IRQ #%d --> %d\n", info->irq,
+ ret);
+ return ret;
+ }
+
+ if (!of_property_read_s32(pdev->dev.of_node, "lpm-qos", &property))
+ info->lpm_qos = property;
+ else
+ info->lpm_qos = 15;
+
+ platform_set_drvdata(pdev, info);
+ device_init_wakeup(dev, 1);
+
+ info->debounce_jiffies = msecs_to_jiffies(USB_GPIO_DEBOUNCE_MS);
+
+ INIT_DELAYED_WORK(&info->wq_detcable, usb_detect_cable);
+
+ mv_enable_wakeup_irqs(info);
+
+ /* Perform initial detection */
+ usb_detect_cable(&info->wq_detcable.work);
+
+ info->dbgfs = debugfs_create_file("mvci_extcon_qos", 0644, NULL, info,
+ &extcon_mvci_dbgfs_ops);
+ if (!info->dbgfs) {
+ dev_err(info->dev, "failed to create debugfs\n");
+ return -ENOMEM;
+ }
+
+ return 0;
+}
+
+static int mv_usb_extcon_remove(struct platform_device *pdev)
+{
+ struct mv_usb_extcon_info *info = platform_get_drvdata(pdev);
+
+ cancel_delayed_work_sync(&info->wq_detcable);
+ device_init_wakeup(&pdev->dev, 0);
+
+ freq_qos_remove_request(&info->qos_idle);
+
+ return 0;
+}
+
+static const struct of_device_id mv_usb_extcon_dt_match[] = {
+ {
+ .compatible = "spacemit,vbus-id",
+ },
+ {}
+};
+
+MODULE_DEVICE_TABLE(of, mv_usb_extcon_dt_match);
+
+static struct platform_driver usb_extcon_driver = {
+ .probe = mv_usb_extcon_probe,
+ .remove = mv_usb_extcon_remove,
+ .driver = {
+ .name = "extcon-k1xci-usb",
+ .of_match_table = mv_usb_extcon_dt_match,
+ },
+};
+
+module_platform_driver(usb_extcon_driver);
+
+MODULE_LICENSE("GPL v2");
--
Armbian

View File

@@ -1,28 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Patrick Yavitz <pyavitz@armbian.com>
Date: Fri, 21 Jun 2024 11:54:06 -0400
Subject: add spacemit patch set
source: https://gitee.com/bianbu-linux/linux-6.1
Signed-off-by: Patrick Yavitz <pyavitz@armbian.com>
---
drivers/firmware/arm_scmi/Kconfig | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/firmware/arm_scmi/Kconfig b/drivers/firmware/arm_scmi/Kconfig
index 111111111111..222222222222 100644
--- a/drivers/firmware/arm_scmi/Kconfig
+++ b/drivers/firmware/arm_scmi/Kconfig
@@ -3,7 +3,7 @@ menu "ARM System Control and Management Interface Protocol"
config ARM_SCMI_PROTOCOL
tristate "ARM System Control and Management Interface (SCMI) Message Protocol"
- depends on ARM || ARM64 || COMPILE_TEST
+ depends on ARM || ARM64 || COMPILE_TEST || SOC_SPACEMIT
help
ARM System Control and Management Interface (SCMI) protocol is a
set of operating system-independent software interfaces that are
--
Armbian

View File

@@ -1,476 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Patrick Yavitz <pyavitz@armbian.com>
Date: Fri, 21 Jun 2024 11:54:06 -0400
Subject: add spacemit patch set
source: https://gitee.com/bianbu-linux/linux-6.1
Signed-off-by: Patrick Yavitz <pyavitz@armbian.com>
---
drivers/gpio/Kconfig | 9 +
drivers/gpio/Makefile | 1 +
drivers/gpio/gpio-k1x.c | 424 ++++++++++
3 files changed, 434 insertions(+)
diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig
index 111111111111..222222222222 100644
--- a/drivers/gpio/Kconfig
+++ b/drivers/gpio/Kconfig
@@ -355,6 +355,15 @@ config GPIO_IOP
If unsure, say N.
+config GPIO_K1X
+ bool "SPACEMIT-K1X GPIO support"
+ depends on SOC_SPACEMIT_K1X
+ help
+ Say yes here to support the K1X GPIO device.
+ The K1X GPIO device may have several banks, and each
+ bank control at most 32 GPIO pins. The number of banks
+ is passed by device tree or platform data.
+
config GPIO_IXP4XX
bool "Intel IXP4xx GPIO"
depends on ARCH_IXP4XX
diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile
index 111111111111..222222222222 100644
--- a/drivers/gpio/Makefile
+++ b/drivers/gpio/Makefile
@@ -187,3 +187,4 @@ obj-$(CONFIG_GPIO_XTENSA) += gpio-xtensa.o
obj-$(CONFIG_GPIO_ZEVIO) += gpio-zevio.o
obj-$(CONFIG_GPIO_ZYNQ) += gpio-zynq.o
obj-$(CONFIG_GPIO_ZYNQMP_MODEPIN) += gpio-zynqmp-modepin.o
+obj-$(CONFIG_GPIO_K1X) += gpio-k1x.o
diff --git a/drivers/gpio/gpio-k1x.c b/drivers/gpio/gpio-k1x.c
new file mode 100644
index 000000000000..111111111111
--- /dev/null
+++ b/drivers/gpio/gpio-k1x.c
@@ -0,0 +1,424 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * spacemit-k1x gpio driver file
+ *
+ * Copyright (C) 2023 Spacemit
+ *
+ */
+
+#include <linux/err.h>
+#include <linux/init.h>
+#include <linux/irq.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/gpio.h>
+#include <linux/clk.h>
+#include <linux/of_device.h>
+#include <linux/platform_device.h>
+#include <linux/module.h>
+#include <linux/irqdomain.h>
+
+#define GPLR 0x0
+#define GPDR 0xc
+#define GPSR 0x18
+#define GPCR 0x24
+#define GRER 0x30
+#define GFER 0x3c
+#define GEDR 0x48
+#define GSDR 0x54
+#define GCDR 0x60
+#define GSRER 0x6c
+#define GCRER 0x78
+#define GSFER 0x84
+#define GCFER 0x90
+#define GAPMASK 0x9c
+#define GCPMASK 0xa8
+
+#define K1X_BANK_GPIO_NUMBER (32)
+#define BANK_GPIO_MASK (K1X_BANK_GPIO_NUMBER - 1)
+
+#define k1x_gpio_to_bank_idx(gpio) ((gpio)/K1X_BANK_GPIO_NUMBER)
+#define k1x_gpio_to_bank_offset(gpio) ((gpio) & BANK_GPIO_MASK)
+#define k1x_bank_to_gpio(idx, offset) (((idx) * K1X_BANK_GPIO_NUMBER) \
+ | ((offset) & BANK_GPIO_MASK))
+
+struct k1x_gpio_bank {
+ void __iomem *reg_bank;
+ u32 irq_mask;
+ u32 irq_rising_edge;
+ u32 irq_falling_edge;
+};
+
+struct k1x_gpio_chip {
+ struct gpio_chip chip;
+ void __iomem *reg_base;
+ int irq;
+ struct irq_domain *domain;
+ unsigned int ngpio;
+ unsigned int nbank;
+ struct k1x_gpio_bank *banks;
+};
+
+static int k1x_gpio_to_irq(struct gpio_chip *chip, unsigned offset)
+{
+ struct k1x_gpio_chip *k1x_chip =
+ container_of(chip, struct k1x_gpio_chip, chip);
+
+ return irq_create_mapping(k1x_chip->domain, offset);
+}
+
+static int k1x_gpio_direction_input(struct gpio_chip *chip, unsigned offset)
+{
+ struct k1x_gpio_chip *k1x_chip =
+ container_of(chip, struct k1x_gpio_chip, chip);
+ struct k1x_gpio_bank *bank =
+ &k1x_chip->banks[k1x_gpio_to_bank_idx(offset)];
+ u32 bit = (1 << k1x_gpio_to_bank_offset(offset));
+
+ writel(bit, bank->reg_bank + GCDR);
+
+ return 0;
+}
+
+static int k1x_gpio_direction_output(struct gpio_chip *chip,
+ unsigned offset, int value)
+{
+ struct k1x_gpio_chip *k1x_chip =
+ container_of(chip, struct k1x_gpio_chip, chip);
+ struct k1x_gpio_bank *bank =
+ &k1x_chip->banks[k1x_gpio_to_bank_idx(offset)];
+ u32 bit = (1 << k1x_gpio_to_bank_offset(offset));
+
+ /* Set value first. */
+ writel(bit, bank->reg_bank + (value ? GPSR : GPCR));
+
+ writel(bit, bank->reg_bank + GSDR);
+
+ return 0;
+}
+
+static int k1x_gpio_get(struct gpio_chip *chip, unsigned offset)
+{
+ struct k1x_gpio_chip *k1x_chip =
+ container_of(chip, struct k1x_gpio_chip, chip);
+ struct k1x_gpio_bank *bank =
+ &k1x_chip->banks[k1x_gpio_to_bank_idx(offset)];
+ u32 bit = (1 << k1x_gpio_to_bank_offset(offset));
+ u32 gplr;
+
+ gplr = readl(bank->reg_bank + GPLR);
+
+ return !!(gplr & bit);
+}
+
+static void k1x_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
+{
+ struct k1x_gpio_chip *k1x_chip =
+ container_of(chip, struct k1x_gpio_chip, chip);
+ struct k1x_gpio_bank *bank =
+ &k1x_chip->banks[k1x_gpio_to_bank_idx(offset)];
+ u32 bit = (1 << k1x_gpio_to_bank_offset(offset));
+ u32 gpdr;
+
+ gpdr = readl(bank->reg_bank + GPDR);
+ /* Is it configured as output? */
+ if (gpdr & bit)
+ writel(bit, bank->reg_bank + (value ? GPSR : GPCR));
+}
+
+#ifdef CONFIG_OF_GPIO
+static int k1x_gpio_of_xlate(struct gpio_chip *chip,
+ const struct of_phandle_args *gpiospec,
+ u32 *flags)
+{
+ struct k1x_gpio_chip *k1x_chip =
+ container_of(chip, struct k1x_gpio_chip, chip);
+
+ /* GPIO index start from 0. */
+ if (gpiospec->args[0] >= k1x_chip->ngpio)
+ return -EINVAL;
+
+ if (flags)
+ *flags = gpiospec->args[1];
+
+ return gpiospec->args[0];
+}
+#endif
+
+static int k1x_gpio_irq_type(struct irq_data *d, unsigned int type)
+{
+ struct k1x_gpio_chip *k1x_chip = irq_data_get_irq_chip_data(d);
+ int gpio = irqd_to_hwirq(d);
+ struct k1x_gpio_bank *bank =
+ &k1x_chip->banks[k1x_gpio_to_bank_idx(gpio)];
+ u32 bit = (1 << k1x_gpio_to_bank_offset(gpio));
+
+ if (type & IRQ_TYPE_EDGE_RISING) {
+ bank->irq_rising_edge |= bit;
+ writel(bit, bank->reg_bank + GSRER);
+ } else {
+ bank->irq_rising_edge &= ~bit;
+ writel(bit, bank->reg_bank + GCRER);
+ }
+
+ if (type & IRQ_TYPE_EDGE_FALLING) {
+ bank->irq_falling_edge |= bit;
+ writel(bit, bank->reg_bank + GSFER);
+ } else {
+ bank->irq_falling_edge &= ~bit;
+ writel(bit, bank->reg_bank + GCFER);
+ }
+
+ return 0;
+}
+
+static irqreturn_t k1x_gpio_demux_handler(int irq, void *data)
+{
+ struct k1x_gpio_chip *k1x_chip = (struct k1x_gpio_chip *)data;
+ struct k1x_gpio_bank *bank;
+ int i, n;
+ u32 gedr;
+ unsigned long pending = 0;
+ unsigned int irqs_handled = 0;
+
+ for (i = 0; i < k1x_chip->nbank; i++) {
+ bank = &k1x_chip->banks[i];
+
+ gedr = readl(bank->reg_bank + GEDR);
+ if (!gedr)
+ continue;
+
+ writel(gedr, bank->reg_bank + GEDR);
+ gedr = gedr & bank->irq_mask;
+
+ if (!gedr)
+ continue;
+ pending = gedr;
+ for_each_set_bit(n, &pending, BITS_PER_LONG) {
+ generic_handle_irq(irq_find_mapping(k1x_chip->domain,
+ k1x_bank_to_gpio(i, n)));
+ }
+ irqs_handled++;
+ }
+
+ return irqs_handled ? IRQ_HANDLED : IRQ_NONE;
+}
+
+static void k1x_ack_muxed_gpio(struct irq_data *d)
+{
+ struct k1x_gpio_chip *k1x_chip = irq_data_get_irq_chip_data(d);
+ int gpio = irqd_to_hwirq(d);
+ struct k1x_gpio_bank *bank =
+ &k1x_chip->banks[k1x_gpio_to_bank_idx(gpio)];
+ u32 bit = (1 << k1x_gpio_to_bank_offset(gpio));
+
+ writel(bit, bank->reg_bank + GEDR);
+}
+
+static void k1x_mask_muxed_gpio(struct irq_data *d)
+{
+ struct k1x_gpio_chip *k1x_chip = irq_data_get_irq_chip_data(d);
+ int gpio = irqd_to_hwirq(d);
+ struct k1x_gpio_bank *bank =
+ &k1x_chip->banks[k1x_gpio_to_bank_idx(gpio)];
+ u32 bit = (1 << k1x_gpio_to_bank_offset(gpio));
+
+ bank->irq_mask &= ~bit;
+
+ /* Clear the bit of rising and falling edge detection. */
+ writel(bit, bank->reg_bank + GCRER);
+ writel(bit, bank->reg_bank + GCFER);
+}
+
+static void k1x_unmask_muxed_gpio(struct irq_data *d)
+{
+ struct k1x_gpio_chip *k1x_chip = irq_data_get_irq_chip_data(d);
+ int gpio = irqd_to_hwirq(d);
+ struct k1x_gpio_bank *bank =
+ &k1x_chip->banks[k1x_gpio_to_bank_idx(gpio)];
+ u32 bit = (1 << k1x_gpio_to_bank_offset(gpio));
+
+ bank->irq_mask |= bit;
+
+ /* Set the bit of rising and falling edge detection if the gpio has. */
+ writel(bit & bank->irq_rising_edge, bank->reg_bank + GSRER);
+ writel(bit & bank->irq_falling_edge, bank->reg_bank + GSFER);
+}
+
+static struct irq_chip k1x_muxed_gpio_chip = {
+ .name = "k1x-gpio-irqchip",
+ .irq_ack = k1x_ack_muxed_gpio,
+ .irq_mask = k1x_mask_muxed_gpio,
+ .irq_unmask = k1x_unmask_muxed_gpio,
+ .irq_set_type = k1x_gpio_irq_type,
+ .flags = IRQCHIP_SKIP_SET_WAKE,
+};
+
+static const struct of_device_id k1x_gpio_dt_ids[] = {
+ { .compatible = "spacemit,k1x-gpio"},
+ {}
+};
+
+static int k1x_irq_domain_map(struct irq_domain *d, unsigned int irq,
+ irq_hw_number_t hw)
+{
+ irq_set_chip_and_handler(irq, &k1x_muxed_gpio_chip,
+ handle_edge_irq);
+ irq_set_chip_data(irq, d->host_data);
+
+ return 0;
+}
+
+static const struct irq_domain_ops k1x_gpio_irq_domain_ops = {
+ .map = k1x_irq_domain_map,
+ .xlate = irq_domain_xlate_twocell,
+};
+
+static int k1x_gpio_probe_dt(struct platform_device *pdev,
+ struct k1x_gpio_chip *k1x_chip)
+{
+ struct device_node *np = pdev->dev.of_node;
+ struct device_node *child;
+ u32 offset;
+ int i, nbank, ret;
+
+ nbank = of_get_child_count(np);
+ if (nbank == 0)
+ return -EINVAL;
+
+ k1x_chip->banks = devm_kzalloc(&pdev->dev,
+ sizeof(*k1x_chip->banks) * nbank,
+ GFP_KERNEL);
+ if (k1x_chip->banks == NULL)
+ return -ENOMEM;
+
+ i = 0;
+ for_each_child_of_node(np, child) {
+ ret = of_property_read_u32(child, "reg-offset", &offset);
+ if (ret) {
+ of_node_put(child);
+ return ret;
+ }
+ k1x_chip->banks[i].reg_bank = k1x_chip->reg_base + offset;
+ i++;
+ }
+
+ k1x_chip->nbank = nbank;
+ k1x_chip->ngpio = k1x_chip->nbank * K1X_BANK_GPIO_NUMBER;
+
+ return 0;
+}
+
+static int k1x_gpio_probe(struct platform_device *pdev)
+{
+ struct device *dev = &pdev->dev;
+ struct device_node *np;
+ struct k1x_gpio_chip *k1x_chip;
+ struct k1x_gpio_bank *bank;
+ struct resource *res;
+ struct irq_domain *domain;
+ struct clk *clk;
+
+ int irq, i, ret;
+ void __iomem *base;
+
+ np = pdev->dev.of_node;
+ if (!np)
+ return -EINVAL;
+
+ k1x_chip = devm_kzalloc(dev, sizeof(*k1x_chip), GFP_KERNEL);
+ if (k1x_chip == NULL)
+ return -ENOMEM;
+
+ irq = platform_get_irq(pdev, 0);
+ if (irq < 0)
+ return irq;
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ if (!res)
+ return -EINVAL;
+ base = devm_ioremap_resource(dev, res);
+ if (!base)
+ return -EINVAL;
+
+ k1x_chip->irq = irq;
+ k1x_chip->reg_base = base;
+
+ ret = k1x_gpio_probe_dt(pdev, k1x_chip);
+ if (ret) {
+ dev_err(dev, "Fail to initialize gpio unit, error %d.\n", ret);
+ return ret;
+ }
+
+ clk = devm_clk_get(dev, NULL);
+ if (IS_ERR(clk)) {
+ dev_err(dev, "Fail to get gpio clock, error %ld.\n",
+ PTR_ERR(clk));
+ return PTR_ERR(clk);
+ }
+ ret = clk_prepare_enable(clk);
+ if (ret) {
+ dev_err(dev, "Fail to enable gpio clock, error %d.\n", ret);
+ return ret;
+ }
+
+ domain = irq_domain_add_linear(np, k1x_chip->ngpio,
+ &k1x_gpio_irq_domain_ops, k1x_chip);
+ if (domain == NULL)
+ return -EINVAL;
+
+ k1x_chip->domain = domain;
+
+ /* Initialize the gpio chip */
+ k1x_chip->chip.label = "k1x-gpio";
+ k1x_chip->chip.request = gpiochip_generic_request;
+ k1x_chip->chip.free = gpiochip_generic_free;
+ k1x_chip->chip.direction_input = k1x_gpio_direction_input;
+ k1x_chip->chip.direction_output = k1x_gpio_direction_output;
+ k1x_chip->chip.get = k1x_gpio_get;
+ k1x_chip->chip.set = k1x_gpio_set;
+ k1x_chip->chip.to_irq = k1x_gpio_to_irq;
+#ifdef CONFIG_OF_GPIO
+ k1x_chip->chip.of_node = np;
+ k1x_chip->chip.of_xlate = k1x_gpio_of_xlate;
+ k1x_chip->chip.of_gpio_n_cells = 2;
+#endif
+ k1x_chip->chip.ngpio = k1x_chip->ngpio;
+
+ if (devm_request_irq(&pdev->dev, irq,
+ k1x_gpio_demux_handler, 0, k1x_chip->chip.label, k1x_chip)) {
+ dev_err(&pdev->dev, "failed to request high IRQ\n");
+ ret = -ENOENT;
+ goto err;
+ }
+
+ gpiochip_add(&k1x_chip->chip);
+
+ /* clear all GPIO edge detects */
+ for (i = 0; i < k1x_chip->nbank; i++) {
+ bank = &k1x_chip->banks[i];
+ writel(0xffffffff, bank->reg_bank + GCFER);
+ writel(0xffffffff, bank->reg_bank + GCRER);
+ /* Unmask edge detection to AP. */
+ writel(0xffffffff, bank->reg_bank + GAPMASK);
+ }
+
+ return 0;
+err:
+ irq_domain_remove(domain);
+ return ret;
+}
+
+static struct platform_driver k1x_gpio_driver = {
+ .probe = k1x_gpio_probe,
+ .driver = {
+ .name = "k1x-gpio",
+ .of_match_table = k1x_gpio_dt_ids,
+ },
+};
+
+static int __init k1x_gpio_init(void)
+{
+ return platform_driver_register(&k1x_gpio_driver);
+}
+subsys_initcall(k1x_gpio_init);
--
Armbian

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -1,138 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Patrick Yavitz <pyavitz@armbian.com>
Date: Sat, 22 Jun 2024 08:00:24 -0400
Subject: drivers: irqchip: irq-sifive-plic.c
Signed-off-by: Patrick Yavitz <pyavitz@armbian.com>
---
drivers/irqchip/irq-sifive-plic.c | 60 ++++++++--
1 file changed, 53 insertions(+), 7 deletions(-)
diff --git a/drivers/irqchip/irq-sifive-plic.c b/drivers/irqchip/irq-sifive-plic.c
index 111111111111..222222222222 100644
--- a/drivers/irqchip/irq-sifive-plic.c
+++ b/drivers/irqchip/irq-sifive-plic.c
@@ -38,27 +38,39 @@
* We always hardwire it to one in Linux.
*/
#define PRIORITY_BASE 0
-#define PRIORITY_PER_ID 4
+#define PRIORITY_PER_ID 4
/*
* Each hart context has a vector of interrupt enable bits associated with it.
* There's one bit for each interrupt source.
*/
+#ifdef CONFIG_SOC_SPACEMIT
+#define PENDING_BASE 0x1000
+#define CONTEXT_ENABLE_BASE 0x2080
+#define CONTEXT_ENABLE_SIZE 0x100
+#else
#define CONTEXT_ENABLE_BASE 0x2000
-#define CONTEXT_ENABLE_SIZE 0x80
+#define CONTEXT_ENABLE_SIZE 0x80
+#endif
/*
* Each hart context has a set of control registers associated with it. Right
* now there's only two: a source priority threshold over which the hart will
* take an interrupt, and a register to claim interrupts.
*/
+#ifdef CONFIG_SOC_SPACEMIT
+#define CONTEXT_BASE 0x201000
+#define CONTEXT_SIZE 0x2000
+#else
#define CONTEXT_BASE 0x200000
-#define CONTEXT_SIZE 0x1000
-#define CONTEXT_THRESHOLD 0x00
-#define CONTEXT_CLAIM 0x04
+#define CONTEXT_SIZE 0x1000
+#endif
-#define PLIC_DISABLE_THRESHOLD 0x7
-#define PLIC_ENABLE_THRESHOLD 0
+#define CONTEXT_THRESHOLD 0x00
+#define CONTEXT_CLAIM 0x04
+
+#define PLIC_DISABLE_THRESHOLD 0x7
+#define PLIC_ENABLE_THRESHOLD 0
#define PLIC_QUIRK_EDGE_INTERRUPT 0
@@ -100,7 +112,19 @@ static void __plic_toggle(void __iomem *enable_base, int hwirq, int enable)
static void plic_toggle(struct plic_handler *handler, int hwirq, int enable)
{
raw_spin_lock(&handler->enable_lock);
+
+#ifdef CONFIG_SOC_SPACEMIT
+ if (!enable)
+ writel(hwirq, handler->hart_base + CONTEXT_CLAIM);
+#endif
+
__plic_toggle(handler->enable_base, hwirq, enable);
+
+#ifdef CONFIG_SOC_SPACEMIT
+ if (enable)
+ writel(hwirq, handler->hart_base + CONTEXT_CLAIM);
+#endif
+
raw_spin_unlock(&handler->enable_lock);
}
@@ -193,7 +217,11 @@ static struct irq_chip plic_edge_chip = {
.irq_set_affinity = plic_set_affinity,
#endif
.irq_set_type = plic_irq_set_type,
+#ifdef CONFIG_SOC_SPACEMIT
+ .flags = IRQCHIP_AFFINITY_PRE_STARTUP | IRQCHIP_ENABLE_WAKEUP_ON_SUSPEND | IRQCHIP_SKIP_SET_WAKE,
+#else
.flags = IRQCHIP_AFFINITY_PRE_STARTUP,
+#endif
};
static struct irq_chip plic_chip = {
@@ -207,7 +235,11 @@ static struct irq_chip plic_chip = {
.irq_set_affinity = plic_set_affinity,
#endif
.irq_set_type = plic_irq_set_type,
+#ifdef CONFIG_SOC_SPACEMIT
+ .flags = IRQCHIP_AFFINITY_PRE_STARTUP | IRQCHIP_ENABLE_WAKEUP_ON_SUSPEND | IRQCHIP_SKIP_SET_WAKE,
+#else
.flags = IRQCHIP_AFFINITY_PRE_STARTUP,
+#endif
};
static int plic_irq_set_type(struct irq_data *d, unsigned int type)
@@ -439,15 +471,29 @@ static int __init __plic_init(struct device_node *node,
cpumask_set_cpu(cpu, &priv->lmask);
handler->present = true;
+#ifdef CONFIG_SOC_SPACEMIT
+ handler->hart_base = priv->regs + CONTEXT_BASE +
+ hartid * CONTEXT_SIZE;
+#else
handler->hart_base = priv->regs + CONTEXT_BASE +
i * CONTEXT_SIZE;
+#endif
raw_spin_lock_init(&handler->enable_lock);
+#ifdef CONFIG_SOC_SPACEMIT
+ handler->enable_base = priv->regs + CONTEXT_ENABLE_BASE +
+ hartid * CONTEXT_ENABLE_SIZE;
+#else
handler->enable_base = priv->regs + CONTEXT_ENABLE_BASE +
i * CONTEXT_ENABLE_SIZE;
+#endif
handler->priv = priv;
done:
for (hwirq = 1; hwirq <= nr_irqs; hwirq++) {
plic_toggle(handler, hwirq, 0);
+ #ifdef CONFIG_SOC_SPACEMIT
+ /* clear pending, which maybe triggered by uboot */
+ writel(0, priv->regs + PENDING_BASE + (hwirq/32)*4);
+ #endif
writel(1, priv->regs + PRIORITY_BASE +
hwirq * PRIORITY_PER_ID);
}
--
Armbian

View File

@@ -1,400 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Patrick Yavitz <pyavitz@armbian.com>
Date: Fri, 21 Jun 2024 11:54:06 -0400
Subject: add spacemit patch set
source: https://gitee.com/bianbu-linux/linux-6.1
Signed-off-by: Patrick Yavitz <pyavitz@armbian.com>
---
drivers/mailbox/Kconfig | 27 +
drivers/mailbox/Makefile | 2 +
drivers/mailbox/spacemit/Makefile | 2 +
drivers/mailbox/spacemit/k1x-mailbox.c | 283 ++++++++++
drivers/mailbox/spacemit/k1x_mailbox.h | 32 ++
5 files changed, 346 insertions(+)
diff --git a/drivers/mailbox/Kconfig b/drivers/mailbox/Kconfig
index 111111111111..222222222222 100644
--- a/drivers/mailbox/Kconfig
+++ b/drivers/mailbox/Kconfig
@@ -294,4 +294,31 @@ config QCOM_IPCC
acts as an interrupt controller for receiving interrupts from clients.
Say Y here if you want to build this driver.
+config SPACEMIT_MAILBOX
+ tristate "Spacemit Message Box"
+ depends on SOC_SPACEMIT
+ help
+ Mailbox implementation for the hardware message box present in
+ various Spacemit SoCs. This mailbox is used for communication
+ between the application CPUs and the power management coprocessor.
+
+if SPACEMIT_MAILBOX
+
+config K1PRO_MAILBOX
+ tristate "Spacemit K1pro Message Box"
+ depends on SOC_SPACEMIT
+ help
+ Mailbox implementation for the hardware message box present in
+ various Spacemit SoCs. This mailbox is used for communication
+ between the application CPUs and the power management coprocessor.
+
+config K1X_MAILBOX
+ tristate "Spacemit K1x Message Box"
+ depends on SOC_SPACEMIT
+ help
+ Mailbox implementation for the hardware message box present in
+ various Spacemit SoCs. This mailbox is used for communication
+ between the application CPUs and the power management coprocessor.
+endif
+
endif
diff --git a/drivers/mailbox/Makefile b/drivers/mailbox/Makefile
index 111111111111..222222222222 100644
--- a/drivers/mailbox/Makefile
+++ b/drivers/mailbox/Makefile
@@ -62,3 +62,5 @@ obj-$(CONFIG_SPRD_MBOX) += sprd-mailbox.o
obj-$(CONFIG_QCOM_IPCC) += qcom-ipcc.o
obj-$(CONFIG_APPLE_MAILBOX) += apple-mailbox.o
+
+obj-$(CONFIG_SPACEMIT_MAILBOX) += spacemit/
diff --git a/drivers/mailbox/spacemit/Makefile b/drivers/mailbox/spacemit/Makefile
new file mode 100644
index 000000000000..111111111111
--- /dev/null
+++ b/drivers/mailbox/spacemit/Makefile
@@ -0,0 +1,2 @@
+obj-$(CONFIG_K1PRO_MAILBOX) += k1pro-mailbox.o
+obj-$(CONFIG_K1X_MAILBOX) += k1x-mailbox.o
diff --git a/drivers/mailbox/spacemit/k1x-mailbox.c b/drivers/mailbox/spacemit/k1x-mailbox.c
new file mode 100644
index 000000000000..111111111111
--- /dev/null
+++ b/drivers/mailbox/spacemit/k1x-mailbox.c
@@ -0,0 +1,283 @@
+// SPDX-License-Identifier: GPL-2.0
+
+#include <linux/bitops.h>
+#include <linux/clk.h>
+#include <linux/device.h>
+#include <linux/err.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/kernel.h>
+#include <linux/mailbox_controller.h>
+#include <linux/mailbox_client.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_irq.h>
+#include <linux/platform_device.h>
+#include <linux/reset.h>
+#include <linux/spinlock.h>
+#include <linux/pm_runtime.h>
+#include <linux/pm_qos.h>
+#include "../mailbox.h"
+#include "k1x_mailbox.h"
+
+#define mbox_dbg(mbox, ...) dev_dbg((mbox)->controller.dev, __VA_ARGS__)
+
+#define DEV_PM_QOS_CLK_GATE 1
+#define DEV_PM_QOS_REGULATOR_GATE 2
+#define DEV_PM_QOS_PM_DOMAIN_GATE 4
+#define DEV_PM_QOS_DEFAULT 7
+
+static struct dev_pm_qos_request greq;
+
+static irqreturn_t spacemit_mbox_irq(int irq, void *dev_id)
+{
+ struct spacemit_mailbox *mbox = dev_id;
+ struct mbox_chan *chan;
+ unsigned int status, msg = 0;
+ int i;
+
+ writel(0, (void __iomem *)&mbox->regs->ipc_iir);
+
+ status = readl((void __iomem *)&mbox->regs->ipc_iir);
+
+ if (!(status & 0xff))
+ return IRQ_NONE;
+
+ for (i = SPACEMIT_TX_ACK_OFFSET; i < SPACEMIT_NUM_CHANNELS + SPACEMIT_TX_ACK_OFFSET; ++i) {
+ chan = &mbox->controller.chans[i - SPACEMIT_TX_ACK_OFFSET];
+ /* new msg irq */
+ if (!(status & (1 << i)))
+ continue;
+
+ /* clear the irq pending */
+ writel(1 << i, (void __iomem *)&mbox->regs->ipc_icr);
+
+ if (chan->txdone_method & TXDONE_BY_IRQ)
+ mbox_chan_txdone(chan, 0);
+ }
+
+ for (i = 0; i < SPACEMIT_NUM_CHANNELS; ++i) {
+ chan = &mbox->controller.chans[i];
+
+ /* new msg irq */
+ if (!(status & (1 << i)))
+ continue;
+
+ mbox_chan_received_data(chan, &msg);
+
+ /* clear the irq pending */
+ writel(1 << i, (void __iomem *)&mbox->regs->ipc_icr);
+ }
+
+ return IRQ_HANDLED;
+}
+
+static int spacemit_chan_send_data(struct mbox_chan *chan, void *data)
+{
+ unsigned long flag;
+ struct spacemit_mailbox *mbox = ((struct spacemit_mb_con_priv *)chan->con_priv)->smb;
+ unsigned int chan_num = chan - mbox->controller.chans;
+
+ spin_lock_irqsave(&mbox->lock, flag);
+
+ writel(1 << chan_num, (void __iomem *)&mbox->regs->ipc_isrw);
+
+ spin_unlock_irqrestore(&mbox->lock, flag);
+
+ mbox_dbg(mbox, "Channel %d sent 0x%08x\n", chan_num, *((unsigned int *)data));
+
+ return 0;
+}
+
+static int spacemit_chan_startup(struct mbox_chan *chan)
+{
+ return 0;
+}
+
+static void spacemit_chan_shutdown(struct mbox_chan *chan)
+{
+ unsigned int j;
+ unsigned long flag;
+ struct spacemit_mailbox *mbox = ((struct spacemit_mb_con_priv *)chan->con_priv)->smb;
+ unsigned int chan_num = chan - mbox->controller.chans;
+
+ spin_lock_irqsave(&mbox->lock, flag);
+
+ /* clear pending */
+ j = 0;
+ j |= (1 << chan_num);
+ writel(j, (void __iomem *)&mbox->regs->ipc_icr);
+
+ spin_unlock_irqrestore(&mbox->lock, flag);
+}
+
+static bool spacemit_chan_last_tx_done(struct mbox_chan *chan)
+{
+ return 0;
+}
+
+static bool spacemit_chan_peek_data(struct mbox_chan *chan)
+{
+ struct spacemit_mailbox *mbox = ((struct spacemit_mb_con_priv *)chan->con_priv)->smb;
+ unsigned int chan_num = chan - mbox->controller.chans;
+
+ return readl((void __iomem *)&mbox->regs->ipc_rdr) & (1 << chan_num);
+}
+
+static const struct mbox_chan_ops spacemit_chan_ops = {
+ .send_data = spacemit_chan_send_data,
+ .startup = spacemit_chan_startup,
+ .shutdown = spacemit_chan_shutdown,
+ .last_tx_done = spacemit_chan_last_tx_done,
+ .peek_data = spacemit_chan_peek_data,
+};
+
+static int spacemit_mailbox_probe(struct platform_device *pdev)
+{
+ struct device *dev = &pdev->dev;
+ struct mbox_chan *chans;
+ struct spacemit_mailbox *mbox;
+ struct spacemit_mb_con_priv *con_priv;
+ int i, ret;
+
+ mbox = devm_kzalloc(dev, sizeof(*mbox), GFP_KERNEL);
+ if (!mbox)
+ return -ENOMEM;
+
+ con_priv = devm_kzalloc(dev, sizeof(*con_priv) * SPACEMIT_NUM_CHANNELS, GFP_KERNEL);
+ if (!con_priv)
+ return -ENOMEM;
+
+ chans = devm_kcalloc(dev, SPACEMIT_NUM_CHANNELS, sizeof(*chans), GFP_KERNEL);
+ if (!chans)
+ return -ENOMEM;
+
+ for (i = 0; i < SPACEMIT_NUM_CHANNELS; ++i) {
+ con_priv[i].smb = mbox;
+ chans[i].con_priv = con_priv + i;
+ }
+
+ mbox->dev = dev;
+
+ mbox->regs = (mbox_reg_desc_t *)devm_platform_ioremap_resource(pdev, 0);
+ if (IS_ERR(mbox->regs)) {
+ ret = PTR_ERR(mbox->regs);
+ dev_err(dev, "Failed to map MMIO resource: %d\n", ret);
+ return -EINVAL;
+ }
+
+ mbox->reset = devm_reset_control_get_exclusive(dev, "core_reset");
+ if (IS_ERR(mbox->reset)) {
+ ret = PTR_ERR(mbox->reset);
+ dev_err(dev, "Failed to get reset: %d\n", ret);
+ return -EINVAL;
+ }
+
+ /* deasser clk */
+ ret = reset_control_deassert(mbox->reset);
+ if (ret) {
+ dev_err(dev, "Failed to deassert reset: %d\n", ret);
+ return -EINVAL;
+ }
+
+ pm_runtime_enable(dev);
+ dev_pm_qos_add_request(dev, &greq, DEV_PM_QOS_MAX_FREQUENCY,
+ DEV_PM_QOS_CLK_GATE | DEV_PM_QOS_PM_DOMAIN_GATE);
+ pm_runtime_get_sync(dev);
+ /* do not disable the clk of mailbox when suspend */
+ dev_pm_qos_update_request(&greq, DEV_PM_QOS_PM_DOMAIN_GATE);
+ pm_runtime_get_noresume(dev);
+
+ /* request irq */
+ ret = devm_request_irq(dev, platform_get_irq(pdev, 0),
+ spacemit_mbox_irq, IRQF_NO_SUSPEND, dev_name(dev), mbox);
+ if (ret) {
+ dev_err(dev, "Failed to register IRQ handler: %d\n", ret);
+ return -EINVAL;
+ }
+
+ /* register the mailbox controller */
+ mbox->controller.dev = dev;
+ mbox->controller.ops = &spacemit_chan_ops;
+ mbox->controller.chans = chans;
+ mbox->controller.num_chans = SPACEMIT_NUM_CHANNELS;
+ mbox->controller.txdone_irq = true;
+ mbox->controller.txdone_poll = false;
+ mbox->controller.txpoll_period = 5;
+
+ spin_lock_init(&mbox->lock);
+ platform_set_drvdata(pdev, mbox);
+
+ ret = mbox_controller_register(&mbox->controller);
+ if (ret) {
+ dev_err(dev, "Failed to register controller: %d\n", ret);
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int spacemit_mailbox_remove(struct platform_device *pdev)
+{
+ struct spacemit_mailbox *mbox = platform_get_drvdata(pdev);
+
+ mbox_controller_unregister(&mbox->controller);
+
+ pm_runtime_put_noidle(&pdev->dev);
+ pm_runtime_put_sync(&pdev->dev);
+
+ return 0;
+}
+
+static const struct of_device_id spacemit_mailbox_of_match[] = {
+ { .compatible = "spacemit,k1-x-mailbox", },
+ {},
+};
+MODULE_DEVICE_TABLE(of, spacemit_mailbox_of_match);
+
+#ifdef CONFIG_PM_SLEEP
+static int k1x_mailbox_suspend_noirq(struct device *dev)
+{
+#if 0
+ int ret;
+ struct spacemit_mailbox *mbox = dev_get_drvdata(dev);
+
+ ret = reset_control_assert(mbox->reset);
+#endif
+
+ return 0;
+}
+
+static int k1x_mailbox_resume_noirq(struct device *dev)
+{
+#if 0
+ int ret;
+ struct spacemit_mailbox *mbox = dev_get_drvdata(dev);
+
+ ret = reset_control_deassert(mbox->reset);
+#endif
+
+ return 0;
+}
+
+static const struct dev_pm_ops k1x_mailbox_pm_qos = {
+ .suspend_noirq = k1x_mailbox_suspend_noirq,
+ .resume_noirq = k1x_mailbox_resume_noirq,
+};
+#endif
+
+static struct platform_driver spacemit_mailbox_driver = {
+ .driver = {
+ .name = "spacemit-mailbox",
+#ifdef CONFIG_PM_SLEEP
+ .pm = &k1x_mailbox_pm_qos,
+#endif
+ .of_match_table = spacemit_mailbox_of_match,
+ },
+ .probe = spacemit_mailbox_probe,
+ .remove = spacemit_mailbox_remove,
+};
+module_platform_driver(spacemit_mailbox_driver);
+
+MODULE_DESCRIPTION("spacemit Message Box driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/mailbox/spacemit/k1x_mailbox.h b/drivers/mailbox/spacemit/k1x_mailbox.h
new file mode 100644
index 000000000000..111111111111
--- /dev/null
+++ b/drivers/mailbox/spacemit/k1x_mailbox.h
@@ -0,0 +1,32 @@
+#ifndef __SPACEMIT_MAILBOX_H__
+#define __SPACEMIT_MAILBOX_H__
+
+#include <linux/kernel.h>
+#include <linux/mailbox_controller.h>
+#include <linux/spinlock.h>
+
+#define SPACEMIT_NUM_CHANNELS 4
+#define SPACEMIT_TX_ACK_OFFSET 4
+
+typedef struct mbox_reg_desc {
+ unsigned int ipc_dw;
+ unsigned int ipc_wdr;
+ unsigned int ipc_isrw;
+ unsigned int ipc_icr;
+ unsigned int ipc_iir;
+ unsigned int ipc_rdr;
+} mbox_reg_desc_t;
+
+struct spacemit_mailbox {
+ struct mbox_controller controller;
+ struct reset_control *reset;
+ mbox_reg_desc_t *regs;
+ spinlock_t lock;
+ struct device *dev;
+};
+
+struct spacemit_mb_con_priv {
+ struct spacemit_mailbox *smb;
+};
+
+#endif /* __SPACEMIT_MAILBOX_H__ */
--
Armbian

View File

@@ -1,387 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Patrick Yavitz <pyavitz@armbian.com>
Date: Fri, 21 Jun 2024 11:54:06 -0400
Subject: add spacemit patch set
source: https://gitee.com/bianbu-linux/linux-6.1
Signed-off-by: Patrick Yavitz <pyavitz@armbian.com>
---
drivers/media/rc/Kconfig | 9 +
drivers/media/rc/Makefile | 1 +
drivers/media/rc/ir-spacemit.c | 331 ++++++++++
3 files changed, 341 insertions(+)
diff --git a/drivers/media/rc/Kconfig b/drivers/media/rc/Kconfig
index 111111111111..222222222222 100644
--- a/drivers/media/rc/Kconfig
+++ b/drivers/media/rc/Kconfig
@@ -387,6 +387,15 @@ config IR_SUNXI
To compile this driver as a module, choose M here: the module will
be called sunxi-ir.
+config IR_SPACEMIT
+ tristate "SPACEMIT IR remote Recriver control"
+ depends on SOC_SPACEMIT
+ help
+ Say Y if you want to use spacemit IR Controller
+
+ To compile this driver as a module, choose M here: the module will be
+ called spacemit-ir
+
config IR_TOY
tristate "Infrared Toy and IR Droid"
depends on USB
diff --git a/drivers/media/rc/Makefile b/drivers/media/rc/Makefile
index 111111111111..222222222222 100644
--- a/drivers/media/rc/Makefile
+++ b/drivers/media/rc/Makefile
@@ -48,6 +48,7 @@ obj-$(CONFIG_IR_SERIAL) += serial_ir.o
obj-$(CONFIG_IR_SPI) += ir-spi.o
obj-$(CONFIG_IR_STREAMZAP) += streamzap.o
obj-$(CONFIG_IR_SUNXI) += sunxi-cir.o
+obj-$(CONFIG_IR_SPACEMIT) += ir-spacemit.o
obj-$(CONFIG_IR_TOY) += ir_toy.o
obj-$(CONFIG_IR_TTUSBIR) += ttusbir.o
obj-$(CONFIG_IR_WINBOND_CIR) += winbond-cir.o
diff --git a/drivers/media/rc/ir-spacemit.c b/drivers/media/rc/ir-spacemit.c
new file mode 100644
index 000000000000..111111111111
--- /dev/null
+++ b/drivers/media/rc/ir-spacemit.c
@@ -0,0 +1,331 @@
+//*SPDX-License-Identifier: GPL-2.0 */
+/*
+ * spacaemit ir-rx controller driver
+ *
+ * Copyright (C) 2023 SPACEMIT Limited
+ */
+#include <linux/clk.h>
+#include <linux/interrupt.h>
+#include <linux/module.h>
+#include <linux/of_platform.h>
+#include <linux/reset.h>
+#include <media/rc-core.h>
+
+#define SPACEMIT_IR_DEV "spacemit-ir"
+
+/*Registers*/
+#define SPACEMIT_IRC_EN 0x0
+#define SPACEMIT_IR_CLKDIV 0x4
+#define SPACEMIT_IR_NOTHR 0x8
+#define SPACEMIT_IR_IDSTATE 0xc
+#define SPACEMIT_IR_FIFO 0x10
+#define SPACEMIT_IR_STS 0x14
+#define SPACEMIT_IR_CMP 0x18
+#define SPACEMIT_IR_INTEN 0x1c
+#define SPACEMIT_IR_INTSTA 0x20
+
+#define SPACEMIT_IR_ENABLE BIT(0)
+#define STATE_IDLE BIT(0)
+#define FIFO_EMPTY BIT(30)
+#define FIFO_FULL BIT(31)
+#define IR_IRQ_EN_PULLDOWN BIT(0)
+#define IR_IRQ_EN_PULLUP BIT(1)
+#define IR_IRQ_EN_COUNT BIT(2)
+#define IR_IRQ_EN_MATCH BIT(3)
+#define IR_FIFO_DATA(val) (val&GENMASK(5,0))
+#define SPACEMIT_IR_NOISE 1
+
+/*ir interrupt status*/
+#define IR_IRQ_PULLUP IR_IRQ_EN_PULLUP
+#define IR_IRQ_PULLDOWN IR_IRQ_EN_PULLDOWN
+#define IR_IRQ_COUNT IR_IRQ_EN_COUNT
+#define IR_IRQ_MATCH IR_IRQ_EN_MATCH
+#define IRQ_CLEAR_ALL \
+ (IR_IRQ_PULLUP | \
+ IR_IRQ_PULLDOWN | \
+ IR_IRQ_COUNT | \
+ IR_IRQ_MATCH)
+#define IR_IRQ_ENALL IRQ_CLEAR_ALL
+
+#define IR_FREQ 100000
+#define CYCLE_TIME 1000000/IR_FREQ
+#define SPACEMIT_IR_TIMEOUT 10000
+#define IRFIFO_DEF_CMP 1
+
+struct spacemit_ir {
+ struct rc_dev *rc;
+ void __iomem *base;
+ int irq;
+ int fifo_size;
+ int clkdiv;
+ struct clk *apb_clk;
+ const char *map_name;
+#ifndef CONFIG_SOC_SPACEMIT_K1X
+ struct clk *clk;
+ struct reset_control *rst;
+#endif
+};
+
+struct spacemit_ir_data {
+ int fifo_size;
+};
+
+static irqreturn_t spacemit_ir_irq(int irqno,void *dev_id)
+{
+ u32 irq_flag,i,rc,fifo_status;
+ u8 info;
+ struct spacemit_ir *ir = dev_id;
+ struct ir_raw_event rawir = {};
+
+ irq_flag = readl(ir->base + SPACEMIT_IR_INTSTA);
+
+ /*clear all interrupt*/
+ writel(IRQ_CLEAR_ALL,ir->base + SPACEMIT_IR_INTSTA);
+
+ /*store data from fifo*/
+ fifo_status = readl(ir->base + SPACEMIT_IR_STS);
+
+ if(!(fifo_status & FIFO_EMPTY))
+ {
+ rc = IR_FIFO_DATA(fifo_status);
+ for(i = 0 ; i < rc ; i++)
+ {
+ info = readb(ir->base + SPACEMIT_IR_FIFO);
+ rawir.pulse = !(info & 0x80);
+ rawir.duration = (info & 0x7f)*ir->rc->rx_resolution;
+ ir_raw_event_store_with_filter(ir->rc, &rawir);
+ }
+ }
+
+ /*wake up ir-event thread*/
+ ir_raw_event_handle(ir->rc);
+
+ return IRQ_HANDLED;
+}
+
+static int spacemit_ir_config(struct rc_dev *rc_dev)
+{
+ struct spacemit_ir *ir = rc_dev->priv;
+ //u32 base_clk = clk_get_rate(ir->apb_clk);
+ u32 base_clk = 50000000;
+
+ /*set clkdiv*/
+ ir->clkdiv = DIV_ROUND_UP(base_clk, IR_FREQ)-1;
+ writel(ir->clkdiv, ir->base + SPACEMIT_IR_CLKDIV);
+
+ writel(IRQ_CLEAR_ALL,ir->base + SPACEMIT_IR_INTSTA);
+
+ /*set noise threshold*/
+ writeb(SPACEMIT_IR_NOISE, ir->base + SPACEMIT_IR_NOTHR);
+
+ writel(IRFIFO_DEF_CMP, ir->base + SPACEMIT_IR_CMP);
+
+ rc_dev->s_idle(rc_dev, true);
+
+ return 0;
+}
+
+static void spacemit_ir_set_idle(struct rc_dev *rc_dev, bool idle)
+{
+ struct spacemit_ir *ir = rc_dev->priv;
+ writel(idle, ir->base + SPACEMIT_IR_IDSTATE);
+}
+
+static int spacemit_ir_hw_init(struct device *dev)
+{
+ struct spacemit_ir *ir = dev_get_drvdata(dev);
+ int ret;
+
+#if 0
+#ifndef CONFIG_SOC_SPACEMIT_K1X
+ ret = reset_control_deassert(ir->rst);
+ if(ret)
+ goto disable_apb_clk;
+#endif
+
+ ret = clk_prepare_enable(ir->clk);
+ if(ret){
+ dev_err(dev,"failed to enable ir clk\n");
+#ifdef CONFIG_SOC_SPACEMIT_K1X
+ goto exit;
+#endif
+ }
+#endif
+
+ spacemit_ir_config(ir->rc);
+ writel(IR_IRQ_ENALL, ir->base + SPACEMIT_IR_INTEN);
+ writel(SPACEMIT_IR_ENABLE, ir->base + SPACEMIT_IRC_EN);
+ return 0;
+
+#if 0
+exit:
+ reset_control_assert(ir->rst);
+disable_apb_clk:
+ clk_disable_unprepare(ir->apb_clk);
+#endif
+
+ return ret;
+}
+
+static void spacemit_ir_hw_exit(struct device *dev)
+{
+ struct spacemit_ir *ir = dev_get_drvdata(dev);
+
+#ifdef CONFIG_SOC_SPACEMIY_K1X
+ clk_disable_unprepare(ir->clk);
+ reset_control_assert(ir->rst);
+#endif
+
+ clk_disable_unprepare(ir->apb_clk);
+}
+
+static int spacemit_ir_probe(struct platform_device *pdev)
+{
+ int ret = 0;
+ struct device *dev = &pdev->dev;
+ struct device_node *dn = dev->of_node;
+#if 0
+ u32 ir_clk;
+#endif
+ struct spacemit_ir *ir;
+
+ ir = devm_kzalloc(dev, sizeof(struct spacemit_ir), GFP_KERNEL);
+ if (!ir)
+ return -ENOMEM;
+
+#if 0
+ ir->clk = devm_clk_get(dev, "ir");
+ if (IS_ERR(ir->clk)) {
+ dev_err(dev, "failed to get a ir clock.\n");
+ return PTR_ERR(ir->clk);
+ }
+#ifndef CONFIG_SOC_SPACEMIT_K1X
+ ir->rst = devm_reset_control_get_exclusive(dev, NULL);
+ if (IS_ERR(ir->rst))
+ return PTR_ERR(ir->rst);
+#endif
+
+ /* Base clock frequency (optional) */
+ of_property_read_u32(dn, "clock-frequency", &ir_clk);
+
+ ret = clk_set_rate(ir->clk, ir_clk);
+ if(ret){
+ dev_err(dev,"set ir base clock failed!\n");
+ return ret;
+ }
+ dev_dbg(dev, "set base clock frequency to %d Hz.\n", ir_clk);
+#endif
+
+ ir->base = devm_platform_ioremap_resource(pdev,0);
+ if(IS_ERR(ir->base)){
+ return PTR_ERR(ir->base);
+ }
+
+ ir->rc = rc_allocate_device(RC_DRIVER_IR_RAW);
+ if (!ir->rc) {
+ dev_err(dev, "failed to allocate device\n");
+ return -ENOMEM;
+ }
+
+ ir->rc->priv = ir;
+ ir->rc->device_name = SPACEMIT_IR_DEV;
+ ir->rc->input_phys = "spacemit-ir/input0";
+ ir->rc->input_id.bustype = BUS_HOST;
+ ir->rc->input_id.vendor = 0x0001;
+ ir->rc->input_id.product = 0x0001;
+ ir->rc->input_id.version = 0x0100;
+ ir->map_name = of_get_property(dn, "linux,rc-map-name", NULL);
+ ir->rc->map_name = ir->map_name ?: RC_MAP_EMPTY;
+ ir->rc->dev.parent = dev;
+ ir->rc->allowed_protocols = RC_PROTO_BIT_ALL_IR_DECODER;
+ ir->rc->rx_resolution = CYCLE_TIME;
+ ir->rc->timeout = SPACEMIT_IR_TIMEOUT;
+ ir->rc->driver_name = SPACEMIT_IR_DEV;
+ ir->rc->s_idle = spacemit_ir_set_idle;
+
+ ret = rc_register_device(ir->rc);
+ if (ret) {
+ dev_err(dev, "failed to register rc device\n");
+ goto free_dev;
+ }
+
+ platform_set_drvdata(pdev, ir);
+
+ ir->irq = platform_get_irq(pdev, 0);
+ if (ir->irq < 0) {
+ ret = ir->irq;
+ goto free_dev;
+ }
+
+ ret = devm_request_irq(dev, ir->irq, spacemit_ir_irq, 0, SPACEMIT_IR_DEV, ir);
+ if (ret) {
+ dev_err(dev, "failed request irq\n");
+ goto free_dev;
+ }
+
+ ret = spacemit_ir_hw_init(dev);
+
+free_dev:
+ rc_free_device(ir->rc);
+
+ return ret;
+}
+
+static int spacemit_ir_remove(struct platform_device *pdev)
+{
+ struct spacemit_ir *ir = platform_get_drvdata(pdev);
+
+ rc_unregister_device(ir->rc);
+ spacemit_ir_hw_exit(&pdev->dev);
+
+ return 0;
+}
+
+static void spacemit_ir_shutdown(struct platform_device *pdev)
+{
+ spacemit_ir_hw_exit(&pdev->dev);
+}
+
+static int __maybe_unused spacemit_ir_suspend(struct device *dev)
+{
+ spacemit_ir_hw_exit(dev);
+ return 0;
+}
+
+static int __maybe_unused spacemit_ir_resume(struct device *dev)
+{
+ return spacemit_ir_hw_init(dev);
+}
+
+static SIMPLE_DEV_PM_OPS(spacemit_ir_pm_ops, spacemit_ir_suspend, spacemit_ir_resume);
+
+static const struct spacemit_ir_data spacemit_k1x_ir_data = {
+ .fifo_size = 32,
+};
+
+static const struct spacemit_ir_data spacemit_k1pro_ir_data = {
+ .fifo_size = 32,
+};
+
+static const struct of_device_id spacemit_ir_match[] = {
+ {
+ .compatible = "spacemit,irc",
+ .data = &spacemit_k1x_ir_data,
+ },
+};
+
+static struct platform_driver spacemit_ir_driver = {
+ .probe = spacemit_ir_probe,
+ .remove = spacemit_ir_remove,
+ .shutdown = spacemit_ir_shutdown,
+ .driver = {
+ .name = SPACEMIT_IR_DEV,
+ .of_match_table = spacemit_ir_match,
+ .pm = &spacemit_ir_pm_ops,
+ },
+};
+
+module_platform_driver(spacemit_ir_driver);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Spacemit");
\ No newline at end of file
--
Armbian

View File

@@ -1,310 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Patrick Yavitz <pyavitz@armbian.com>
Date: Fri, 21 Jun 2024 11:54:06 -0400
Subject: add spacemit patch set
source: https://gitee.com/bianbu-linux/linux-6.1
Signed-off-by: Patrick Yavitz <pyavitz@armbian.com>
---
drivers/mfd/Kconfig | 10 +
drivers/mfd/Makefile | 1 +
drivers/mfd/spacemit-mfd.c | 257 ++++++++++
3 files changed, 268 insertions(+)
diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig
index 111111111111..222222222222 100644
--- a/drivers/mfd/Kconfig
+++ b/drivers/mfd/Kconfig
@@ -2166,6 +2166,16 @@ config MFD_QCOM_PM8008
under it in the device tree. Additional drivers must be enabled in
order to use the functionality of the device.
+config MFD_SPACEMIT_PMIC
+ tristate "Spacemit Power Management IC"
+ depends on I2C && OF
+ depends on SOC_SPACEMIT
+ select MFD_CORE
+ select REGMAP_I2C
+ select REGMAP_IRQ
+ help
+ Select this option to get support for the SPACEMIT Power Management ICs.
+
menu "Multimedia Capabilities Port drivers"
depends on ARCH_SA1100
diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile
index 111111111111..222222222222 100644
--- a/drivers/mfd/Makefile
+++ b/drivers/mfd/Makefile
@@ -280,3 +280,4 @@ rsmu-i2c-objs := rsmu_core.o rsmu_i2c.o
rsmu-spi-objs := rsmu_core.o rsmu_spi.o
obj-$(CONFIG_MFD_RSMU_I2C) += rsmu-i2c.o
obj-$(CONFIG_MFD_RSMU_SPI) += rsmu-spi.o
+obj-$(CONFIG_MFD_SPACEMIT_PMIC) += spacemit-mfd.o
diff --git a/drivers/mfd/spacemit-mfd.c b/drivers/mfd/spacemit-mfd.c
new file mode 100644
index 000000000000..111111111111
--- /dev/null
+++ b/drivers/mfd/spacemit-mfd.c
@@ -0,0 +1,257 @@
+// SPDX-License-Identifier: GPL-2.0-only
+
+#include <linux/i2c.h>
+#include <linux/interrupt.h>
+#include <linux/mfd/core.h>
+#include <linux/module.h>
+#include <linux/of_device.h>
+#include <linux/regmap.h>
+#include <linux/reboot.h>
+#include <linux/ioport.h>
+#include <linux/pm_wakeirq.h>
+#include <linux/mfd/spacemit/spacemit_pmic.h>
+
+SPM8821_REGMAP_CONFIG;
+SPM8821_IRQS_DESC;
+SPM8821_IRQ_CHIP_DESC;
+SPM8821_POWER_KEY_RESOURCES_DESC;
+SPM8821_RTC_RESOURCES_DESC;
+SPM8821_MFD_CELL;
+SPM8821_MFD_MATCH_DATA;
+
+PM853_MFD_CELL;
+PM853_REGMAP_CONFIG;
+PM853_MFD_MATCH_DATA;
+
+SY8810L_MFD_CELL;
+SY8810L_REGMAP_CONFIG;
+SY8810L_MFD_MATCH_DATA;
+
+struct restart_config_info
+{
+ const char *cmd_para;
+ uint32_t value;
+};
+
+static const struct restart_config_info config_info[] = {
+ // enter uboot fastboot mode after restart
+ {"fastboot", 1},
+ // enter uboot shell after restart
+ {"uboot", 2},
+};
+
+static const struct of_device_id spacemit_pmic_of_match[] = {
+ { .compatible = "spacemit,spm8821" , .data = (void *)&spm8821_mfd_match_data },
+ { .compatible = "spacemit,pm853" , .data = (void *)&pm853_mfd_match_data },
+ { .compatible = "spacemit,sy8810l" , .data = (void *)&sy8810l_mfd_match_data },
+ { },
+};
+MODULE_DEVICE_TABLE(of, spacemit_pmic_of_match);
+
+struct mfd_match_data *match_data;
+
+static void spacemit_pm_power_off(void)
+{
+ int ret;
+ struct spacemit_pmic *pmic = (struct spacemit_pmic *)match_data->ptr;
+
+ ret = regmap_update_bits(pmic->regmap, match_data->shutdown.reg,
+ match_data->shutdown.bit, match_data->shutdown.bit);
+ if (ret) {
+ pr_err("Failed to shutdown device!\n");
+ }
+
+ while (1) {
+ asm volatile ("wfi");
+ }
+
+ return;
+}
+
+static int spacemit_restart_notify(struct notifier_block *this, unsigned long mode, void *cmd)
+{
+ int i, ret;
+ struct spacemit_pmic *pmic = (struct spacemit_pmic *)match_data->ptr;
+
+ if (NULL != cmd) {
+ for (i = 0; i < ARRAY_SIZE(config_info); i++) {
+ if (0 == strcmp(cmd, config_info[i].cmd_para)) {
+ regmap_update_bits(pmic->regmap, match_data->non_reset.reg,
+ match_data->non_reset.bit, config_info[i].value);
+ break;
+ }
+ }
+ }
+
+ ret = regmap_update_bits(pmic->regmap, match_data->reboot.reg,
+ match_data->reboot.bit, match_data->reboot.bit);
+ if (ret) {
+ pr_err("Failed to reboot device!\n");
+ }
+
+ while (1) {
+ asm volatile ("wfi");
+ }
+
+ return NOTIFY_DONE;
+}
+
+static struct notifier_block spacemit_restart_handler = {
+ .notifier_call = spacemit_restart_notify,
+ .priority = 0,
+};
+
+static int spacemit_prepare_sub_pmic(struct spacemit_pmic *pmic)
+{
+ struct i2c_client *client = pmic->i2c;
+ struct spacemit_sub_pmic *sub = pmic->sub;
+
+ sub->power_page_addr = pmic->i2c->addr + 1;
+
+ sub->power_page = i2c_new_dummy_device(client->adapter,
+ sub->power_page_addr);
+ if (sub->power_page == NULL)
+ return -ENODEV;
+
+ sub->power_regmap = devm_regmap_init_i2c(sub->power_page,
+ pmic->regmap_cfg);
+ if (IS_ERR(sub->power_regmap))
+ return PTR_ERR(sub->power_regmap);
+
+ regcache_cache_bypass(sub->power_regmap, true);
+
+ i2c_set_clientdata(sub->power_page, pmic);
+
+ return 0;
+}
+
+static int spacemit_pmic_probe(struct i2c_client *client,
+ const struct i2c_device_id *id)
+{
+ int ret;
+ int nr_cells;
+ struct device_node *np;
+ struct spacemit_pmic *pmic;
+ const struct mfd_cell *cells;
+ const struct of_device_id *of_id;
+
+ pmic = devm_kzalloc(&client->dev, sizeof(*pmic), GFP_KERNEL);
+ if (!pmic) {
+ pr_err("%s:%d, err\n", __func__, __LINE__);
+ return -ENOMEM;
+ }
+
+ of_id = of_match_device(client->dev.driver->of_match_table, &client->dev);
+ if (!of_id) {
+ pr_err("Unable to match OF ID\n");
+ return -ENODEV;
+ }
+
+ /* find the property in device node */
+ np = of_find_compatible_node(NULL, NULL, of_id->compatible);
+ if (!np)
+ return 0;
+
+ of_node_put(np);
+
+ match_data = (struct mfd_match_data *)of_id->data;
+ match_data->ptr = (void *)pmic;
+
+ pmic->regmap_cfg = match_data->regmap_cfg;
+ pmic->regmap_irq_chip = match_data->regmap_irq_chip;
+ cells = match_data->mfd_cells;
+ nr_cells = match_data->nr_cells;
+
+ if (strcmp(match_data->name, "pm853") == 0) {
+ pmic->sub = devm_kzalloc(&client->dev, sizeof(struct spacemit_sub_pmic), GFP_KERNEL);
+ if (!pmic->sub)
+ return -ENOMEM;
+
+ }
+
+ pmic->i2c = client;
+
+ i2c_set_clientdata(client, pmic);
+
+ pmic->regmap = devm_regmap_init_i2c(client, pmic->regmap_cfg);
+ if (IS_ERR(pmic->regmap)) {
+ pr_err("%s:%d, regmap initialization failed\n",
+ __func__, __LINE__);
+ return PTR_ERR(pmic->regmap);
+ }
+
+ regcache_cache_bypass(pmic->regmap, true);
+
+ /* prepare sub pmic */
+ if (pmic->sub) {
+ ret = spacemit_prepare_sub_pmic(pmic);
+ if (ret < 0) {
+ pr_err("failed to prepare sub pmic %d\n", ret);
+ return ret;
+ }
+ }
+
+ if (!client->irq) {
+ pr_warn("%s:%d, No interrupt supported\n",
+ __func__, __LINE__);
+ } else {
+ if (pmic->regmap_irq_chip) {
+ ret = regmap_add_irq_chip(pmic->regmap, client->irq, IRQF_ONESHOT, -1,
+ pmic->regmap_irq_chip, &pmic->irq_data);
+ if (ret) {
+ pr_err("failed to add irqchip %d\n", ret);
+ return ret;
+ }
+ }
+
+ dev_pm_set_wake_irq(&client->dev, client->irq);
+ device_init_wakeup(&client->dev, true);
+ }
+
+ ret = devm_mfd_add_devices(&client->dev, PLATFORM_DEVID_NONE,
+ cells, nr_cells, NULL, 0,
+ regmap_irq_get_domain(pmic->irq_data));
+ if (ret) {
+ pr_err("failed to add MFD devices %d\n", ret);
+ return -EINVAL;
+ }
+
+ if (match_data->shutdown.reg)
+ pm_power_off = spacemit_pm_power_off;
+
+ if (match_data->reboot.reg) {
+ ret = register_restart_handler(&spacemit_restart_handler);
+ if (ret)
+ pr_warn("failed to register rst handler, %d\n", ret);
+ }
+
+ return 0;
+}
+
+static void spacemit_pmic_remove(struct i2c_client *client)
+{
+ /* !TODO */
+}
+
+static void spacemit_pmic_shutdown(struct i2c_client *client)
+{
+ /* !TODO */
+}
+
+static struct i2c_driver spacemit_pmic_i2c_driver = {
+ .driver = {
+ .name = "spacemit-pmic",
+ .of_match_table = spacemit_pmic_of_match,
+ },
+ .probe = spacemit_pmic_probe,
+ .remove = spacemit_pmic_remove,
+ .shutdown = spacemit_pmic_shutdown,
+};
+
+static int spacemit_mfd_init(void)
+{
+ return i2c_add_driver(&spacemit_pmic_i2c_driver);
+}
+subsys_initcall(spacemit_mfd_init);
+
+MODULE_LICENSE("GPL");
--
Armbian

View File

@@ -1,878 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Patrick Yavitz <pyavitz@armbian.com>
Date: Fri, 21 Jun 2024 11:54:06 -0400
Subject: add spacemit patch set
source: https://gitee.com/bianbu-linux/linux-6.1
Signed-off-by: Patrick Yavitz <pyavitz@armbian.com>
---
drivers/misc/Kconfig | 7 +++++++
drivers/misc/Makefile | 1 +
2 files changed, 8 insertions(+)
diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig
index 111111111111..222222222222 100644
--- a/drivers/misc/Kconfig
+++ b/drivers/misc/Kconfig
@@ -497,6 +497,13 @@ config VCPU_STALL_DETECTOR
If you do not intend to run this kernel as a guest, say N.
+config SPACEMIT_TCM
+ bool "Generic tcm alloc management driver"
+ depends on SOC_SPACEMIT
+ default y
+ help
+ This driver allows you to alloc tcm for userspace.
+
source "drivers/misc/c2port/Kconfig"
source "drivers/misc/eeprom/Kconfig"
source "drivers/misc/cb710/Kconfig"
diff --git a/drivers/misc/Makefile b/drivers/misc/Makefile
index 111111111111..222222222222 100644
--- a/drivers/misc/Makefile
+++ b/drivers/misc/Makefile
@@ -62,3 +62,4 @@ obj-$(CONFIG_HI6421V600_IRQ) += hi6421v600-irq.o
obj-$(CONFIG_OPEN_DICE) += open-dice.o
obj-$(CONFIG_GP_PCI1XXXX) += mchp_pci1xxxx/
obj-$(CONFIG_VCPU_STALL_DETECTOR) += vcpu_stall_detector.o
+obj-$(CONFIG_SPACEMIT_TCM) += tcm.o
--
Armbian
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Patrick Yavitz <pyavitz@xxxxx.com>
Date: Sat, 22 Jun 2024 08:06:33 -0400
Subject: drivers: misc: eeprom: at24.c
Signed-off-by: Patrick Yavitz <pyavitz@xxxxx.com>
---
drivers/misc/eeprom/at24.c | 49 +-
drivers/misc/tcm.c | 674 ++++++++++
2 files changed, 693 insertions(+), 30 deletions(-)
diff --git a/drivers/misc/eeprom/at24.c b/drivers/misc/eeprom/at24.c
index 111111111111..222222222222 100644
--- a/drivers/misc/eeprom/at24.c
+++ b/drivers/misc/eeprom/at24.c
@@ -433,7 +433,8 @@ static int at24_read(void *priv, unsigned int off, void *val, size_t count)
ret = pm_runtime_get_sync(dev);
if (ret < 0) {
- pm_runtime_put_noidle(dev);
+ pm_runtime_mark_last_busy(dev);
+ pm_runtime_put_autosuspend(dev);
return ret;
}
@@ -447,14 +448,16 @@ static int at24_read(void *priv, unsigned int off, void *val, size_t count)
ret = at24_regmap_read(at24, buf + i, off + i, count);
if (ret < 0) {
mutex_unlock(&at24->lock);
- pm_runtime_put(dev);
+ pm_runtime_mark_last_busy(dev);
+ pm_runtime_put_autosuspend(dev);
return ret;
}
}
mutex_unlock(&at24->lock);
- pm_runtime_put(dev);
+ pm_runtime_mark_last_busy(dev);
+ pm_runtime_put_autosuspend(dev);
if (unlikely(at24->read_post))
at24->read_post(off, buf, i);
@@ -480,7 +483,8 @@ static int at24_write(void *priv, unsigned int off, void *val, size_t count)
ret = pm_runtime_get_sync(dev);
if (ret < 0) {
- pm_runtime_put_noidle(dev);
+ pm_runtime_mark_last_busy(dev);
+ pm_runtime_put_autosuspend(dev);
return ret;
}
@@ -494,7 +498,8 @@ static int at24_write(void *priv, unsigned int off, void *val, size_t count)
ret = at24_regmap_write(at24, buf, off, count);
if (ret < 0) {
mutex_unlock(&at24->lock);
- pm_runtime_put(dev);
+ pm_runtime_mark_last_busy(dev);
+ pm_runtime_put_autosuspend(dev);
return ret;
}
buf += ret;
@@ -504,7 +509,8 @@ static int at24_write(void *priv, unsigned int off, void *val, size_t count)
mutex_unlock(&at24->lock);
- pm_runtime_put(dev);
+ pm_runtime_mark_last_busy(dev);
+ pm_runtime_put_autosuspend(dev);
return 0;
}
@@ -716,7 +722,6 @@ static int at24_probe(struct i2c_client *client)
at24->offset_adj = at24_get_offset_adj(flags, byte_len);
at24->client_regmaps[0] = regmap;
- at24->vcc_reg = devm_regulator_get(dev, "vcc");
if (IS_ERR(at24->vcc_reg))
return PTR_ERR(at24->vcc_reg);
@@ -769,17 +774,10 @@ static int at24_probe(struct i2c_client *client)
i2c_set_clientdata(client, at24);
- full_power = acpi_dev_state_d0(&client->dev);
- if (full_power) {
- err = regulator_enable(at24->vcc_reg);
- if (err) {
- dev_err(dev, "Failed to enable vcc regulator\n");
- return err;
- }
-
- pm_runtime_set_active(dev);
- }
+ pm_runtime_use_autosuspend(dev);
+ pm_runtime_set_autosuspend_delay(dev, 10);
pm_runtime_enable(dev);
+ pm_runtime_get_sync(dev);
/*
* Perform a one-byte test read to verify that the chip is functional,
@@ -790,8 +788,6 @@ static int at24_probe(struct i2c_client *client)
err = at24_read(at24, 0, &test_byte, 1);
if (err) {
pm_runtime_disable(dev);
- if (!pm_runtime_status_suspended(dev))
- regulator_disable(at24->vcc_reg);
return -ENODEV;
}
}
@@ -799,8 +795,6 @@ static int at24_probe(struct i2c_client *client)
at24->nvmem = devm_nvmem_register(dev, &nvmem_config);
if (IS_ERR(at24->nvmem)) {
pm_runtime_disable(dev);
- if (!pm_runtime_status_suspended(dev))
- regulator_disable(at24->vcc_reg);
return dev_err_probe(dev, PTR_ERR(at24->nvmem),
"failed to register nvmem\n");
}
@@ -809,7 +803,8 @@ static int at24_probe(struct i2c_client *client)
if (cdata == &at24_data_spd)
at24_probe_temp_sensor(client);
- pm_runtime_idle(dev);
+ pm_runtime_mark_last_busy(dev);
+ pm_runtime_put_autosuspend(dev);
if (writable)
dev_info(dev, "%u byte %s EEPROM, writable, %u bytes/write\n",
@@ -835,18 +830,12 @@ static void at24_remove(struct i2c_client *client)
static int __maybe_unused at24_suspend(struct device *dev)
{
- struct i2c_client *client = to_i2c_client(dev);
- struct at24_data *at24 = i2c_get_clientdata(client);
-
- return regulator_disable(at24->vcc_reg);
+ return 0;
}
static int __maybe_unused at24_resume(struct device *dev)
{
- struct i2c_client *client = to_i2c_client(dev);
- struct at24_data *at24 = i2c_get_clientdata(client);
-
- return regulator_enable(at24->vcc_reg);
+ return 0;
}
static const struct dev_pm_ops at24_pm_ops = {
diff --git a/drivers/misc/tcm.c b/drivers/misc/tcm.c
new file mode 100644
index 000000000000..111111111111
--- /dev/null
+++ b/drivers/misc/tcm.c
@@ -0,0 +1,674 @@
+#include <linux/of_address.h>
+#include <linux/of_device.h>
+#include <linux/platform_device.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/fs.h>
+#include <linux/mm.h>
+#include <linux/miscdevice.h>
+#include <linux/uaccess.h>
+#include <linux/of.h>
+#include <linux/slab.h>
+#include <linux/mutex.h>
+#include <linux/list_sort.h>
+#include <linux/poll.h>
+#include <linux/compat.h>
+#include <linux/random.h>
+
+#define TCM_NAME "tcm"
+
+#define IOC_MAGIC 'c'
+#define TCM_MEM_SHOW _IOR(IOC_MAGIC, 2, int)
+#define TCM_VA_TO_PA _IOR(IOC_MAGIC, 4, int)
+#define TCM_REQUEST_MEM _IOR(IOC_MAGIC, 5, int)
+#define TCM_RELEASE_MEM _IOR(IOC_MAGIC, 6, int)
+
+#define MM_MIN_SHIFT (PAGE_SHIFT) /* 16 bytes */
+#define MM_MIN_CHUNK (1 << MM_MIN_SHIFT)
+#define MM_GRAN_MASK (MM_MIN_CHUNK-1)
+#define MM_ALIGN_UP(a) (((a) + MM_GRAN_MASK) & ~MM_GRAN_MASK)
+#define MM_ALIGN_DOWN(a) ((a) & ~MM_GRAN_MASK)
+#define MM_ALLOC_BIT (0x80000000)
+
+typedef struct {
+ size_t vaddr;
+ size_t size;
+} block_t;
+
+typedef struct {
+ size_t addr_base;
+ int block_num;
+ block_t *block;
+ struct device *dev;
+ struct mutex mutex;
+ wait_queue_head_t wait;
+ struct list_head req_head;
+} tcm_t;
+
+typedef struct {
+ struct list_head list;
+ uintptr_t paddr; /* Phy addr of memory */
+ size_t size; /* Size of this chunk */
+ uintptr_t next_paddr;
+ int block_id;
+ void *caller;
+} mm_node_t;
+
+typedef struct {
+ struct list_head head;
+ size_t max_size;
+} list_manager_t;
+
+typedef struct {
+ size_t mm_heapsize;
+ size_t free_size;
+ uintptr_t start;
+ uintptr_t end;
+ list_manager_t free;
+ list_manager_t alloc;
+} mm_heap_t;
+
+typedef struct {
+ struct list_head list;
+ phys_addr_t paddr;
+ size_t size;
+} mm_alloc_node_t;
+
+typedef struct {
+ struct list_head list;
+ int pid;
+ uint32_t rand_id;
+ size_t req_size;
+ int timeout;
+} request_mem_t;
+
+typedef struct {
+ void *vaddr;
+ void *paddr;
+} va_to_pa_msg_t;
+
+static tcm_t tcm;
+static mm_heap_t *g_mmheap;
+static int g_block_num;
+
+static void add_node(mm_heap_t *heap, list_manager_t *list, mm_node_t *node, char *tip)
+{
+ mm_node_t *cur;
+
+ node->next_paddr = node->paddr + node->size;
+ if (list_empty(&list->head)) {
+ list_add(&node->list, &list->head);
+ dev_dbg(tcm.dev, "[%s] add first node:%lx addr:%lx len:%lx\n", tip, (uintptr_t)node, (uintptr_t)node->paddr, node->size);
+ return;
+ }
+
+ list_for_each_entry(cur, &list->head, list) {
+ if ((size_t)cur->paddr > (size_t)node->paddr ) {
+ list_add_tail(&node->list, &cur->list);
+ dev_dbg(tcm.dev, "[%s] add node:%lx addr:%lx len:%lx\n", tip, (uintptr_t)node, (uintptr_t)node->paddr, node->size);
+ return;
+ }
+ }
+
+ dev_dbg(tcm.dev, "[%s] add tail node:%lx addr:%lx len:%lx\n", tip, (uintptr_t)node, (uintptr_t)node->paddr, node->size);
+
+ list_add_tail(&node->list, &list->head);
+}
+
+static void add_free_node(mm_heap_t *heap, mm_node_t *node)
+{
+ heap->free_size += node->size;
+ add_node(heap, &heap->free, node, "free");
+}
+
+static void del_free_node(mm_heap_t *heap, mm_node_t *node)
+{
+ heap->free_size -= node->size;
+ list_del(&node->list);
+}
+
+static void add_alloc_node(mm_heap_t *heap, mm_node_t *node)
+{
+ add_node(heap, &heap->alloc, node, "alloc");
+}
+
+static void del_alloc_node(mm_heap_t *heap, mm_node_t *node)
+{
+ list_del(&node->list);
+}
+
+static void mm_addregion(mm_heap_t *heap, void *heapstart, size_t heapsize)
+{
+ mm_node_t *node;
+ uintptr_t heapbase;
+ uintptr_t heapend;
+
+ heapbase = MM_ALIGN_UP((uintptr_t)heapstart);
+ heapend = MM_ALIGN_DOWN((uintptr_t)heapstart + (uintptr_t)heapsize);
+ heapsize = heapend - heapbase;
+
+ heap->mm_heapsize += heapsize;
+ heap->start = heapbase;
+ heap->end = heapend;
+
+ node = (mm_node_t *)(kmalloc(sizeof(mm_node_t), GFP_KERNEL));
+ node->paddr = heapbase;
+ node->size = heapsize;
+
+ add_free_node(heap, node);
+ dev_dbg(tcm.dev, "mm init(start:0x%lx)(len:0x%lx)\n", heapbase, heapsize);
+}
+
+static mm_node_t *get_free_max_node(mm_heap_t *heap, size_t size)
+{
+ mm_node_t *node, *max_node;
+
+ max_node = list_first_entry(&heap->free.head, mm_node_t, list);
+ list_for_each_entry(node, &heap->free.head, list) {
+ if (node->size >= size) {
+ max_node = node;
+ break;
+ }
+ if (node->size >= max_node->size) {
+ max_node = node;
+ }
+ }
+
+ return max_node;
+}
+
+static int node_fission(mm_heap_t *heap, mm_node_t *node, size_t size)
+{
+ size_t remaining = node->size - size;
+
+ dev_dbg(tcm.dev, "remaining size:%lx\n", remaining);
+ if (remaining > 0) {
+ mm_node_t *remainder = (mm_node_t *)(kmalloc(sizeof(mm_node_t), GFP_KERNEL));
+ if (!remainder) {
+ return -1;
+ }
+
+ remainder->size = remaining;
+ remainder->paddr = node->paddr + size;
+ node->size = size;
+
+ add_free_node(heap, remainder);
+ }
+
+ del_free_node(heap, node);
+ add_alloc_node(heap, node);
+
+ return 0;
+}
+
+static void *mm_max_mallc(mm_heap_t *heap, size_t size, size_t *valid_size)
+{
+ mm_node_t *node;
+
+ size = MM_ALIGN_UP(size);
+
+ node = get_free_max_node(heap, size);
+
+ dev_dbg(tcm.dev, "\n%s node:(%lx)(%lx)(%lx)\n", __func__, (uintptr_t)node, (uintptr_t)node->paddr, node->size);
+
+ if (size <= node->size) {
+ node_fission(heap, node, size);
+ *valid_size = size;
+ } else {
+ node_fission(heap, node, node->size);
+ *valid_size = node->size;
+ }
+
+ return (void *)node->paddr;
+}
+
+static mm_node_t *get_node_by_ptr(mm_heap_t *heap, void *mem)
+{
+ mm_node_t *node;
+
+ list_for_each_entry(node, &heap->alloc.head, list) {
+ if ((size_t)node->paddr == (size_t)mem) {
+ return node;
+ }
+ }
+
+ return NULL;
+}
+
+static void mm_free(mm_heap_t *heap, void *mem)
+{
+ mm_node_t *cur, *next, *node;
+ int gc_flag = 0;
+
+ node = get_node_by_ptr(heap, mem);
+ if (!node) return;
+
+ dev_dbg(tcm.dev, "%s node:(%lx)(%lx)(%lx)\n", __func__, (uintptr_t)node, (uintptr_t)node->paddr, node->size);
+
+ del_alloc_node(heap, node);
+
+ list_for_each_entry_safe(cur, next, &heap->free.head, list) {
+ if (cur->next_paddr == (size_t)node->paddr) {
+ cur->size += node->size;
+ gc_flag |= 1;
+
+ dev_dbg(tcm.dev, "gc prev succful(%lx)(%lx)(%lx)\n", (uintptr_t)cur, (uintptr_t)cur->paddr, cur->size);
+ if (!list_is_last(&cur->list, &heap->free.head)) {
+ if (cur->next_paddr == (size_t)next->paddr) {
+ cur->size += next->size;
+ gc_flag |= 2;
+ dev_dbg(tcm.dev, "gc 2 next succful(%lx)(%lx)(%lx)\n", (uintptr_t)cur, (uintptr_t)cur->paddr, cur->size);
+ list_del(&next->list);
+ kfree(next);
+ }
+ }
+ break;
+ }
+
+ if (node->next_paddr == (size_t)cur->paddr) {
+ cur->paddr = node->paddr;
+ cur->size += node->size;
+ gc_flag |= 2;
+ dev_dbg(tcm.dev, "gc next succful(%lx)(%lx)(%lx)\n", (uintptr_t)cur, (uintptr_t)cur->paddr, cur->size);
+ break;;
+ }
+ }
+
+ if (gc_flag == 0) {
+ add_free_node(heap, node);
+ } else {
+ kfree(node);
+ }
+}
+
+static void mm_show(mm_heap_t *heap)
+{
+ mm_node_t *node;
+ int i = 0;
+
+ printk("%s start\n", __func__);
+ list_for_each_entry(node, &heap->free.head, list) {
+ printk("mem free node[%d]: %lx paddr: %lx size:0x%lx\n",
+ i ++, (uintptr_t)node, (uintptr_t)node->paddr, node->size);
+ }
+
+ i = 0;
+ list_for_each_entry(node, &heap->alloc.head, list) {
+ printk("mem alloc node[%d]: %lx paddr: %lx size:0x%lx\n",
+ i ++, (uintptr_t)node, (uintptr_t)node->paddr, node->size);
+ }
+
+ printk("%s end\n", __func__);
+}
+
+static int get_id(uintptr_t ptr)
+{
+ int i;
+ for (i = 0; i < g_block_num; i++) {
+ if (ptr >= g_mmheap[i].start && ptr < g_mmheap[i].end){
+ return i;
+ }
+ }
+ return -1;
+}
+
+static void tcm_free(void *ptr)
+{
+ int id = get_id((uintptr_t)ptr);
+ if (id < 0) {
+ return;
+ }
+ mm_free(&g_mmheap[id], ptr);
+}
+
+static size_t total_free_size(void)
+{
+ int i;
+ size_t total = 0;
+
+ for (i = 0; i < g_block_num; i++) {
+ total += g_mmheap[i].free_size;
+ }
+
+ return total;
+}
+
+static struct list_head *tcm_discontinuous_malloc(size_t size)
+{
+ struct list_head *head;
+ int i, remain;
+ size_t total;
+
+ total = total_free_size();
+ if (total < size) return NULL;
+
+ head = kmalloc(sizeof(struct list_head), GFP_KERNEL);
+ if (!head) return NULL;
+
+ INIT_LIST_HEAD(head);
+ remain = size;
+
+ for (i = 0; i < g_block_num; i++) {
+ while (g_mmheap[i].free_size) {
+ mm_alloc_node_t *alloc = kmalloc(sizeof(mm_alloc_node_t), GFP_KERNEL);
+ alloc->paddr = (phys_addr_t)mm_max_mallc(&g_mmheap[i], remain, &alloc->size);
+ list_add(&alloc->list, head);
+ remain -= alloc->size;
+ if (remain <= 0) {
+ break;
+ }
+ }
+ if (remain <= 0) {
+ break;
+ }
+ }
+
+ return head;
+}
+
+static int mm_init(mm_heap_t *heap, size_t start, size_t end)
+{
+ memset(heap, 0, sizeof(mm_heap_t));
+
+ INIT_LIST_HEAD(&heap->free.head);
+ INIT_LIST_HEAD(&heap->alloc.head);
+
+ mm_addregion(heap, (void *)start, end - start);
+
+ return 0;
+}
+
+static void *tcm_match_pa(unsigned long vaddr)
+{
+ // TODO
+ struct vm_area_struct *vma;
+ mm_alloc_node_t *node;
+ struct list_head *head;
+
+ vma = find_vma(current->mm, vaddr);
+ if (!vma) {
+ return NULL;
+ }
+
+ head = (struct list_head *)vma->vm_private_data;
+ list_for_each_entry(node, head, list) {
+ return (void *)node->paddr;
+ }
+
+ return NULL;
+}
+
+static request_mem_t *get_req_mem_node(int pid)
+{
+ request_mem_t *cur;
+
+ list_for_each_entry(cur, &tcm.req_head, list) {
+ if (pid == cur->pid) {
+ return cur;
+ }
+ }
+
+ return NULL;
+}
+
+static int del_req_mem_node(request_mem_t *node)
+{
+ mutex_lock(&tcm.mutex);
+ list_add_tail(&node->list, &tcm.req_head);
+ mutex_unlock(&tcm.mutex);
+
+ return 0;
+}
+
+static int add_req_mem_node(request_mem_t *node)
+{
+ mutex_lock(&tcm.mutex);
+ list_add_tail(&node->list, &tcm.req_head);
+ mutex_unlock(&tcm.mutex);
+
+ return 0;
+}
+
+static void tcm_vma_close(struct vm_area_struct *vma)
+{
+ mm_alloc_node_t *cur, *next;
+ struct list_head *head = (struct list_head *)vma->vm_private_data;
+
+ list_for_each_entry_safe(cur, next, head, list) {
+ tcm_free((void *)cur->paddr);
+ list_del(&cur->list);
+ kfree(cur);
+ }
+ kfree(head);
+ dev_dbg(tcm.dev, "wake up block thread");
+ wake_up_all(&tcm.wait);
+}
+
+static const struct vm_operations_struct tcm_vm_ops = {
+ .close = tcm_vma_close,
+};
+
+static int mmap_compare(void* priv, const struct list_head* a, const struct list_head* b)
+{
+ mm_alloc_node_t* da = list_entry(a, mm_alloc_node_t, list);
+ mm_alloc_node_t* db = list_entry(b, mm_alloc_node_t, list);
+
+ return ((size_t)da->paddr > (size_t)db->paddr) ? 1 : (((size_t)da->paddr < (size_t)db->paddr) ? -1 : 0);
+}
+
+static int tcm_mmap(struct file *file, struct vm_area_struct *vma)
+{
+ size_t size = vma->vm_end - vma->vm_start;
+ phys_addr_t offset = (phys_addr_t)vma->vm_pgoff << PAGE_SHIFT;
+ struct page* page = NULL;
+ unsigned long pfn;
+ unsigned long addr;
+ struct list_head *head;
+ mm_alloc_node_t *node;
+
+ /* Does it even fit in phys_addr_t? */
+ if (offset >> PAGE_SHIFT != vma->vm_pgoff)
+ return -EINVAL;
+
+ vma->vm_ops = &tcm_vm_ops;
+
+ mutex_lock(&tcm.mutex);
+ head = tcm_discontinuous_malloc(size);
+ mutex_unlock(&tcm.mutex);
+
+ if (!head) {
+ return -EINVAL;
+ }
+
+ list_sort(NULL, head, mmap_compare);
+
+ vma->vm_private_data = head;
+ addr = vma->vm_start;
+
+ list_for_each_entry(node, head, list) {
+ pfn = node->paddr >> PAGE_SHIFT;
+ page = phys_to_page(node->paddr);
+ if (!page) {
+ return -ENXIO;
+ }
+ if (remap_pfn_range(vma,
+ addr,
+ pfn,
+ node->size,
+ vma->vm_page_prot)) {
+ return -EAGAIN;
+ }
+ addr += node->size;
+ }
+
+ return 0;
+}
+
+static long tcm_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
+{
+ if (cmd == TCM_MEM_SHOW) {
+ int i = 0;
+ for (; i < g_block_num; i++) {
+ printk("mem block id(%d):\n", i);
+ mm_show(&g_mmheap[i]);
+ }
+ }else if (cmd == TCM_VA_TO_PA) {
+ va_to_pa_msg_t msg;
+
+ if(copy_from_user(&msg, (void *)arg, sizeof(va_to_pa_msg_t))) {
+ return -EFAULT;
+ }
+
+ msg.paddr = tcm_match_pa((unsigned long)msg.vaddr);
+
+ if(copy_to_user((void *)arg, &msg, sizeof(va_to_pa_msg_t))) {
+ return -EFAULT;
+ }
+ } else if (cmd == TCM_REQUEST_MEM) {
+ size_t size;
+ request_mem_t *node;
+
+ if(copy_from_user(&size, (void *)arg, sizeof(size_t))) {
+ return -EFAULT;
+ }
+
+ node = kmalloc(sizeof(request_mem_t), GFP_KERNEL);
+ if (!node) return -ENOMEM;
+
+ node->pid = task_pid_nr(current);
+ node->req_size = size;
+ add_req_mem_node(node);
+ } else if (cmd == TCM_RELEASE_MEM) {
+ size_t size;
+ request_mem_t *node;
+ if(copy_from_user(&size, (void *)arg, sizeof(size_t))) {
+ return -EFAULT;
+ }
+ node = get_req_mem_node(task_pid_nr(current));
+ if (node) del_req_mem_node(node);
+ }
+
+ return 0;
+}
+
+static unsigned int tcm_poll(struct file *file, poll_table *wait)
+{
+ __poll_t mask = 0;
+
+ request_mem_t *node = get_req_mem_node(task_pid_nr(current));
+ dev_dbg(tcm.dev, "poll get node(%lx)\n", (size_t)node);
+
+ if (node == NULL) {
+ mask = EPOLLERR;
+ } else {
+ poll_wait(file, &tcm.wait, wait);
+ if (total_free_size() >= node->req_size) {
+ mask = EPOLLIN;
+ }
+ }
+
+ return mask;
+}
+
+static const struct file_operations tcm_fops = {
+ .owner = THIS_MODULE,
+ .mmap = tcm_mmap,
+ .unlocked_ioctl = tcm_ioctl,
+ .poll = tcm_poll,
+};
+
+static struct miscdevice tcm_misc_device = {
+ .minor = MISC_DYNAMIC_MINOR,
+ .name = TCM_NAME,
+ .fops = &tcm_fops,
+};
+
+static const struct of_device_id tcm_dt_ids[] = {
+ { .compatible = "spacemit,k1-pro-tcm", .data = NULL },
+ { .compatible = "spacemit,k1-x-tcm", .data = NULL },
+ {}
+};
+
+static int tcm_probe(struct platform_device *pdev)
+{
+ struct resource *res;
+ int ret, num;
+ struct device_node *np, *child;
+
+ tcm.dev = &pdev->dev;
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ if (!res) {
+ dev_err(tcm.dev, "found no memory resource\n");
+ return -EINVAL;
+ }
+
+ np = tcm.dev->of_node;
+ num = (np) ? of_get_available_child_count(np) + 1 : 1;
+
+ dev_dbg(tcm.dev, "-----------child num:%d\n", num);
+ g_mmheap = kmalloc(sizeof(mm_heap_t)*num, GFP_KERNEL);
+ if (!g_mmheap)
+ return -ENOMEM;
+
+ for_each_available_child_of_node(np, child) {
+ struct resource child_res;
+
+ ret = of_address_to_resource(child, 0, &child_res);
+ if (ret < 0) {
+ dev_err(tcm.dev,
+ "could not get address for node %pOF\n",
+ child);
+ return -EINVAL;
+ }
+
+ if (child_res.start < res->start || child_res.end > res->end) {
+ dev_err(tcm.dev,
+ "reserved block %pOF outside the tcm area\n",
+ child);
+ return -EINVAL;
+ }
+
+ mm_init(&g_mmheap[g_block_num], child_res.start , child_res.start + resource_size(&child_res));
+ g_block_num ++;
+
+ }
+
+ csr_write(0x5db, 1);
+ ret = misc_register(&tcm_misc_device);
+ if (ret) {
+ dev_err(tcm.dev, "failed to register misc device\n");
+ return ret;
+ }
+ mutex_init(&tcm.mutex);
+ init_waitqueue_head(&tcm.wait);
+ INIT_LIST_HEAD(&tcm.req_head);
+ dev_dbg(tcm.dev, "tcm register succfully\n");
+ return 0;
+}
+
+static int tcm_remove(struct platform_device *pdev)
+{
+ dev_dbg(tcm.dev, "tcm deregister succfully\n");
+ csr_write(0x5db, 0);
+ kfree(g_mmheap);
+ misc_deregister(&tcm_misc_device);
+
+ return 0;
+}
+
+static struct platform_driver tcm_driver = {
+ .driver = {
+ .name = TCM_NAME,
+ .of_match_table = tcm_dt_ids,
+ },
+ .probe = tcm_probe,
+ .remove = tcm_remove,
+};
+
+static int __init tcm_init(void)
+{
+ return platform_driver_register(&tcm_driver);
+}
+
+module_init(tcm_init);
--
Armbian

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -1,29 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Patrick Yavitz <pyavitz@armbian.com>
Date: Fri, 21 Jun 2024 11:54:06 -0400
Subject: add spacemit patch set
source: https://gitee.com/bianbu-linux/linux-6.1
Signed-off-by: Patrick Yavitz <pyavitz@armbian.com>
---
drivers/nvme/host/core.c | 3 +++
1 file changed, 3 insertions(+)
diff --git a/drivers/nvme/host/core.c b/drivers/nvme/host/core.c
index 111111111111..222222222222 100644
--- a/drivers/nvme/host/core.c
+++ b/drivers/nvme/host/core.c
@@ -1964,6 +1964,9 @@ static void nvme_update_disk_info(struct gendisk *disk,
* value of the Atomic Write Unit Power Fail parameter.
*/
blk_queue_physical_block_size(disk->queue, min(phys_bs, atomic_bs));
+#if defined(CONFIG_SOC_SPACEMIT_K1X)
+ blk_queue_max_segment_size(disk->queue, 0x80000);
+#endif
blk_queue_io_min(disk->queue, phys_bs);
blk_queue_io_opt(disk->queue, io_opt);
--
Armbian

View File

@@ -1,325 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Patrick Yavitz <pyavitz@armbian.com>
Date: Fri, 21 Jun 2024 11:54:06 -0400
Subject: add spacemit patch set
source: https://gitee.com/bianbu-linux/linux-6.1
Signed-off-by: Patrick Yavitz <pyavitz@armbian.com>
---
drivers/phy/Kconfig | 1 +
drivers/phy/Makefile | 1 +
drivers/phy/spacemit/Kconfig | 11 +
drivers/phy/spacemit/Makefile | 2 +
drivers/phy/spacemit/phy-spacemit-k1x-combphy.c | 252 ++++++++++
5 files changed, 267 insertions(+)
diff --git a/drivers/phy/Kconfig b/drivers/phy/Kconfig
index 111111111111..222222222222 100644
--- a/drivers/phy/Kconfig
+++ b/drivers/phy/Kconfig
@@ -96,5 +96,6 @@ source "drivers/phy/tegra/Kconfig"
source "drivers/phy/ti/Kconfig"
source "drivers/phy/intel/Kconfig"
source "drivers/phy/xilinx/Kconfig"
+source "drivers/phy/spacemit/Kconfig"
endmenu
diff --git a/drivers/phy/Makefile b/drivers/phy/Makefile
index 111111111111..222222222222 100644
--- a/drivers/phy/Makefile
+++ b/drivers/phy/Makefile
@@ -30,6 +30,7 @@ obj-y += allwinner/ \
rockchip/ \
samsung/ \
socionext/ \
+ spacemit/ \
st/ \
sunplus/ \
tegra/ \
diff --git a/drivers/phy/spacemit/Kconfig b/drivers/phy/spacemit/Kconfig
new file mode 100644
index 000000000000..111111111111
--- /dev/null
+++ b/drivers/phy/spacemit/Kconfig
@@ -0,0 +1,11 @@
+# SPDX-License-Identifier: GPL-2.0
+#
+# Phy drivers for Spacemit platforms
+#
+config PHY_SPACEMIT_K1X_COMBPHY
+ tristate "Spacemit K1-x USB3&PCIE combo PHY driver"
+ depends on OF
+ select GENERIC_PHY
+ default SOC_SPACEMIT_K1X && USB_DWC3_SPACEMIT
+ help
+ USB3 and PCIE Combo PHY Support for Spacemit k1-x Soc
diff --git a/drivers/phy/spacemit/Makefile b/drivers/phy/spacemit/Makefile
new file mode 100644
index 000000000000..111111111111
--- /dev/null
+++ b/drivers/phy/spacemit/Makefile
@@ -0,0 +1,2 @@
+# SPDX-License-Identifier: GPL-2.0
+obj-$(CONFIG_PHY_SPACEMIT_K1X_COMBPHY) += phy-spacemit-k1x-combphy.o
diff --git a/drivers/phy/spacemit/phy-spacemit-k1x-combphy.c b/drivers/phy/spacemit/phy-spacemit-k1x-combphy.c
new file mode 100644
index 000000000000..111111111111
--- /dev/null
+++ b/drivers/phy/spacemit/phy-spacemit-k1x-combphy.c
@@ -0,0 +1,252 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * phy-spacemit-k1x-combphy.c - Spacemit k1-x combo PHY for USB3 and PCIE
+ *
+ * Copyright (c) 2023 Spacemit Co., Ltd.
+ *
+ */
+
+#include <dt-bindings/phy/phy.h>
+#include <linux/phy/phy.h>
+#include <linux/platform_device.h>
+#include <linux/of_device.h>
+#include <linux/clk.h>
+#include <linux/reset.h>
+#include <linux/delay.h>
+
+#define SPACEMIT_COMBPHY_WAIT_TIMEOUT 1000
+#define SPACEMIT_COMBPHY_MODE_SEL BIT(3)
+
+// Registers for USB3 PHY
+#define SPACEMIT_COMBPHY_USB_REG1 0x68
+#define SPACEMIT_COMBPHY_USB_REG1_VAL 0x0
+#define SPACEMIT_COMBPHY_USB_REG2 (0x12 << 2)
+#define SPACEMIT_COMBPHY_USB_REG2_VAL 0x603a2276
+#define SPACEMIT_COMBPHY_USB_REG3 (0x02 << 2)
+#define SPACEMIT_COMBPHY_USB_REG3_VAL 0x97c
+#define SPACEMIT_COMBPHY_USB_REG4 (0x06 << 2)
+#define SPACEMIT_COMBPHY_USB_REG4_VAL 0x0
+#define SPACEMIT_COMBPHY_USB_PLL_REG 0x8
+#define SPACEMIT_COMBPHY_USB_PLL_MASK 0x1
+#define SPACEMIT_COMBPHY_USB_PLL_VAL 0x1
+
+struct spacemit_combphy_priv;
+
+struct spacemit_combphy_priv {
+ struct device *dev;
+ int num_clks;
+ struct clk_bulk_data *clks;
+ struct reset_control *phy_rst;
+ void __iomem *phy_sel;
+ void __iomem *puphy_base;
+ struct phy *phy;
+ u8 type;
+};
+
+static inline void spacemit_reg_updatel(void __iomem *reg, u32 offset, u32 mask,
+ u32 val)
+{
+ u32 tmp;
+ tmp = readl(reg + offset);
+ tmp = (tmp & ~(mask)) | val;
+ writel(tmp, reg + offset);
+}
+
+static int spacemit_combphy_wait_ready(struct spacemit_combphy_priv *priv,
+ u32 offset, u32 mask, u32 val)
+{
+ int timeout = SPACEMIT_COMBPHY_WAIT_TIMEOUT;
+ while (((readl(priv->puphy_base + offset) & mask) != val) && --timeout)
+ ;
+ if (!timeout) {
+ return -ETIMEDOUT;
+ }
+ dev_dbg(priv->dev, "phy init timeout remain: %d", timeout);
+ return 0;
+}
+
+static int spacemit_combphy_set_mode(struct spacemit_combphy_priv *priv)
+{
+ u8 mode = priv->type;
+ if (mode == PHY_TYPE_USB3) {
+ spacemit_reg_updatel(priv->phy_sel, 0, 0,
+ SPACEMIT_COMBPHY_MODE_SEL);
+ } else {
+ dev_err(priv->dev, "PHY type %x not supported\n", mode);
+ return -EINVAL;
+ }
+ return 0;
+}
+
+static int spacemit_combphy_init_usb(struct spacemit_combphy_priv *priv)
+{
+ int ret;
+ void __iomem *base = priv->puphy_base;
+ dev_info(priv->dev, "USB3 PHY init.\n");
+
+ writel(SPACEMIT_COMBPHY_USB_REG1_VAL, base + SPACEMIT_COMBPHY_USB_REG1);
+ writel(SPACEMIT_COMBPHY_USB_REG2_VAL, base + SPACEMIT_COMBPHY_USB_REG2);
+ writel(SPACEMIT_COMBPHY_USB_REG3_VAL, base + SPACEMIT_COMBPHY_USB_REG3);
+ writel(SPACEMIT_COMBPHY_USB_REG4_VAL, base + SPACEMIT_COMBPHY_USB_REG4);
+
+ ret = spacemit_combphy_wait_ready(priv, SPACEMIT_COMBPHY_USB_PLL_REG,
+ SPACEMIT_COMBPHY_USB_PLL_MASK,
+ SPACEMIT_COMBPHY_USB_PLL_VAL);
+
+ if (ret)
+ dev_err(priv->dev, "USB3 PHY init timeout!\n");
+
+ return ret;
+}
+
+static int spacemit_combphy_init(struct phy *phy)
+{
+ struct spacemit_combphy_priv *priv = phy_get_drvdata(phy);
+ int ret;
+
+ ret = spacemit_combphy_set_mode(priv);
+
+ if (ret) {
+ dev_err(priv->dev, "failed to set mode for PHY type %x\n",
+ priv->type);
+ goto out;
+ }
+
+ ret = clk_bulk_prepare_enable(priv->num_clks, priv->clks);
+ if (ret) {
+ dev_err(priv->dev, "failed to enable clks\n");
+ goto out;
+ }
+
+ ret = reset_control_deassert(priv->phy_rst);
+ if (ret) {
+ dev_err(priv->dev, "failed to deassert rst\n");
+ goto err_clk;
+ }
+
+ switch (priv->type) {
+ case PHY_TYPE_USB3:
+ ret = spacemit_combphy_init_usb(priv);
+ break;
+ default:
+ dev_err(priv->dev, "PHY type %x not supported\n", priv->type);
+ ret = -EINVAL;
+ break;
+ }
+
+ if (ret)
+ goto err_rst;
+
+ return 0;
+
+err_rst:
+ reset_control_assert(priv->phy_rst);
+err_clk:
+ clk_bulk_disable_unprepare(priv->num_clks, priv->clks);
+out:
+ return ret;
+}
+
+static int spacemit_combphy_exit(struct phy *phy)
+{
+ struct spacemit_combphy_priv *priv = phy_get_drvdata(phy);
+
+ clk_bulk_disable_unprepare(priv->num_clks, priv->clks);
+ reset_control_assert(priv->phy_rst);
+
+ return 0;
+}
+
+static struct phy *spacemit_combphy_xlate(struct device *dev,
+ struct of_phandle_args *args)
+{
+ struct spacemit_combphy_priv *priv = dev_get_drvdata(dev);
+
+ if (args->args_count != 1) {
+ dev_err(dev, "invalid number of arguments\n");
+ return ERR_PTR(-EINVAL);
+ }
+
+ if (priv->type != PHY_NONE && priv->type != args->args[0])
+ dev_warn(dev, "PHY type %d is selected to override %d\n",
+ args->args[0], priv->type);
+
+ priv->type = args->args[0];
+
+ if (args->args_count > 1) {
+ dev_dbg(dev, "combo phy idx: %d selected", args->args[1]);
+ }
+
+ return priv->phy;
+}
+
+static const struct phy_ops spacemit_combphy_ops = {
+ .init = spacemit_combphy_init,
+ .exit = spacemit_combphy_exit,
+ .owner = THIS_MODULE,
+};
+
+static int spacemit_combphy_probe(struct platform_device *pdev)
+{
+ struct phy_provider *phy_provider;
+ struct device *dev = &pdev->dev;
+ struct spacemit_combphy_priv *priv;
+ int ret;
+
+ priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
+ if (!priv)
+ return -ENOMEM;
+
+ priv->puphy_base = devm_platform_ioremap_resource_byname(pdev, "puphy");
+ if (IS_ERR(priv->puphy_base)) {
+ ret = PTR_ERR(priv->puphy_base);
+ return ret;
+ }
+
+ priv->phy_sel = devm_platform_ioremap_resource_byname(pdev, "phy_sel");
+ if (IS_ERR(priv->phy_sel)) {
+ ret = PTR_ERR(priv->phy_sel);
+ return ret;
+ }
+
+ priv->dev = dev;
+ priv->type = PHY_NONE;
+
+ priv->num_clks = devm_clk_bulk_get_all(dev, &priv->clks);
+
+ priv->phy_rst = devm_reset_control_array_get_shared(dev);
+ if (IS_ERR(priv->phy_rst))
+ return dev_err_probe(dev, PTR_ERR(priv->phy_rst),
+ "failed to get phy reset\n");
+
+ priv->phy = devm_phy_create(dev, NULL, &spacemit_combphy_ops);
+ if (IS_ERR(priv->phy)) {
+ dev_err(dev, "failed to create combphy\n");
+ return PTR_ERR(priv->phy);
+ }
+
+ dev_set_drvdata(dev, priv);
+ phy_set_drvdata(priv->phy, priv);
+
+ phy_provider =
+ devm_of_phy_provider_register(dev, spacemit_combphy_xlate);
+
+ return PTR_ERR_OR_ZERO(phy_provider);
+}
+
+static const struct of_device_id spacemit_combphy_of_match[] = {
+ {
+ .compatible = "spacemit,k1x-combphy",
+ },
+ {},
+};
+MODULE_DEVICE_TABLE(of, spacemit_combphy_of_match);
+
+static struct platform_driver spacemit_combphy_driver = {
+ .probe = spacemit_combphy_probe,
+ .driver = {
+ .name = "spacemit-k1x-combphy",
+ .of_match_table = spacemit_combphy_of_match,
+ },
+};
+module_platform_driver(spacemit_combphy_driver);
--
Armbian

File diff suppressed because it is too large Load Diff

View File

@@ -1,198 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Patrick Yavitz <pyavitz@armbian.com>
Date: Fri, 21 Jun 2024 11:54:06 -0400
Subject: add spacemit patch set
source: https://gitee.com/bianbu-linux/linux-6.1
Signed-off-by: Patrick Yavitz <pyavitz@armbian.com>
---
drivers/pwm/Makefile | 1 +
drivers/pwm/pwm-pxa.c | 98 +++++++++-
2 files changed, 95 insertions(+), 4 deletions(-)
diff --git a/drivers/pwm/Makefile b/drivers/pwm/Makefile
index 111111111111..222222222222 100644
--- a/drivers/pwm/Makefile
+++ b/drivers/pwm/Makefile
@@ -15,6 +15,7 @@ obj-$(CONFIG_PWM_CLPS711X) += pwm-clps711x.o
obj-$(CONFIG_PWM_CRC) += pwm-crc.o
obj-$(CONFIG_PWM_CROS_EC) += pwm-cros-ec.o
obj-$(CONFIG_PWM_DWC) += pwm-dwc.o
+obj-$(CONFIG_PWM_DWC_K1pro) += pwm-dwc-k1pro.o
obj-$(CONFIG_PWM_EP93XX) += pwm-ep93xx.o
obj-$(CONFIG_PWM_FSL_FTM) += pwm-fsl-ftm.o
obj-$(CONFIG_PWM_HIBVT) += pwm-hibvt.o
diff --git a/drivers/pwm/pwm-pxa.c b/drivers/pwm/pwm-pxa.c
index 111111111111..222222222222 100644
--- a/drivers/pwm/pwm-pxa.c
+++ b/drivers/pwm/pwm-pxa.c
@@ -14,6 +14,7 @@
#include <linux/slab.h>
#include <linux/err.h>
#include <linux/clk.h>
+#include <linux/reset.h>
#include <linux/io.h>
#include <linux/pwm.h>
#include <linux/of_device.h>
@@ -45,7 +46,12 @@ struct pxa_pwm_chip {
struct device *dev;
struct clk *clk;
+ struct reset_control *reset;
void __iomem *mmio_base;
+#ifdef CONFIG_SOC_SPACEMIT_K1X
+ int dcr_fd; /* Controller PWM_DCR FD feature */
+ int rcpu_pwm; /* PWM in rcpu domain */
+#endif
};
static inline struct pxa_pwm_chip *to_pxa_pwm_chip(struct pwm_chip *chip)
@@ -82,10 +88,32 @@ static int pxa_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm,
return -EINVAL;
if (duty_ns == period_ns)
+#ifdef CONFIG_SOC_SPACEMIT_K1X
+ {
+ if(pc->dcr_fd)
+ dc = PWMDCR_FD;
+ else{
+ dc = (pv + 1) * duty_ns / period_ns;
+ if (dc >= PWMDCR_FD) {
+ dc = PWMDCR_FD - 1;
+ pv = dc - 1;
+ }
+ }
+ }
+#else
dc = PWMDCR_FD;
+#endif
else
dc = mul_u64_u64_div_u64(pv + 1, duty_ns, period_ns);
+#ifdef CONFIG_SOC_SPACEMIT_K1X
+ /*
+ * FIXME: Graceful shutdown mode would cause the function clock
+ * could not be enabled normally, so chose abrupt shutdown mode.
+ */
+ prescale |= PWMCR_SD;
+#endif
+
/* NOTE: the clock to PWM has to be enabled first
* before writing to the registers
*/
@@ -157,6 +185,9 @@ static const struct of_device_id pwm_of_match[] = {
{ .compatible = "marvell,pxa270-pwm", .data = &pwm_id_table[0]},
{ .compatible = "marvell,pxa168-pwm", .data = &pwm_id_table[0]},
{ .compatible = "marvell,pxa910-pwm", .data = &pwm_id_table[0]},
+#ifdef CONFIG_SOC_SPACEMIT_K1X
+ { .compatible = "spacemit,k1x-pwm", .data = &pwm_id_table[0]},
+#endif
{ }
};
MODULE_DEVICE_TABLE(of, pwm_of_match);
@@ -187,10 +218,32 @@ static int pwm_probe(struct platform_device *pdev)
if (pc == NULL)
return -ENOMEM;
+#ifdef CONFIG_SOC_SPACEMIT_K1X
+ if (pdev->dev.of_node) {
+ if(of_get_property(pdev->dev.of_node, "k1x,pwm-disable-fd", NULL))
+ pc->dcr_fd = 0;
+ else
+ pc->dcr_fd = 1;
+ if(of_get_property(pdev->dev.of_node, "rcpu-pwm", NULL))
+ pc->rcpu_pwm = 1;
+ else
+ pc->rcpu_pwm = 0;
+ }
+ else {
+ pc->dcr_fd = 0;
+ pc->rcpu_pwm = 0;
+ }
+#endif
+
pc->clk = devm_clk_get(&pdev->dev, NULL);
if (IS_ERR(pc->clk))
return PTR_ERR(pc->clk);
+ pc->reset = devm_reset_control_get_optional(&pdev->dev, NULL);
+ if(IS_ERR(pc->reset))
+ return PTR_ERR(pc->reset);
+ reset_control_deassert(pc->reset);
+
pc->chip.dev = &pdev->dev;
pc->chip.ops = &pxa_pwm_ops;
pc->chip.npwm = (id->driver_data & HAS_SECONDARY_PWM) ? 2 : 1;
@@ -201,27 +254,64 @@ static int pwm_probe(struct platform_device *pdev)
}
pc->mmio_base = devm_platform_ioremap_resource(pdev, 0);
- if (IS_ERR(pc->mmio_base))
- return PTR_ERR(pc->mmio_base);
+ if (IS_ERR(pc->mmio_base)) {
+ ret = PTR_ERR(pc->mmio_base);
+ goto err_rst;
+ }
ret = devm_pwmchip_add(&pdev->dev, &pc->chip);
if (ret < 0) {
dev_err(&pdev->dev, "pwmchip_add() failed: %d\n", ret);
- return ret;
+ goto err_rst;
}
+ platform_set_drvdata(pdev, pc);
+
return 0;
+
+err_rst:
+ reset_control_assert(pc->reset);
+ return ret;
}
+#ifdef CONFIG_PM_SLEEP
+static int pxa_pwm_suspend_noirq(struct device *dev)
+{
+ return 0;
+}
+
+static int pxa_pwm_resume_noirq(struct device *dev)
+{
+ struct pxa_pwm_chip *pc = dev_get_drvdata(dev);
+
+ /* if pwm in rcpu domain, deassert reset first before apply the old state */
+ if(pc->rcpu_pwm)
+ reset_control_deassert(pc->reset);
+ return 0;
+}
+#endif
+
+static const struct dev_pm_ops pxa_pwm_pm_qos = {
+ .suspend_noirq = pxa_pwm_suspend_noirq,
+ .resume_noirq = pxa_pwm_resume_noirq,
+};
+
static struct platform_driver pwm_driver = {
.driver = {
.name = "pxa25x-pwm",
+#ifdef CONFIG_PM_SLEEP
+ .pm = &pxa_pwm_pm_qos,
+#endif
.of_match_table = pwm_of_match,
},
.probe = pwm_probe,
.id_table = pwm_id_table,
};
-module_platform_driver(pwm_driver);
+static int k1x_pwm_driver_init(void)
+{
+ return platform_driver_register(&pwm_driver);
+}
+late_initcall_sync(k1x_pwm_driver_init);
MODULE_LICENSE("GPL v2");
--
Armbian

View File

@@ -1,160 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Patrick Yavitz <pyavitz@armbian.com>
Date: Fri, 21 Jun 2024 11:54:06 -0400
Subject: add spacemit patch set
source: https://gitee.com/bianbu-linux/linux-6.1
Signed-off-by: Patrick Yavitz <pyavitz@armbian.com>
---
drivers/regulator/Kconfig | 8 +
drivers/regulator/Makefile | 1 +
drivers/regulator/spacemit-regulator.c | 109 ++++++++++
3 files changed, 118 insertions(+)
diff --git a/drivers/regulator/Kconfig b/drivers/regulator/Kconfig
index 111111111111..222222222222 100644
--- a/drivers/regulator/Kconfig
+++ b/drivers/regulator/Kconfig
@@ -1524,4 +1524,12 @@ config REGULATOR_QCOM_LABIBB
boost regulator and IBB can be used as a negative boost regulator
for LCD display panel.
+config REGULATOR_SPACEMIT
+ tristate "Spacemit regulator support"
+ depends on MFD_SPACEMIT_PMIC
+ select REGULATOR_FIXED_VOLTAGE
+ help
+ This driver provides support for the voltage regulators on the
+ spacemit pmic.
+
endif
diff --git a/drivers/regulator/Makefile b/drivers/regulator/Makefile
index 111111111111..222222222222 100644
--- a/drivers/regulator/Makefile
+++ b/drivers/regulator/Makefile
@@ -182,5 +182,6 @@ obj-$(CONFIG_REGULATOR_WM831X) += wm831x-ldo.o
obj-$(CONFIG_REGULATOR_WM8350) += wm8350-regulator.o
obj-$(CONFIG_REGULATOR_WM8400) += wm8400-regulator.o
obj-$(CONFIG_REGULATOR_WM8994) += wm8994-regulator.o
+obj-$(CONFIG_REGULATOR_SPACEMIT) += spacemit-regulator.o
ccflags-$(CONFIG_REGULATOR_DEBUG) += -DDEBUG
diff --git a/drivers/regulator/spacemit-regulator.c b/drivers/regulator/spacemit-regulator.c
new file mode 100644
index 000000000000..111111111111
--- /dev/null
+++ b/drivers/regulator/spacemit-regulator.c
@@ -0,0 +1,109 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Regulator driver for Spacemit PMIC
+ *
+ * Copyright (c) 2023, SPACEMIT Co., Ltd
+ *
+ */
+
+#include <linux/delay.h>
+#include <linux/gpio.h>
+#include <linux/i2c.h>
+#include <linux/module.h>
+#include <linux/of_device.h>
+#include <linux/of_gpio.h>
+#include <linux/regulator/driver.h>
+#include <linux/regulator/of_regulator.h>
+#include <linux/gpio/consumer.h>
+#include <linux/mfd/spacemit/spacemit_pmic.h>
+
+static const struct regulator_ops pmic_dcdc_ldo_ops = {
+ .list_voltage = regulator_list_voltage_linear_range,
+ .map_voltage = regulator_map_voltage_linear_range,
+ .get_voltage_sel = regulator_get_voltage_sel_regmap,
+ .set_voltage_sel = regulator_set_voltage_sel_regmap,
+ .set_voltage_time_sel = regulator_set_voltage_time_sel,
+ .enable = regulator_enable_regmap,
+ .disable = regulator_disable_regmap,
+ .is_enabled = regulator_is_enabled_regmap,
+};
+
+static const struct regulator_ops pmic_switch_ops = {
+ .enable = regulator_enable_regmap,
+ .disable = regulator_disable_regmap,
+ .is_enabled = regulator_is_enabled_regmap,
+};
+
+SPM8821_BUCK_LINER_RANGE;SPM8821_LDO_LINER_RANGE;SPM8821_REGULATOR_DESC;
+SPM8821_REGULATOR_MATCH_DATA;
+
+PM853_BUCK_LINER_RANGE1;PM853_BUCK_LINER_RANGE2;PM853_LDO_LINER_RANGE1;
+PM853_LDO_LINER_RANGE2;PM853_LDO_LINER_RANGE3;PM853_LDO_LINER_RANGE4;
+PM853_REGULATOR_DESC;PM853_REGULATOR_MATCH_DATA;
+
+SY8810L_BUCK_LINER_RANGE;SY8810L_REGULATOR_DESC;SY8810L_REGULATOR_MATCH_DATA;
+
+static const struct of_device_id spacemit_regulator_of_match[] = {
+ { .compatible = "pmic,regulator,spm8821", .data = (void *)&spm8821_regulator_match_data },
+ { .compatible = "pmic,regulator,pm853", .data = (void *)&pm853_regulator_match_data },
+ { .compatible = "pmic,regulator,sy8810l", .data = (void *)&sy8810l_regulator_match_data },
+ { },
+};
+MODULE_DEVICE_TABLE(of, spacemit_regulator_of_match);
+
+static int spacemit_regulator_probe(struct platform_device *pdev)
+{
+ struct regulator_config config = {};
+ struct spacemit_pmic *pmic = dev_get_drvdata(pdev->dev.parent);
+ struct i2c_client *client;
+ const struct of_device_id *of_id;
+ struct regulator_match_data *match_data;
+ struct regulator_dev *regulator_dev;
+ int i;
+
+ of_id = of_match_device(spacemit_regulator_of_match, &pdev->dev);
+ if (!of_id) {
+ pr_err("Unable to match OF ID\n");
+ return -ENODEV;
+ }
+
+ match_data = (struct regulator_match_data *)of_id->data;
+
+ client = pmic->i2c;
+ config.dev = &client->dev;
+ config.regmap = pmic->regmap;
+
+ if (strcmp(match_data->name, "pm853") == 0) {
+ client = pmic->sub->power_page;
+ config.dev = &pmic->i2c->dev;
+ config.regmap = pmic->sub->power_regmap;
+ }
+
+ for (i = 0; i < match_data->nr_desc; ++i) {
+ regulator_dev = devm_regulator_register(&pdev->dev,
+ match_data->desc + i, &config);
+ if (IS_ERR(regulator_dev)) {
+ pr_err("failed to register %d regulator\n", i);
+ return PTR_ERR(regulator_dev);
+ }
+ }
+
+ return 0;
+}
+
+static struct platform_driver spacemit_regulator_driver = {
+ .probe = spacemit_regulator_probe,
+ .driver = {
+ .name = "spacemit-regulator",
+ .of_match_table = spacemit_regulator_of_match,
+ },
+};
+
+static int spacemit_regulator_init(void)
+{
+ return platform_driver_register(&spacemit_regulator_driver);
+}
+subsys_initcall(spacemit_regulator_init);
+
+MODULE_DESCRIPTION("regulator drivers for the Spacemit series PMICs");
+
--
Armbian

View File

@@ -1,762 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Patrick Yavitz <pyavitz@armbian.com>
Date: Fri, 21 Jun 2024 11:54:06 -0400
Subject: add spacemit patch set
source: https://gitee.com/bianbu-linux/linux-6.1
Signed-off-by: Patrick Yavitz <pyavitz@armbian.com>
---
drivers/remoteproc/Kconfig | 12 +
drivers/remoteproc/Makefile | 2 +
drivers/remoteproc/k1x-rproc.c | 706 ++++++++++
3 files changed, 720 insertions(+)
diff --git a/drivers/remoteproc/Kconfig b/drivers/remoteproc/Kconfig
index 111111111111..222222222222 100644
--- a/drivers/remoteproc/Kconfig
+++ b/drivers/remoteproc/Kconfig
@@ -161,6 +161,18 @@ config PRU_REMOTEPROC
processors on various TI SoCs. It's safe to say N here if you're
not interested in the PRU or if you are unsure.
+config K1PRO_REMOTEPROC
+ tristate "Spacemit k1pro remoteproc support"
+ help
+ Say Y here here to support spacemit remote processors
+ via the remote processor framework.
+
+config K1X_REMOTEPROC
+ tristate "Spacemit k1x remoteproc support"
+ help
+ Say Y here here to support spacemit remote processors
+ via the remote processor framework.
+
config QCOM_PIL_INFO
tristate
diff --git a/drivers/remoteproc/Makefile b/drivers/remoteproc/Makefile
index 111111111111..222222222222 100644
--- a/drivers/remoteproc/Makefile
+++ b/drivers/remoteproc/Makefile
@@ -38,3 +38,5 @@ obj-$(CONFIG_ST_SLIM_REMOTEPROC) += st_slim_rproc.o
obj-$(CONFIG_STM32_RPROC) += stm32_rproc.o
obj-$(CONFIG_TI_K3_DSP_REMOTEPROC) += ti_k3_dsp_remoteproc.o
obj-$(CONFIG_TI_K3_R5_REMOTEPROC) += ti_k3_r5_remoteproc.o
+obj-$(CONFIG_K1PRO_REMOTEPROC) += k1proc-rproc.o
+obj-$(CONFIG_K1X_REMOTEPROC) += k1x-rproc.o
diff --git a/drivers/remoteproc/k1x-rproc.c b/drivers/remoteproc/k1x-rproc.c
new file mode 100644
index 000000000000..111111111111
--- /dev/null
+++ b/drivers/remoteproc/k1x-rproc.c
@@ -0,0 +1,706 @@
+// SPDX-License-Identifier: GPL-2.0
+
+#include <linux/limits.h>
+#include <linux/module.h>
+#include <linux/io.h>
+#include <linux/regmap.h>
+#include <linux/mfd/syscon.h>
+#include <linux/of_device.h>
+#include <linux/of_reserved_mem.h>
+#include <linux/pm_runtime.h>
+#include <linux/remoteproc.h>
+#include <linux/reset.h>
+#include <linux/clk.h>
+#include <linux/clkdev.h>
+#include <linux/kthread.h>
+#include <linux/clk-provider.h>
+#include <linux/mailbox_client.h>
+#include <linux/completion.h>
+#include <linux/freezer.h>
+#include <uapi/linux/sched/types.h>
+#include <uapi/linux/sched.h>
+#include <linux/sched/prio.h>
+#include <linux/rpmsg.h>
+#include <linux/pm_qos.h>
+#include <linux/delay.h>
+#include <linux/syscore_ops.h>
+#include <linux/pm_domain.h>
+#include <linux/spacemit/platform_pm_ops.h>
+#include "remoteproc_internal.h"
+
+#define MAX_MEM_BASE 2
+#define MAX_MBOX 2
+
+#define K1X_MBOX_VQ0_ID 0
+#define K1X_MBOX_VQ1_ID 1
+
+#define BOOTC_MEM_BASE_OFFSET 0
+#define SYSCTRL_MEM_BASE_OFFSET 1
+
+#define ESOS_BOOT_ENTRY_REG_OFFSET 0x88
+#define ESOS_BOOTUP_REG_OFFSET 0x30
+#define ESOS_AON_PER_CLK_RST_CTL_REG 0x2c
+
+#define ESOS_DDR_REGMAP_BASE_REG_OFFSET 0xc0
+
+#define APMU_AUDIO_CLK_RES_CTRL 0x14c
+#define APMU_AUDIO_POWER_STATUS_OFFSET 23
+
+#define DEV_PM_QOS_CLK_GATE 1
+#define DEV_PM_QOS_REGULATOR_GATE 2
+#define DEV_PM_QOS_PM_DOMAIN_GATE 4
+#define DEV_PM_QOS_DEFAULT 7
+
+struct dev_pm_qos_request greq;
+struct reset_control *gcore_reset;
+
+struct spacemit_mbox {
+ const char name[10];
+ struct mbox_chan *chan;
+ struct mbox_client client;
+ struct task_struct *mb_thread;
+ bool kthread_running;
+ struct completion mb_comp;
+ int vq_id;
+};
+
+struct spacemit_rproc {
+ struct device *dev;
+ struct reset_control *core_rst;
+ struct clk *core_clk;
+ unsigned int ddr_remap_base;
+ void __iomem *base[MAX_MEM_BASE];
+ struct spacemit_mbox *mb;
+#ifdef CONFIG_PM_SLEEP
+ struct rpmsg_device *rpdev;
+#endif
+};
+
+static int spacemit_rproc_mem_alloc(struct rproc *rproc,
+ struct rproc_mem_entry *mem)
+{
+ void __iomem *va = NULL;
+
+ dev_dbg(&rproc->dev, "map memory: %pa+%zx\n", &mem->dma, mem->len);
+ va = ioremap(mem->dma, mem->len);
+ if (!va) {
+ dev_err(&rproc->dev, "Unable to map memory region: %pa+%zx\n",
+ &mem->dma, mem->len);
+ return -ENOMEM;
+ }
+
+ memset(va, 0, mem->len);
+
+ /* Update memory entry va */
+ mem->va = va;
+
+ return 0;
+}
+
+static int spacemit_rproc_mem_release(struct rproc *rproc,
+ struct rproc_mem_entry *mem)
+{
+ dev_dbg(&rproc->dev, "unmap memory: %pa\n", &mem->dma);
+
+ iounmap(mem->va);
+
+ return 0;
+}
+
+static int spacemit_rproc_prepare(struct rproc *rproc)
+{
+ struct spacemit_rproc *priv = rproc->priv;
+ struct device *dev = rproc->dev.parent;
+ struct device_node *np = dev->of_node;
+ struct of_phandle_iterator it;
+ struct rproc_mem_entry *mem;
+ struct reserved_mem *rmem;
+ u32 da;
+ int ret, index = 0;
+
+ /* de-assert the audio module */
+ reset_control_deassert(priv->core_rst);
+
+ /* open the clk & pm-switch using pm-domain framework */
+ dev_pm_qos_add_request(priv->dev, &greq, DEV_PM_QOS_MAX_FREQUENCY,
+ DEV_PM_QOS_CLK_GATE | DEV_PM_QOS_PM_DOMAIN_GATE);
+
+ /* enable the power-switch and the clk */
+ pm_runtime_get_sync(priv->dev);
+
+ /* Register associated reserved memory regions */
+ of_phandle_iterator_init(&it, np, "memory-region", NULL, 0);
+ while (of_phandle_iterator_next(&it) == 0) {
+ rmem = of_reserved_mem_lookup(it.node);
+ if (!rmem) {
+ dev_err(&rproc->dev,
+ "unable to acquire memory-region\n");
+ return -EINVAL;
+ }
+
+ if (rmem->base > U64_MAX) {
+ dev_err(&rproc->dev,
+ "the rmem base is overflow\n");
+ return -EINVAL;
+ }
+
+ /* find the da */
+ ret = of_property_read_u32(it.node, "da_base", &da);
+ if (ret) {
+ /* no da_base; means that the da = dma */
+ da = rmem->base;
+ }
+
+ if (strcmp(it.node->name, "vdev0buffer")) {
+ mem = rproc_mem_entry_init(dev, NULL,
+ rmem->base,
+ rmem->size, da,
+ spacemit_rproc_mem_alloc,
+ spacemit_rproc_mem_release,
+ it.node->name);
+ } else {
+ /* Register reserved memory for vdev buffer alloc */
+ mem = rproc_of_resm_mem_entry_init(dev, index,
+ rmem->size,
+ rmem->base,
+ it.node->name);
+ }
+
+ if (!mem)
+ return -ENOMEM;
+
+ rproc_add_carveout(rproc, mem);
+ index++;
+ }
+
+ return 0;
+}
+
+static int spacemit_rproc_start(struct rproc *rproc)
+{
+ struct spacemit_rproc *priv = rproc->priv;
+
+ /* enable ipc2ap clk & reset--> rcpu side */
+ writel(0xff, priv->base[BOOTC_MEM_BASE_OFFSET] + ESOS_AON_PER_CLK_RST_CTL_REG);
+
+ /* set the boot-entry */
+ writel(rproc->bootaddr, priv->base[SYSCTRL_MEM_BASE_OFFSET] + ESOS_BOOT_ENTRY_REG_OFFSET);
+
+ /* set ddr map */
+ writel(priv->ddr_remap_base, priv->base[SYSCTRL_MEM_BASE_OFFSET] + ESOS_DDR_REGMAP_BASE_REG_OFFSET);
+
+ /* lanching up esos */
+ writel(1, priv->base[BOOTC_MEM_BASE_OFFSET] + ESOS_BOOTUP_REG_OFFSET);
+
+ return 0;
+}
+
+static int spacemit_rproc_stop(struct rproc *rproc)
+{
+ struct spacemit_rproc *priv = rproc->priv;
+
+ /* hold the rcpu */
+ writel(0, priv->base[BOOTC_MEM_BASE_OFFSET] + ESOS_BOOTUP_REG_OFFSET);
+
+ pm_runtime_put_sync(priv->dev);
+
+ reset_control_assert(priv->core_rst);
+
+ return 0;
+}
+
+static int spacemit_rproc_parse_fw(struct rproc *rproc, const struct firmware *fw)
+{
+ int ret;
+
+ ret = rproc_elf_load_rsc_table(rproc, fw);
+ if (ret)
+ dev_info(&rproc->dev, "No resource table in elf\n");
+
+ return 0;
+}
+
+static u64 spacemit_get_boot_addr(struct rproc *rproc, const struct firmware *fw)
+{
+ int err;
+ unsigned int entry_point;
+ struct device *dev = rproc->dev.parent;
+
+ /* get the entry point */
+ err = of_property_read_u32(dev->of_node, "esos-entry-point", &entry_point);
+ if (err) {
+ dev_err(dev, "failed to get entry point\n");
+ return 0;
+ }
+
+ return entry_point;
+}
+
+static void spacemit_rproc_kick(struct rproc *rproc, int vqid)
+{
+ struct spacemit_rproc *ddata = rproc->priv;
+ unsigned int i;
+ int err;
+
+ if (WARN_ON(vqid >= MAX_MBOX))
+ return;
+
+ for (i = 0; i < MAX_MBOX; i++) {
+ if (vqid != ddata->mb[i].vq_id)
+ continue;
+ if (!ddata->mb[i].chan)
+ return;
+ err = mbox_send_message(ddata->mb[i].chan, "kick");
+ if (err < 0)
+ dev_err(&rproc->dev, "%s: failed (%s, err:%d)\n",
+ __func__, ddata->mb[i].name, err);
+ return;
+ }
+}
+
+static struct rproc_ops spacemit_rproc_ops = {
+ .prepare = spacemit_rproc_prepare,
+ .start = spacemit_rproc_start,
+ .stop = spacemit_rproc_stop,
+ .load = rproc_elf_load_segments,
+ .parse_fw = spacemit_rproc_parse_fw,
+ .kick = spacemit_rproc_kick,
+ .find_loaded_rsc_table = rproc_elf_find_loaded_rsc_table,
+ .sanity_check = rproc_elf_sanity_check,
+ .get_boot_addr = spacemit_get_boot_addr,
+};
+
+static int __process_theread(void *arg)
+{
+ int ret;
+ struct mbox_client *cl = arg;
+ struct rproc *rproc = dev_get_drvdata(cl->dev);
+ struct spacemit_mbox *mb = container_of(cl, struct spacemit_mbox, client);
+ struct sched_param param = {.sched_priority = 0 };
+
+ mb->kthread_running = true;
+ ret = sched_setscheduler(current, SCHED_FIFO, &param);
+
+ do {
+ wait_for_completion_timeout(&mb->mb_comp, 10);
+ if (rproc_vq_interrupt(rproc, mb->vq_id) == IRQ_NONE)
+ dev_dbg(&rproc->dev, "no message found in vq%d\n", mb->vq_id);
+ } while (!kthread_should_stop());
+
+ mb->kthread_running = false;
+
+ return 0;
+}
+static void k1x_rproc_mb_callback(struct mbox_client *cl, void *data)
+{
+ struct spacemit_mbox *mb = container_of(cl, struct spacemit_mbox, client);
+
+ complete(&mb->mb_comp);
+}
+
+static struct spacemit_mbox k1x_rpoc_mbox[] = {
+ {
+ .name = "vq0",
+ .vq_id = K1X_MBOX_VQ0_ID,
+ .client = {
+ .rx_callback = k1x_rproc_mb_callback,
+ .tx_block = true,
+ },
+ },
+ {
+ .name = "vq1",
+ .vq_id = K1X_MBOX_VQ1_ID,
+ .client = {
+ .rx_callback = k1x_rproc_mb_callback,
+ .tx_block = true,
+ },
+ },
+};
+
+#ifdef CONFIG_PM_SLEEP
+
+#define STARTUP_MSG "pwr_management"
+
+static struct rpmsg_device_id rpmsg_rcpu_pwr_management_id_table[] = {
+ { .name = "rcpu-pwr-management-service", .driver_data = 0 },
+ { },
+};
+MODULE_DEVICE_TABLE(rpmsg, rpmsg_rcpu_pwr_management_id_table);
+
+static int rpmsg_rcpu_pwr_cb(struct rpmsg_device *rpdev, void *data,
+ int len, void *priv, u32 src)
+{
+ struct spacemit_rproc *srproc;
+
+ if (strcmp(data, "pwr_management_ok") == 0) {
+ pr_err("Connection create success\n");
+ return 0;
+ }
+
+ srproc = dev_get_drvdata(&rpdev->dev);
+
+ /* do something */
+
+ return 0;
+}
+
+static int rpmsg_rcpu_pwr_manage_probe(struct rpmsg_device *rpdev)
+{
+ int ret;
+ struct rproc *rproc;
+ struct spacemit_rproc *srproc;
+ struct platform_device *pdev;
+
+ pdev = (struct platform_device *)rpmsg_rcpu_pwr_management_id_table[0].driver_data;
+
+ rproc = platform_get_drvdata(pdev);
+ srproc = rproc->priv;
+ srproc->rpdev = rpdev;
+
+ dev_set_drvdata(&rpdev->dev, srproc);
+
+ dev_info(&rpdev->dev, "new channel: 0x%x -> 0x%x!\n",
+ rpdev->src, rpdev->dst);
+
+ ret = rpmsg_send(rpdev->ept, STARTUP_MSG, strlen(STARTUP_MSG));
+
+ return 0;
+}
+
+static void rpmsg_rcpu_pwr_manage_romove(struct rpmsg_device *rpdev)
+{
+ dev_info(&rpdev->dev, "rpmsg rcpu power management driver is removed\n");
+}
+
+/* here we should register a endpoint for power-management */
+static struct rpmsg_driver rpmsg_rcpu_pm_client = {
+ .drv.name = KBUILD_MODNAME,
+ .id_table = rpmsg_rcpu_pwr_management_id_table,
+ .probe = rpmsg_rcpu_pwr_manage_probe,
+ .callback = rpmsg_rcpu_pwr_cb,
+ .remove = rpmsg_rcpu_pwr_manage_romove,
+};
+
+module_rpmsg_driver(rpmsg_rcpu_pm_client);
+
+static int rproc_syscore_suspend(void)
+{
+ return 0;
+}
+
+static void rproc_syscore_resume(void)
+{
+ /* reset the rcpu */
+ reset_control_assert(gcore_reset);
+
+ reset_control_deassert(gcore_reset);
+}
+
+static struct syscore_ops rproc_syscore_ops = {
+ .suspend = rproc_syscore_suspend,
+ .resume = rproc_syscore_resume,
+};
+
+#define RCPU_ENTER_LOW_PWR_MODE "$"
+
+static int rproc_platform_late(void)
+{
+ int ret;
+ unsigned int val;
+ struct rproc *rproc;
+ struct spacemit_rproc *srproc;
+ struct rproc_mem_entry *rcpu_snapshots_mem;
+ struct platform_device *pdev;
+ struct generic_pm_domain *genpd;
+
+ pdev = (struct platform_device *)rpmsg_rcpu_pwr_management_id_table[0].driver_data;
+
+ rproc = dev_get_drvdata(&pdev->dev);
+ srproc = rproc->priv;
+
+ /* send msg to rcpu to let it enter low power mode */
+ ret = rpmsg_send(srproc->rpdev->ept, RCPU_ENTER_LOW_PWR_MODE,
+ strlen(RCPU_ENTER_LOW_PWR_MODE));
+
+ rcpu_snapshots_mem = rproc_find_carveout_by_name(rproc, "rcpu_mem_snapshots");
+ if (!rcpu_snapshots_mem) {
+ pr_err("Failed to find the rcpu_mem_snapshots\n");
+ return -1;
+ }
+
+ while (1) {
+ /* will be wrotten by rpcu */
+ val = readl(rcpu_snapshots_mem->va);
+ if (val == 1)
+ break;
+ }
+
+ /* wait the rcpu enter wfi */
+ mdelay(10);
+
+ genpd = pd_to_genpd(pdev->dev.pm_domain);
+
+ pdev->dev.power.wakeup_path = false;
+
+ /* close the clk & power-switch */
+ genpd->domain.ops.suspend_noirq(&pdev->dev);
+
+ return 0;
+}
+
+static void rproc_platfrom_wake(void)
+{
+ unsigned int val;
+ struct rproc *rproc;
+ struct spacemit_rproc *srproc;
+ struct rproc_mem_entry *rcpu_sram_mem, *rcpu_snapshots_mem;
+ struct platform_device *pdev;
+ struct generic_pm_domain *genpd;
+
+ pdev = (struct platform_device *)rpmsg_rcpu_pwr_management_id_table[0].driver_data;
+
+ rproc = dev_get_drvdata(&pdev->dev);
+ srproc = rproc->priv;
+
+ genpd = pd_to_genpd(pdev->dev.pm_domain);
+ /* enable the clk & power-switch */
+ genpd->domain.ops.resume_noirq(&pdev->dev);
+
+ /* enable ipc2ap clk & reset--> rcpu side */
+ writel(0xff, srproc->base[BOOTC_MEM_BASE_OFFSET] + ESOS_AON_PER_CLK_RST_CTL_REG);
+
+ /* set ddr map */
+ writel(srproc->ddr_remap_base, srproc->base[SYSCTRL_MEM_BASE_OFFSET] + ESOS_DDR_REGMAP_BASE_REG_OFFSET);
+
+ rcpu_sram_mem = rproc_find_carveout_by_name(rproc, "mem");
+ if (!rcpu_sram_mem) {
+ pr_err("Failed to find the rcpu_mem_0\n");
+ return;
+ }
+
+ rcpu_snapshots_mem = rproc_find_carveout_by_name(rproc, "rcpu_mem_snapshots");
+ if (!rcpu_snapshots_mem) {
+ pr_err("Failed to find the rcpu_mem_snapshots\n");
+ return;
+ }
+
+ /* copy the code */
+ memcpy((void *)rcpu_sram_mem->va,
+ (void *)((u32 *)rcpu_snapshots_mem->va + 1),
+ rcpu_sram_mem->len - sizeof(u32));
+
+ /* luaching up rpcu */
+ writel(1, srproc->base[BOOTC_MEM_BASE_OFFSET] + ESOS_BOOTUP_REG_OFFSET);
+
+ while (1) {
+ /* will be wrotten by rpcu */
+ val = readl(rcpu_snapshots_mem->va);
+ if (val == 2)
+ break;
+ }
+
+ memset((void *)rcpu_snapshots_mem->va, 0, rcpu_snapshots_mem->len);
+}
+
+static struct platfrom_pm_ops rproc_platform_pm_ops = {
+ .prepare_late = rproc_platform_late,
+ .wake = rproc_platfrom_wake,
+};
+
+static int spacemit_rproc_suspend(struct device *dev)
+{
+ /* this code do nothing but pretect the power & clk of audio
+ * from closing in noirq process when system suspend
+ * */
+ device_set_wakeup_path(dev);
+
+ return 0;
+}
+
+static int spacemit_rproc_resume(struct device *dev)
+{
+ return 0;
+}
+
+static const struct dev_pm_ops spacemit_rproc_pm_ops = {
+ .suspend = spacemit_rproc_suspend,
+ .resume = spacemit_rproc_resume,
+};
+#endif
+
+static int spacemit_rproc_probe(struct platform_device *pdev)
+{
+ int ret, i;
+ const char *name;
+ struct device *dev = &pdev->dev;
+ struct device_node *np = dev->of_node;
+ const char *fw_name = "esos.elf";
+ struct spacemit_rproc *priv;
+ struct mbox_client *cl;
+ struct rproc *rproc;
+
+ ret = rproc_of_parse_firmware(dev, 0, &fw_name);
+ if (ret < 0 && ret != -EINVAL)
+ return ret;
+
+ rproc = devm_rproc_alloc(dev, np->name, &spacemit_rproc_ops,
+ fw_name, sizeof(*priv));
+ if (!rproc)
+ return -ENOMEM;
+
+ priv = rproc->priv;
+ priv->dev = dev;
+
+ priv->base[BOOTC_MEM_BASE_OFFSET] = devm_platform_ioremap_resource(pdev, BOOTC_MEM_BASE_OFFSET);
+ if (IS_ERR(priv->base[BOOTC_MEM_BASE_OFFSET])) {
+ ret = PTR_ERR(priv->base[BOOTC_MEM_BASE_OFFSET]);
+ dev_err(dev, "failed to get reg base\n");
+ return ret;
+ }
+
+ priv->base[SYSCTRL_MEM_BASE_OFFSET] = devm_platform_ioremap_resource(pdev, SYSCTRL_MEM_BASE_OFFSET);
+ if (IS_ERR(priv->base[SYSCTRL_MEM_BASE_OFFSET])) {
+ ret = PTR_ERR(priv->base[SYSCTRL_MEM_BASE_OFFSET]);
+ dev_err(dev, "failed to get reg base\n");
+ return ret;
+ }
+
+ priv->core_rst = devm_reset_control_get_exclusive(dev, NULL);
+ if (IS_ERR(priv->core_rst)) {
+ ret = PTR_ERR(priv->core_rst);
+ dev_err_probe(dev, ret, "fail to acquire rproc reset\n");
+ return ret;
+ }
+
+ gcore_reset = priv->core_rst;
+
+ priv->core_clk = devm_clk_get(dev, "core");
+ if (IS_ERR(priv->core_clk)) {
+ ret = PTR_ERR(priv->core_clk);
+ dev_err(dev, "failed to acquire rpoc core\n");
+ return ret;
+ }
+
+ /* get the ddr-remap base */
+ ret = of_property_read_u32(pdev->dev.of_node, "ddr-remap-base", &priv->ddr_remap_base);
+
+ pm_runtime_enable(dev);
+
+ platform_set_drvdata(pdev, rproc);
+
+ /* get the mailbox */
+ priv->mb = k1x_rpoc_mbox;
+
+ for (i = 0; i < MAX_MBOX; ++i) {
+ name = priv->mb[i].name;
+
+ cl = &priv->mb[i].client;
+ cl->dev = dev;
+ init_completion(&priv->mb[i].mb_comp);
+
+ priv->mb[i].chan = mbox_request_channel_byname(cl, name);
+ if (IS_ERR(priv->mb[i].chan)) {
+ dev_err(dev, "failed to request mbox channel\n");
+ return -EINVAL;
+ }
+
+ if (priv->mb[i].vq_id >= 0) {
+ priv->mb[i].mb_thread = kthread_run(__process_theread, (void *)cl, name);
+ if (IS_ERR(priv->mb[i].mb_thread))
+ return PTR_ERR(priv->mb[i].mb_thread);
+ }
+ }
+
+#ifdef CONFIG_PM_SLEEP
+ rpmsg_rcpu_pwr_management_id_table[0].driver_data = (unsigned long long)pdev;
+
+ register_syscore_ops(&rproc_syscore_ops);
+
+ register_platform_pm_ops(&rproc_platform_pm_ops);
+#endif
+
+ rproc->auto_boot = true;
+ ret = devm_rproc_add(dev, rproc);
+ if (ret) {
+ dev_err(dev, "rproc_add failed\n");
+ }
+
+ return ret;
+}
+
+static void k1x_rproc_free_mbox(struct rproc *rproc)
+{
+ struct spacemit_rproc *ddata = rproc->priv;
+ unsigned int i;
+
+ for (i = 0; i < MAX_MBOX; i++) {
+ if (ddata->mb[i].chan)
+ mbox_free_channel(ddata->mb[i].chan);
+ ddata->mb[i].chan = NULL;
+ }
+}
+
+static int spacemit_rproc_remove(struct platform_device *pdev)
+{
+ int i = 0;
+ struct rproc *rproc = platform_get_drvdata(pdev);
+ struct spacemit_rproc *ddata = rproc->priv;
+
+ for (i = 0; i < MAX_MBOX; ++i)
+ if (ddata->mb[i].kthread_running)
+ kthread_stop(ddata->mb[i].mb_thread);
+
+ rproc_del(rproc);
+ k1x_rproc_free_mbox(rproc);
+ rproc_free(rproc);
+
+#ifdef CONFIG_PM_SLEEP
+ unregister_rpmsg_driver(&rpmsg_rcpu_pm_client);
+#endif
+ return 0;
+}
+
+static const struct of_device_id spacemit_rproc_of_match[] = {
+ { .compatible = "spacemit,k1-x-rproc" },
+ {},
+};
+
+MODULE_DEVICE_TABLE(of, spacemit_rproc_of_match);
+
+static void spacemit_rproc_shutdown(struct platform_device *pdev)
+{
+ int i;
+ struct rproc *rproc;
+ struct spacemit_rproc *priv;
+
+ rproc = dev_get_drvdata(&pdev->dev);
+ priv = rproc->priv;
+
+ for (i = 0; i < MAX_MBOX; ++i) {
+ /* release the resource of rt thread */
+ kthread_stop(priv->mb[i].mb_thread);
+ /* mbox_free_channel(priv->mb[i].chan); */
+ }
+}
+
+static struct platform_driver spacemit_rproc_driver = {
+ .probe = spacemit_rproc_probe,
+ .remove = spacemit_rproc_remove,
+ .shutdown = spacemit_rproc_shutdown,
+ .driver = {
+ .name = "spacemit-rproc",
+#ifdef CONFIG_PM_SLEEP
+ .pm = &spacemit_rproc_pm_ops,
+#endif
+ .of_match_table = spacemit_rproc_of_match,
+ },
+};
+
+static __init int spacemit_rproc_driver_init(void)
+{
+ return platform_driver_register(&spacemit_rproc_driver);
+}
+subsys_initcall(spacemit_rproc_driver_init);
+
+MODULE_LICENSE("GPL v2");
+MODULE_DESCRIPTION("sapcemit remote processor control driver");
--
Armbian

View File

@@ -1,602 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Patrick Yavitz <pyavitz@armbian.com>
Date: Fri, 21 Jun 2024 11:54:06 -0400
Subject: add spacemit patch set
source: https://gitee.com/bianbu-linux/linux-6.1
Signed-off-by: Patrick Yavitz <pyavitz@armbian.com>
---
drivers/reset/Kconfig | 17 +
drivers/reset/Makefile | 3 +
drivers/reset/reset-spacemit-k1x.c | 540 ++++++++++
3 files changed, 560 insertions(+)
diff --git a/drivers/reset/Kconfig b/drivers/reset/Kconfig
index 111111111111..222222222222 100644
--- a/drivers/reset/Kconfig
+++ b/drivers/reset/Kconfig
@@ -319,6 +319,23 @@ config RESET_ZYNQ
default ARCH_ZYNQ
help
This enables the reset controller driver for Xilinx Zynq SoCs.
+config RESET_K1PRO_SPACEMIT
+ tristate "Reset controller driver for Spacemit K1PRO SoCs"
+ depends on SOC_SPACEMIT_K1PRO
+ help
+ Support for reset controllers on Spacemit K1PRO SoCs.
+
+config RESET_K1X_SPACEMIT
+ tristate "Reset controller driver for Spacemit K1X SoCs"
+ depends on SOC_SPACEMIT_K1X
+ help
+ Support for reset controllers on Spacemit K1X SoCs.
+
+config RESET_K1MATRIX_SPACEMIT
+ tristate "Reset controller driver for Spacemit K1MATRIX SoCs"
+ default y
+ help
+ Support for reset controllers on Spacemit K1MATRIX SoCs.
source "drivers/reset/sti/Kconfig"
source "drivers/reset/hisilicon/Kconfig"
diff --git a/drivers/reset/Makefile b/drivers/reset/Makefile
index 111111111111..222222222222 100644
--- a/drivers/reset/Makefile
+++ b/drivers/reset/Makefile
@@ -41,3 +41,6 @@ obj-$(CONFIG_RESET_UNIPHIER) += reset-uniphier.o
obj-$(CONFIG_RESET_UNIPHIER_GLUE) += reset-uniphier-glue.o
obj-$(CONFIG_RESET_ZYNQ) += reset-zynq.o
obj-$(CONFIG_ARCH_ZYNQMP) += reset-zynqmp.o
+obj-$(CONFIG_RESET_K1PRO_SPACEMIT) += reset-spacemit-k1pro.o
+obj-$(CONFIG_RESET_K1X_SPACEMIT) += reset-spacemit-k1x.o
+obj-$(CONFIG_RESET_K1_MATRIX_SPACEMIT) += reset-spacemit-k1matrix.o
diff --git a/drivers/reset/reset-spacemit-k1x.c b/drivers/reset/reset-spacemit-k1x.c
new file mode 100644
index 000000000000..111111111111
--- /dev/null
+++ b/drivers/reset/reset-spacemit-k1x.c
@@ -0,0 +1,540 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Spacemit k1x reset controller driver
+ *
+ * Copyright (c) 2023, spacemit Corporation.
+ *
+ */
+
+#include <linux/mfd/syscon.h>
+#include <linux/mod_devicetable.h>
+#include <linux/of_device.h>
+#include <linux/of_address.h>
+#include <linux/platform_device.h>
+#include <linux/reset-controller.h>
+#include <linux/io.h>
+#include <dt-bindings/reset/spacemit-k1x-reset.h>
+#include <linux/clk-provider.h>
+#include <linux/atomic.h>
+#include <linux/spinlock.h>
+
+#include "../clk/spacemit/ccu-spacemit-k1x.h"
+
+#define LOG_INFO(fmt, arg...) pr_info("[RESET][%s][%d]:" fmt "\n", __func__, __LINE__, ##arg)
+
+/* APBC register offset */
+#define APBC_UART1_CLK_RST 0x0
+#define APBC_UART2_CLK_RST 0x4
+#define APBC_GPIO_CLK_RST 0x8
+#define APBC_PWM0_CLK_RST 0xc
+#define APBC_PWM1_CLK_RST 0x10
+#define APBC_PWM2_CLK_RST 0x14
+#define APBC_PWM3_CLK_RST 0x18
+#define APBC_TWSI8_CLK_RST 0x20
+#define APBC_UART3_CLK_RST 0x24
+#define APBC_RTC_CLK_RST 0x28
+#define APBC_TWSI0_CLK_RST 0x2c
+#define APBC_TWSI1_CLK_RST 0x30
+#define APBC_TIMERS1_CLK_RST 0x34
+#define APBC_TWSI2_CLK_RST 0x38
+#define APBC_AIB_CLK_RST 0x3c
+#define APBC_TWSI4_CLK_RST 0x40
+#define APBC_TIMERS2_CLK_RST 0x44
+#define APBC_ONEWIRE_CLK_RST 0x48
+#define APBC_TWSI5_CLK_RST 0x4c
+#define APBC_DRO_CLK_RST 0x58
+#define APBC_IR_CLK_RST 0x5c
+#define APBC_TWSI6_CLK_RST 0x60
+#define APBC_TWSI7_CLK_RST 0x68
+#define APBC_TSEN_CLK_RST 0x6c
+
+#define APBC_UART4_CLK_RST 0x70
+#define APBC_UART5_CLK_RST 0x74
+#define APBC_UART6_CLK_RST 0x78
+#define APBC_SSP3_CLK_RST 0x7c
+
+#define APBC_SSPA0_CLK_RST 0x80
+#define APBC_SSPA1_CLK_RST 0x84
+
+#define APBC_IPC_AP2AUD_CLK_RST 0x90
+#define APBC_UART7_CLK_RST 0x94
+#define APBC_UART8_CLK_RST 0x98
+#define APBC_UART9_CLK_RST 0x9c
+
+#define APBC_CAN0_CLK_RST 0xa0
+#define APBC_PWM4_CLK_RST 0xa8
+#define APBC_PWM5_CLK_RST 0xac
+#define APBC_PWM6_CLK_RST 0xb0
+#define APBC_PWM7_CLK_RST 0xb4
+#define APBC_PWM8_CLK_RST 0xb8
+#define APBC_PWM9_CLK_RST 0xbc
+#define APBC_PWM10_CLK_RST 0xc0
+#define APBC_PWM11_CLK_RST 0xc4
+#define APBC_PWM12_CLK_RST 0xc8
+#define APBC_PWM13_CLK_RST 0xcc
+#define APBC_PWM14_CLK_RST 0xd0
+#define APBC_PWM15_CLK_RST 0xd4
+#define APBC_PWM16_CLK_RST 0xd8
+#define APBC_PWM17_CLK_RST 0xdc
+#define APBC_PWM18_CLK_RST 0xe0
+#define APBC_PWM19_CLK_RST 0xe4
+/* end of APBC register offset */
+
+/* MPMU register offset */
+#define MPMU_WDTPCR 0x200
+/* end of MPMU register offset */
+
+/* APMU register offset */
+#define APMU_JPG_CLK_RES_CTRL 0x20
+#define APMU_CSI_CCIC2_CLK_RES_CTRL 0x24
+#define APMU_ISP_CLK_RES_CTRL 0x38
+#define APMU_LCD_CLK_RES_CTRL1 0x44
+#define APMU_LCD_SPI_CLK_RES_CTRL 0x48
+#define APMU_LCD_CLK_RES_CTRL2 0x4c
+#define APMU_CCIC_CLK_RES_CTRL 0x50
+#define APMU_SDH0_CLK_RES_CTRL 0x54
+#define APMU_SDH1_CLK_RES_CTRL 0x58
+#define APMU_USB_CLK_RES_CTRL 0x5c
+#define APMU_QSPI_CLK_RES_CTRL 0x60
+#define APMU_USB_CLK_RES_CTRL 0x5c
+#define APMU_DMA_CLK_RES_CTRL 0x64
+#define APMU_AES_CLK_RES_CTRL 0x68
+#define APMU_VPU_CLK_RES_CTRL 0xa4
+#define APMU_GPU_CLK_RES_CTRL 0xcc
+#define APMU_SDH2_CLK_RES_CTRL 0xe0
+#define APMU_PMUA_MC_CTRL 0xe8
+#define APMU_PMU_CC2_AP 0x100
+#define APMU_PMUA_EM_CLK_RES_CTRL 0x104
+
+#define APMU_AUDIO_CLK_RES_CTRL 0x14c
+#define APMU_HDMI_CLK_RES_CTRL 0x1B8
+
+#define APMU_PCIE_CLK_RES_CTRL_0 0x3cc
+#define APMU_PCIE_CLK_RES_CTRL_1 0x3d4
+#define APMU_PCIE_CLK_RES_CTRL_2 0x3dc
+
+#define APMU_EMAC0_CLK_RES_CTRL 0x3e4
+#define APMU_EMAC1_CLK_RES_CTRL 0x3ec
+/* end of APMU register offset */
+
+/* APBC2 register offset */
+#define APBC2_UART1_CLK_RST 0x00
+#define APBC2_SSP2_CLK_RST 0x04
+#define APBC2_TWSI3_CLK_RST 0x08
+#define APBC2_RTC_CLK_RST 0x0c
+#define APBC2_TIMERS0_CLK_RST 0x10
+#define APBC2_KPC_CLK_RST 0x14
+#define APBC2_GPIO_CLK_RST 0x1c
+/* end of APBC2 register offset */
+
+/* RCPU register offset */
+#define RCPU_HDMI_CLK_RST 0x2044
+#define RCPU_CAN_CLK_RST 0x4c
+/* end of RCPU register offset */
+
+/* RCPU2 register offset */
+#define RCPU2_PWM_CLK_RST 0x08
+/* end of RCPU2 register offset */
+
+enum spacemit_reset_base_type{
+ RST_BASE_TYPE_MPMU = 0,
+ RST_BASE_TYPE_APMU = 1,
+ RST_BASE_TYPE_APBC = 2,
+ RST_BASE_TYPE_APBS = 3,
+ RST_BASE_TYPE_CIU = 4,
+ RST_BASE_TYPE_DCIU = 5,
+ RST_BASE_TYPE_DDRC = 6,
+ RST_BASE_TYPE_AUDC = 7,
+ RST_BASE_TYPE_APBC2 = 8,
+ RST_BASE_TYPE_RCPU = 9,
+ RST_BASE_TYPE_RCPU2 = 10,
+};
+
+struct spacemit_reset_signal {
+ u32 offset;
+ u32 mask;
+ u32 deassert_val;
+ u32 assert_val;
+ enum spacemit_reset_base_type type;
+};
+
+struct spacemit_reset_variant {
+ const struct spacemit_reset_signal *signals;
+ u32 signals_num;
+ struct reset_control_ops ops;
+};
+
+struct spacemit_reset {
+ spinlock_t *lock;
+ struct reset_controller_dev rcdev;
+ void __iomem *mpmu_base;
+ void __iomem *apmu_base;
+ void __iomem *apbc_base;
+ void __iomem *apbs_base;
+ void __iomem *ciu_base;
+ void __iomem *dciu_base;
+ void __iomem *ddrc_base;
+ void __iomem *audio_ctrl_base;
+ void __iomem *apbc2_base;
+ void __iomem *rcpu_base;
+ void __iomem *rcpu2_base;
+ const struct spacemit_reset_signal *signals;
+};
+
+struct spacemit_reset k1x_reset_controller;
+
+static const struct spacemit_reset_signal
+ k1x_reset_signals[RESET_NUMBER] = {
+ [RESET_UART1] = { APBC_UART1_CLK_RST, BIT(2), 0, BIT(2), RST_BASE_TYPE_APBC },
+ [RESET_UART2] = { APBC_UART2_CLK_RST, BIT(2), 0, BIT(2), RST_BASE_TYPE_APBC },
+ [RESET_GPIO] = { APBC_GPIO_CLK_RST, BIT(2), 0, BIT(2), RST_BASE_TYPE_APBC },
+ [RESET_PWM0] = { APBC_PWM0_CLK_RST, BIT(2)|BIT(0), BIT(0), BIT(2), RST_BASE_TYPE_APBC },
+ [RESET_PWM1] = { APBC_PWM1_CLK_RST, BIT(2)|BIT(0), BIT(0), BIT(2), RST_BASE_TYPE_APBC },
+ [RESET_PWM2] = { APBC_PWM2_CLK_RST, BIT(2)|BIT(0), BIT(0), BIT(2), RST_BASE_TYPE_APBC },
+ [RESET_PWM3] = { APBC_PWM3_CLK_RST, BIT(2)|BIT(0), BIT(0), BIT(2), RST_BASE_TYPE_APBC },
+ [RESET_PWM4] = { APBC_PWM4_CLK_RST, BIT(2)|BIT(0), BIT(0), BIT(2), RST_BASE_TYPE_APBC },
+ [RESET_PWM5] = { APBC_PWM5_CLK_RST, BIT(2)|BIT(0), BIT(0), BIT(2), RST_BASE_TYPE_APBC },
+ [RESET_PWM6] = { APBC_PWM6_CLK_RST, BIT(2)|BIT(0), BIT(0), BIT(2), RST_BASE_TYPE_APBC },
+ [RESET_PWM7] = { APBC_PWM7_CLK_RST, BIT(2)|BIT(0), BIT(0), BIT(2), RST_BASE_TYPE_APBC },
+ [RESET_PWM8] = { APBC_PWM8_CLK_RST, BIT(2)|BIT(0), BIT(0), BIT(2), RST_BASE_TYPE_APBC },
+ [RESET_PWM9] = { APBC_PWM9_CLK_RST, BIT(2)|BIT(0), BIT(0), BIT(2), RST_BASE_TYPE_APBC },
+ [RESET_PWM10] = { APBC_PWM10_CLK_RST, BIT(2)|BIT(0), BIT(0), BIT(2), RST_BASE_TYPE_APBC },
+ [RESET_PWM11] = { APBC_PWM11_CLK_RST, BIT(2)|BIT(0), BIT(0), BIT(2), RST_BASE_TYPE_APBC },
+ [RESET_PWM12] = { APBC_PWM12_CLK_RST, BIT(2)|BIT(0), BIT(0), BIT(2), RST_BASE_TYPE_APBC },
+ [RESET_PWM13] = { APBC_PWM13_CLK_RST, BIT(2)|BIT(0), BIT(0), BIT(2), RST_BASE_TYPE_APBC },
+ [RESET_PWM14] = { APBC_PWM14_CLK_RST, BIT(2)|BIT(0), BIT(0), BIT(2), RST_BASE_TYPE_APBC },
+ [RESET_PWM15] = { APBC_PWM15_CLK_RST, BIT(2)|BIT(0), BIT(0), BIT(2), RST_BASE_TYPE_APBC },
+ [RESET_PWM16] = { APBC_PWM16_CLK_RST, BIT(2)|BIT(0), BIT(0), BIT(2), RST_BASE_TYPE_APBC },
+ [RESET_PWM17] = { APBC_PWM17_CLK_RST, BIT(2)|BIT(0), BIT(0), BIT(2), RST_BASE_TYPE_APBC },
+ [RESET_PWM18] = { APBC_PWM18_CLK_RST, BIT(2)|BIT(0), BIT(0), BIT(2), RST_BASE_TYPE_APBC },
+ [RESET_PWM19] = { APBC_PWM19_CLK_RST, BIT(2)|BIT(0), BIT(0), BIT(2), RST_BASE_TYPE_APBC },
+ [RESET_SSP3] = { APBC_SSP3_CLK_RST, BIT(2), 0, BIT(2), RST_BASE_TYPE_APBC },
+ [RESET_UART3] = { APBC_UART3_CLK_RST, BIT(2), 0, BIT(2), RST_BASE_TYPE_APBC },
+ [RESET_RTC] = { APBC_RTC_CLK_RST, BIT(2), 0, BIT(2), RST_BASE_TYPE_APBC },
+ [RESET_TWSI0] = { APBC_TWSI0_CLK_RST, BIT(2), 0, BIT(2), RST_BASE_TYPE_APBC },
+ [RESET_TIMERS1] = { APBC_TIMERS1_CLK_RST, BIT(2), 0, BIT(2), RST_BASE_TYPE_APBC },
+ [RESET_AIB] = { APBC_AIB_CLK_RST, BIT(2), 0, BIT(2), RST_BASE_TYPE_APBC },
+ [RESET_TIMERS2] = { APBC_TIMERS2_CLK_RST,BIT(2), 0, BIT(2), RST_BASE_TYPE_APBC },
+ [RESET_ONEWIRE] = { APBC_ONEWIRE_CLK_RST, BIT(2), 0, BIT(2), RST_BASE_TYPE_APBC },
+ [RESET_SSPA0] = { APBC_SSPA0_CLK_RST, BIT(2), 0, BIT(2), RST_BASE_TYPE_APBC },
+ [RESET_SSPA1] = { APBC_SSPA1_CLK_RST, BIT(2), 0, BIT(2), RST_BASE_TYPE_APBC },
+ [RESET_DRO] = { APBC_DRO_CLK_RST, BIT(2), 0, BIT(2), RST_BASE_TYPE_APBC },
+ [RESET_IR] = { APBC_IR_CLK_RST, BIT(2), 0, BIT(2), RST_BASE_TYPE_APBC },
+ [RESET_TWSI1] = { APBC_TWSI1_CLK_RST, BIT(2), 0, BIT(2), RST_BASE_TYPE_APBC },
+ [RESET_TSEN] = { APBC_TSEN_CLK_RST, BIT(2), 0, BIT(2), RST_BASE_TYPE_APBC },
+ [RESET_TWSI2] = { APBC_TWSI2_CLK_RST, BIT(2), 0, BIT(2), RST_BASE_TYPE_APBC },
+ [RESET_TWSI4] = { APBC_TWSI4_CLK_RST, BIT(2), 0, BIT(2), RST_BASE_TYPE_APBC },
+ [RESET_TWSI5] = { APBC_TWSI5_CLK_RST, BIT(2), 0, BIT(2), RST_BASE_TYPE_APBC },
+ [RESET_TWSI6] = { APBC_TWSI6_CLK_RST, BIT(2), 0, BIT(2), RST_BASE_TYPE_APBC },
+ [RESET_TWSI7] = { APBC_TWSI7_CLK_RST, BIT(2), 0, BIT(2), RST_BASE_TYPE_APBC },
+ [RESET_TWSI8] = { APBC_TWSI8_CLK_RST, BIT(2), 0, BIT(2), RST_BASE_TYPE_APBC },
+ [RESET_IPC_AP2AUD] = { APBC_IPC_AP2AUD_CLK_RST, BIT(2), 0, BIT(2), RST_BASE_TYPE_APBC },
+ [RESET_UART4] = { APBC_UART4_CLK_RST, BIT(2), 0, BIT(2), RST_BASE_TYPE_APBC },
+ [RESET_UART5] = { APBC_UART5_CLK_RST, BIT(2), 0, BIT(2), RST_BASE_TYPE_APBC },
+ [RESET_UART6] = { APBC_UART6_CLK_RST, BIT(2), 0, BIT(2), RST_BASE_TYPE_APBC },
+ [RESET_UART7] = { APBC_UART7_CLK_RST, BIT(2), 0, BIT(2), RST_BASE_TYPE_APBC },
+ [RESET_UART8] = { APBC_UART8_CLK_RST, BIT(2), 0, BIT(2), RST_BASE_TYPE_APBC },
+ [RESET_UART9] = { APBC_UART9_CLK_RST, BIT(2), 0, BIT(2), RST_BASE_TYPE_APBC },
+ [RESET_CAN0] = { APBC_CAN0_CLK_RST, BIT(2), 0, BIT(2), RST_BASE_TYPE_APBC },
+ //MPMU
+ [RESET_WDT] = { MPMU_WDTPCR, BIT(2), 0, BIT(2), RST_BASE_TYPE_MPMU },
+ //APMU
+ [RESET_JPG] = { APMU_JPG_CLK_RES_CTRL, BIT(0), BIT(0), 0, RST_BASE_TYPE_APMU },
+ [RESET_CSI] = { APMU_CSI_CCIC2_CLK_RES_CTRL, BIT(1), BIT(1), 0, RST_BASE_TYPE_APMU },
+ [RESET_CCIC2_PHY] = { APMU_CSI_CCIC2_CLK_RES_CTRL, BIT(2), BIT(2), 0, RST_BASE_TYPE_APMU },
+ [RESET_CCIC3_PHY] = { APMU_CSI_CCIC2_CLK_RES_CTRL, BIT(29), BIT(29), 0, RST_BASE_TYPE_APMU },
+ [RESET_ISP] = { APMU_ISP_CLK_RES_CTRL, BIT(0), BIT(0), 0, RST_BASE_TYPE_APMU },
+ [RESET_ISP_AHB] = { APMU_ISP_CLK_RES_CTRL, BIT(3), BIT(3), 0, RST_BASE_TYPE_APMU },
+ [RESET_ISP_CI] = { APMU_ISP_CLK_RES_CTRL, BIT(16), BIT(16), 0, RST_BASE_TYPE_APMU },
+ [RESET_ISP_CPP] = { APMU_ISP_CLK_RES_CTRL, BIT(27), BIT(27), 0, RST_BASE_TYPE_APMU },
+ [RESET_LCD] = { APMU_LCD_CLK_RES_CTRL1, BIT(4), BIT(4), 0, RST_BASE_TYPE_APMU },
+ [RESET_DSI_ESC] = { APMU_LCD_CLK_RES_CTRL1, BIT(3), BIT(3), 0, RST_BASE_TYPE_APMU },
+ [RESET_V2D] = { APMU_LCD_CLK_RES_CTRL1, BIT(27), BIT(27), 0, RST_BASE_TYPE_APMU },
+ [RESET_MIPI] = { APMU_LCD_CLK_RES_CTRL1, BIT(15), BIT(15), 0, RST_BASE_TYPE_APMU },
+ [RESET_LCD_SPI] = { APMU_LCD_SPI_CLK_RES_CTRL, BIT(0), BIT(0), 0, RST_BASE_TYPE_APMU },
+ [RESET_LCD_SPI_BUS] = { APMU_LCD_SPI_CLK_RES_CTRL, BIT(4), BIT(4), 0, RST_BASE_TYPE_APMU },
+ [RESET_LCD_SPI_HBUS] = { APMU_LCD_SPI_CLK_RES_CTRL, BIT(2), BIT(2), 0, RST_BASE_TYPE_APMU },
+ [RESET_LCD_MCLK] = { APMU_LCD_CLK_RES_CTRL2, BIT(9), BIT(9), 0, RST_BASE_TYPE_APMU },
+ [RESET_CCIC_4X] = { APMU_CCIC_CLK_RES_CTRL, BIT(1), BIT(1), 0, RST_BASE_TYPE_APMU },
+ [RESET_CCIC1_PHY] = { APMU_CCIC_CLK_RES_CTRL, BIT(2), BIT(2), 0, RST_BASE_TYPE_APMU },
+ [RESET_SDH_AXI] = { APMU_SDH0_CLK_RES_CTRL, BIT(0), BIT(0), 0, RST_BASE_TYPE_APMU },
+ [RESET_SDH0] = { APMU_SDH0_CLK_RES_CTRL, BIT(1), BIT(1), 0, RST_BASE_TYPE_APMU },
+ [RESET_SDH1] = { APMU_SDH1_CLK_RES_CTRL, BIT(1), BIT(1), 0, RST_BASE_TYPE_APMU },
+ [RESET_USB_AXI] = { APMU_USB_CLK_RES_CTRL, BIT(0), BIT(0), 0, RST_BASE_TYPE_APMU },
+ [RESET_USBP1_AXI] = { APMU_USB_CLK_RES_CTRL, BIT(4), BIT(4), 0, RST_BASE_TYPE_APMU },
+ [RESET_USB3_0] = { APMU_USB_CLK_RES_CTRL, BIT(9)|BIT(10)|BIT(11), BIT(9)|BIT(10)|BIT(11), 0, RST_BASE_TYPE_APMU },
+ [RESET_QSPI] = { APMU_QSPI_CLK_RES_CTRL, BIT(1), BIT(1), 0, RST_BASE_TYPE_APMU },
+ [RESET_QSPI_BUS] = { APMU_QSPI_CLK_RES_CTRL, BIT(0), BIT(0), 0, RST_BASE_TYPE_APMU },
+ [RESET_DMA] = { APMU_DMA_CLK_RES_CTRL, BIT(0), BIT(0), 0, RST_BASE_TYPE_APMU },
+ [RESET_AES] = { APMU_AES_CLK_RES_CTRL, BIT(4), BIT(4), 0, RST_BASE_TYPE_APMU },
+ [RESET_VPU] = { APMU_VPU_CLK_RES_CTRL, BIT(0), BIT(0), 0, RST_BASE_TYPE_APMU },
+ [RESET_GPU] = { APMU_GPU_CLK_RES_CTRL, BIT(1), BIT(1), 0, RST_BASE_TYPE_APMU },
+ [RESET_SDH2] = { APMU_SDH2_CLK_RES_CTRL, BIT(1), BIT(1), 0, RST_BASE_TYPE_APMU },
+ [RESET_MC] = { APMU_PMUA_MC_CTRL, BIT(0), BIT(0), 0, RST_BASE_TYPE_APMU },//?
+ [RESET_EM_AXI] = { APMU_PMUA_EM_CLK_RES_CTRL, BIT(0), BIT(0), 0, RST_BASE_TYPE_APMU },
+ [RESET_EM] = { APMU_PMUA_EM_CLK_RES_CTRL, BIT(1), BIT(1), 0, RST_BASE_TYPE_APMU },
+ [RESET_AUDIO_SYS] = { APMU_AUDIO_CLK_RES_CTRL, BIT(0)|BIT(2)|BIT(3), BIT(0)|BIT(2)|BIT(3), 0, RST_BASE_TYPE_APMU },
+ [RESET_HDMI] = { APMU_HDMI_CLK_RES_CTRL, BIT(9), BIT(9), 0, RST_BASE_TYPE_APMU },
+ [RESET_PCIE0] = { APMU_PCIE_CLK_RES_CTRL_0, BIT(3)|BIT(4)|BIT(5)|BIT(8), BIT(3)|BIT(4)|BIT(5), BIT(8), RST_BASE_TYPE_APMU },
+ [RESET_PCIE1] = { APMU_PCIE_CLK_RES_CTRL_1, BIT(3)|BIT(4)|BIT(5)|BIT(8), BIT(3)|BIT(4)|BIT(5), BIT(8), RST_BASE_TYPE_APMU },
+ [RESET_PCIE2] = { APMU_PCIE_CLK_RES_CTRL_2, 0x138, 0x38, 0x100, RST_BASE_TYPE_APMU },
+ [RESET_EMAC0] = { APMU_EMAC0_CLK_RES_CTRL, BIT(1), BIT(1), 0, RST_BASE_TYPE_APMU },
+ [RESET_EMAC1] = { APMU_EMAC1_CLK_RES_CTRL, BIT(1), BIT(1), 0, RST_BASE_TYPE_APMU },
+ //APBC2
+ [RESET_SEC_UART1] = { APBC2_UART1_CLK_RST, BIT(2), 0, BIT(2), RST_BASE_TYPE_APBC2 },
+ [RESET_SEC_SSP2] = { APBC2_SSP2_CLK_RST, BIT(2), 0, BIT(2), RST_BASE_TYPE_APBC2 },
+ [RESET_SEC_TWSI3] = { APBC2_TWSI3_CLK_RST, BIT(2), 0, BIT(2), RST_BASE_TYPE_APBC2 },
+ [RESET_SEC_RTC] = { APBC2_RTC_CLK_RST, BIT(2), 0, BIT(2), RST_BASE_TYPE_APBC2 },
+ [RESET_SEC_TIMERS0] = { APBC2_TIMERS0_CLK_RST, BIT(2), 0, BIT(2), RST_BASE_TYPE_APBC2 },
+ [RESET_SEC_KPC] = { APBC2_KPC_CLK_RST, BIT(2), 0, BIT(2), RST_BASE_TYPE_APBC2 },
+ [RESET_SEC_GPIO] = { APBC2_GPIO_CLK_RST, BIT(2), 0, BIT(2), RST_BASE_TYPE_APBC2 },
+ //RCPU
+ [RESET_RCPU_HDMIAUDIO] = { RCPU_HDMI_CLK_RST, BIT(0), BIT(0), 0, RST_BASE_TYPE_RCPU },
+ [RESET_RCPU_CAN] = { RCPU_CAN_CLK_RST, BIT(0), BIT(0), 0, RST_BASE_TYPE_RCPU },
+ //RCPU2
+ [RESET_RCPU2_PWM] = { RCPU2_PWM_CLK_RST, BIT(2)|BIT(0), BIT(0), BIT(2), RST_BASE_TYPE_RCPU2 },
+};
+
+static struct spacemit_reset *to_spacemit_reset(
+ struct reset_controller_dev *rcdev)
+{
+ return container_of(rcdev, struct spacemit_reset, rcdev);
+}
+
+static u32 spacemit_reset_read(struct spacemit_reset *reset,
+ u32 id)
+{
+ void __iomem *base;
+ switch(reset->signals[id].type){
+ case RST_BASE_TYPE_MPMU:
+ base = reset->mpmu_base;
+ break;
+ case RST_BASE_TYPE_APMU:
+ base = reset->apmu_base;
+ break;
+ case RST_BASE_TYPE_APBC:
+ base = reset->apbc_base;
+ break;
+ case RST_BASE_TYPE_APBS:
+ base = reset->apbs_base;
+ break;
+ case RST_BASE_TYPE_CIU:
+ base = reset->ciu_base;
+ break;
+ case RST_BASE_TYPE_DCIU:
+ base = reset->dciu_base;
+ break;
+ case RST_BASE_TYPE_DDRC:
+ base = reset->ddrc_base;
+ break;
+ case RST_BASE_TYPE_AUDC:
+ base = reset->audio_ctrl_base;
+ break;
+ case RST_BASE_TYPE_APBC2:
+ base = reset->apbc2_base;
+ break;
+ case RST_BASE_TYPE_RCPU:
+ base = reset->rcpu_base;
+ break;
+ case RST_BASE_TYPE_RCPU2:
+ base = reset->rcpu2_base;
+ break;
+ default:
+ base = reset->apbc_base;
+ break;
+
+ }
+
+ return readl(base + reset->signals[id].offset);
+}
+
+static void spacemit_reset_write(struct spacemit_reset *reset, u32 value,
+ u32 id)
+{
+ void __iomem *base;
+ switch(reset->signals[id].type){
+ case RST_BASE_TYPE_MPMU:
+ base = reset->mpmu_base;
+ break;
+ case RST_BASE_TYPE_APMU:
+ base = reset->apmu_base;
+ break;
+ case RST_BASE_TYPE_APBC:
+ base = reset->apbc_base;
+ break;
+ case RST_BASE_TYPE_APBS:
+ base = reset->apbs_base;
+ break;
+ case RST_BASE_TYPE_CIU:
+ base = reset->ciu_base;
+ break;
+ case RST_BASE_TYPE_DCIU:
+ base = reset->dciu_base;
+ break;
+ case RST_BASE_TYPE_DDRC:
+ base = reset->ddrc_base;
+ break;
+ case RST_BASE_TYPE_AUDC:
+ base = reset->audio_ctrl_base;
+ break;
+ case RST_BASE_TYPE_APBC2:
+ base = reset->apbc2_base;
+ break;
+ case RST_BASE_TYPE_RCPU:
+ base = reset->rcpu_base;
+ break;
+ case RST_BASE_TYPE_RCPU2:
+ base = reset->rcpu2_base;
+ break;
+ default:
+ base = reset->apbc_base;
+ break;
+
+ }
+ writel(value, base + reset->signals[id].offset);
+}
+
+static void spacemit_reset_set(struct reset_controller_dev *rcdev,
+ u32 id, bool assert)
+{
+ u32 value;
+ struct spacemit_reset *reset = to_spacemit_reset(rcdev);
+
+ value = spacemit_reset_read(reset, id);
+ if(assert == true) {
+ value &= ~ reset->signals[id].mask;
+ value |=reset->signals[id].assert_val;
+
+ } else {
+ value &= ~reset->signals[id].mask;
+ value |= reset->signals[id].deassert_val;
+ }
+ spacemit_reset_write(reset, value, id);
+}
+
+static int spacemit_reset_update(struct reset_controller_dev *rcdev,
+ unsigned long id, bool assert)
+{
+ unsigned long flags;
+ struct spacemit_reset *reset = to_spacemit_reset(rcdev);
+
+ if(id < RESET_UART1 || id >= RESET_NUMBER)
+ return 0;
+
+ if (id == RESET_TWSI8)
+ return 0;
+
+ spin_lock_irqsave(reset->lock, flags);
+ if(assert == true){
+ spacemit_reset_set(rcdev, id, assert);
+ }
+ else{
+ spacemit_reset_set(rcdev, id, assert);
+ }
+ spin_unlock_irqrestore(reset->lock, flags);
+ return 0;
+}
+
+static int spacemit_reset_assert(struct reset_controller_dev *rcdev,
+ unsigned long id)
+{
+ return spacemit_reset_update(rcdev, id, true);
+}
+
+static int spacemit_reset_deassert(struct reset_controller_dev *rcdev,
+ unsigned long id)
+{
+ return spacemit_reset_update(rcdev, id, false);
+}
+
+static const struct spacemit_reset_variant k1x_reset_data = {
+ .signals = k1x_reset_signals,
+ .signals_num = ARRAY_SIZE(k1x_reset_signals),
+ .ops = {
+ .assert = spacemit_reset_assert,
+ .deassert = spacemit_reset_deassert,
+ },
+};
+
+static void spacemit_reset_init(struct device_node *np)
+{
+ struct spacemit_reset *reset;
+
+ //LOG_INFO("init reset");
+ if (of_device_is_compatible(np, "spacemit,k1x-reset")){
+ reset = &k1x_reset_controller;
+ reset->mpmu_base = of_iomap(np, 0);
+ if (!reset->mpmu_base) {
+ pr_err("failed to map mpmu registers\n");
+ goto out;
+ }
+
+ reset->apmu_base = of_iomap(np, 1);
+ if (!reset->apmu_base) {
+ pr_err("failed to map apmu registers\n");
+ goto out;
+ }
+
+ reset->apbc_base = of_iomap(np, 2);
+ if (!reset->apbc_base) {
+ pr_err("failed to map apbc registers\n");
+ goto out;
+ }
+
+ reset->apbs_base = of_iomap(np, 3);
+ if (!reset->apbs_base) {
+ pr_err("failed to map apbs registers\n");
+ goto out;
+ }
+
+ reset->ciu_base = of_iomap(np, 4);
+ if (!reset->ciu_base) {
+ pr_err("failed to map ciu registers\n");
+ goto out;
+ }
+
+ reset->dciu_base = of_iomap(np, 5);
+ if (!reset->dciu_base) {
+ pr_err("failed to map dragon ciu registers\n");
+ goto out;
+ }
+
+ reset->ddrc_base = of_iomap(np, 6);
+ if (!reset->ddrc_base) {
+ pr_err("failed to map ddrc registers\n");
+ goto out;
+ }
+
+ reset->apbc2_base = of_iomap(np, 7);
+ if (!reset->apbc2_base) {
+ pr_err("failed to map apbc2 registers\n");
+ goto out;
+ }
+
+ reset->rcpu_base = of_iomap(np, 8);
+ if (!reset->rcpu_base) {
+ pr_err("failed to map rcpu registers\n");
+ goto out;
+ }
+
+ reset->rcpu2_base = of_iomap(np, 9);
+ if (!reset->rcpu2_base) {
+ pr_err("failed to map rcpu2 registers\n");
+ goto out;
+ }
+ }
+
+ reset->lock = &g_cru_lock;
+ reset->signals = k1x_reset_data.signals;
+ reset->rcdev.owner = THIS_MODULE;
+ reset->rcdev.nr_resets = k1x_reset_data.signals_num;
+ reset->rcdev.ops = &k1x_reset_data.ops;
+ reset->rcdev.of_node = np;
+ //LOG_INFO("register");
+ reset_controller_register(&reset->rcdev);
+out:
+ return;
+}
+
+CLK_OF_DECLARE(k1x_reset, "spacemit,k1x-reset", spacemit_reset_init);
+
--
Armbian

View File

@@ -1,722 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Patrick Yavitz <pyavitz@armbian.com>
Date: Fri, 21 Jun 2024 11:54:06 -0400
Subject: add spacemit patch set
source: https://gitee.com/bianbu-linux/linux-6.1
Signed-off-by: Patrick Yavitz <pyavitz@armbian.com>
---
drivers/rtc/Kconfig | 9 +-
drivers/rtc/Makefile | 1 +
drivers/rtc/rtc-sa1100.c | 18 +
drivers/rtc/rtc-sa1100.h | 1 +
drivers/rtc/rtc-spt-pmic.c | 577 ++++++++++
5 files changed, 605 insertions(+), 1 deletion(-)
diff --git a/drivers/rtc/Kconfig b/drivers/rtc/Kconfig
index 111111111111..222222222222 100644
--- a/drivers/rtc/Kconfig
+++ b/drivers/rtc/Kconfig
@@ -724,6 +724,13 @@ config RTC_DRV_SD3078
This driver can also be built as a module. If so, the module
will be called rtc-sd3078
+config RTC_DRV_SPT_PMIC
+ tristate "Spacemit spm8xxx RTC"
+ depends on MFD_SPACEMIT_PMIC
+ help
+ If you say yes here you will get support for the
+ RTC of Spacemit spm8xxx PMIC.
+
endif # I2C
comment "SPI RTC drivers"
@@ -1458,7 +1465,7 @@ config RTC_DRV_EP93XX
config RTC_DRV_SA1100
tristate "SA11x0/PXA2xx/PXA910"
- depends on ARCH_SA1100 || ARCH_PXA || ARCH_MMP
+ depends on ARCH_SA1100 || ARCH_PXA || ARCH_MMP || SOC_SPACEMIT_K1X
help
If you say Y here you will get access to the real time clock
built into your SA11x0 or PXA2xx CPU.
diff --git a/drivers/rtc/Makefile b/drivers/rtc/Makefile
index 111111111111..222222222222 100644
--- a/drivers/rtc/Makefile
+++ b/drivers/rtc/Makefile
@@ -186,3 +186,4 @@ obj-$(CONFIG_RTC_DRV_WM8350) += rtc-wm8350.o
obj-$(CONFIG_RTC_DRV_X1205) += rtc-x1205.o
obj-$(CONFIG_RTC_DRV_XGENE) += rtc-xgene.o
obj-$(CONFIG_RTC_DRV_ZYNQMP) += rtc-zynqmp.o
+obj-$(CONFIG_RTC_DRV_SPT_PMIC) += rtc-spt-pmic.o
diff --git a/drivers/rtc/rtc-sa1100.c b/drivers/rtc/rtc-sa1100.c
index 111111111111..222222222222 100644
--- a/drivers/rtc/rtc-sa1100.c
+++ b/drivers/rtc/rtc-sa1100.c
@@ -20,6 +20,7 @@
#include <linux/platform_device.h>
#include <linux/module.h>
#include <linux/clk.h>
+#include <linux/reset.h>
#include <linux/rtc.h>
#include <linux/init.h>
#include <linux/fs.h>
@@ -80,7 +81,10 @@ static irqreturn_t sa1100_rtc_interrupt(int irq, void *dev_id)
/* update irq data & counter */
if (rtsr & RTSR_AL)
+ {
events |= RTC_AF | RTC_IRQF;
+ printk("rtc hit alarm\n");
+ }
if (rtsr & RTSR_HZ)
events |= RTC_UF | RTC_IRQF;
@@ -186,6 +190,10 @@ int sa1100_rtc_init(struct platform_device *pdev, struct sa1100_rtc *info)
ret = clk_prepare_enable(info->clk);
if (ret)
return ret;
+
+ ret = reset_control_deassert(info->reset);
+ if(ret)
+ goto free_clk;
/*
* According to the manual we should be able to let RTTR be zero
* and then a default diviser for a 32.768KHz clock is used.
@@ -207,6 +215,7 @@ int sa1100_rtc_init(struct platform_device *pdev, struct sa1100_rtc *info)
ret = devm_rtc_register_device(info->rtc);
if (ret) {
+ reset_control_assert(info->reset);
clk_disable_unprepare(info->clk);
return ret;
}
@@ -236,6 +245,10 @@ int sa1100_rtc_init(struct platform_device *pdev, struct sa1100_rtc *info)
writel_relaxed(RTSR_AL | RTSR_HZ, info->rtsr);
return 0;
+
+free_clk:
+ clk_disable_unprepare(info->clk);
+ return ret;
}
EXPORT_SYMBOL_GPL(sa1100_rtc_init);
@@ -274,6 +287,10 @@ static int sa1100_rtc_probe(struct platform_device *pdev)
return ret;
}
+ info->reset = devm_reset_control_get_optional(&pdev->dev, NULL);
+ if(IS_ERR(info->reset))
+ return PTR_ERR(info->reset);
+
base = devm_platform_ioremap_resource(pdev, 0);
if (IS_ERR(base))
return PTR_ERR(base);
@@ -305,6 +322,7 @@ static int sa1100_rtc_remove(struct platform_device *pdev)
spin_lock_irq(&info->lock);
writel_relaxed(0, info->rtsr);
spin_unlock_irq(&info->lock);
+ reset_control_assert(info->reset);
clk_disable_unprepare(info->clk);
}
diff --git a/drivers/rtc/rtc-sa1100.h b/drivers/rtc/rtc-sa1100.h
index 111111111111..222222222222 100644
--- a/drivers/rtc/rtc-sa1100.h
+++ b/drivers/rtc/rtc-sa1100.h
@@ -17,6 +17,7 @@ struct sa1100_rtc {
int irq_alarm;
struct rtc_device *rtc;
struct clk *clk;
+ struct reset_control *reset;
};
int sa1100_rtc_init(struct platform_device *pdev, struct sa1100_rtc *info);
diff --git a/drivers/rtc/rtc-spt-pmic.c b/drivers/rtc/rtc-spt-pmic.c
new file mode 100644
index 000000000000..111111111111
--- /dev/null
+++ b/drivers/rtc/rtc-spt-pmic.c
@@ -0,0 +1,577 @@
+// SPDX-License-Identifier: GPL-2.0-only
+#include <linux/of.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/rtc.h>
+#include <linux/platform_device.h>
+#include <linux/pm.h>
+#include <linux/pm_wakeirq.h>
+#include <linux/of_device.h>
+#include <linux/regmap.h>
+#include <linux/slab.h>
+#include <linux/mfd/spacemit/spacemit_pmic.h>
+
+SPM8821_RTC_REG_DESC;
+
+struct spacemit_rtc {
+ int irq;
+ struct device *dev;
+ struct regmap *regmap;
+ struct rtc_device *rtc_dev;
+ struct rtc_regdesc *desc;
+};
+
+static const struct of_device_id spacemit_id_table[] = {
+ { .compatible = "pmic,rtc,spm8821", .data = &spm8821_regdesc, },
+ { },
+};
+MODULE_DEVICE_TABLE(of, spacemit_id_table);
+
+static irqreturn_t spt_rtc_irq(int irq, void *_pwr)
+{
+ struct spacemit_rtc *rtc = (struct spacemit_rtc *)_pwr;
+
+ rtc_update_irq(rtc->rtc_dev, 1, RTC_IRQF | RTC_AF);
+
+ return IRQ_HANDLED;
+}
+
+static int spt_rtc_read_time(struct device *dev, struct rtc_time *tm)
+{
+ int ret;
+ unsigned int v[6], pre_v[6] = {0};
+ struct spacemit_rtc *rtc = dev_get_drvdata(dev);
+
+ ret = regmap_read(rtc->regmap, rtc->desc->cnt_s.reg, &pre_v[0]);
+ if (ret) {
+ dev_err(rtc->dev, "failed to read second: %d\n", ret);
+ return -EINVAL;
+ }
+
+ ret = regmap_read(rtc->regmap, rtc->desc->cnt_mi.reg, &pre_v[1]);
+ if (ret) {
+ dev_err(rtc->dev, "failed to read minute: %d\n", ret);
+ return -EINVAL;
+ }
+
+ ret = regmap_read(rtc->regmap, rtc->desc->cnt_h.reg, &pre_v[2]);
+ if (ret) {
+ dev_err(rtc->dev, "failed to read hour: %d\n", ret);
+ return -EINVAL;
+ }
+
+ ret = regmap_read(rtc->regmap, rtc->desc->cnt_d.reg, &pre_v[3]);
+ if (ret) {
+ dev_err(rtc->dev, "failed to read day: %d\n", ret);
+ return -EINVAL;
+ }
+
+ ret = regmap_read(rtc->regmap, rtc->desc->cnt_mo.reg, &pre_v[4]);
+ if (ret) {
+ dev_err(rtc->dev, "failed to read month: %d\n", ret);
+ return -EINVAL;
+ }
+
+ ret = regmap_read(rtc->regmap, rtc->desc->cnt_y.reg, &pre_v[5]);
+ if (ret) {
+ dev_err(rtc->dev, "failed to read year: %d\n", ret);
+ return -EINVAL;
+ }
+
+ while (1) {
+ ret = regmap_read(rtc->regmap, rtc->desc->cnt_s.reg, &v[0]);
+ if (ret) {
+ dev_err(rtc->dev, "failed to read second: %d\n", ret);
+ return -EINVAL;
+ }
+
+ ret = regmap_read(rtc->regmap, rtc->desc->cnt_mi.reg, &v[1]);
+ if (ret) {
+ dev_err(rtc->dev, "failed to read minute: %d\n", ret);
+ return -EINVAL;
+ }
+
+ ret = regmap_read(rtc->regmap, rtc->desc->cnt_h.reg, &v[2]);
+ if (ret) {
+ dev_err(rtc->dev, "failed to read hour: %d\n", ret);
+ return -EINVAL;
+ }
+
+ ret = regmap_read(rtc->regmap, rtc->desc->cnt_d.reg, &v[3]);
+ if (ret) {
+ dev_err(rtc->dev, "failed to read day: %d\n", ret);
+ return -EINVAL;
+ }
+
+ ret = regmap_read(rtc->regmap, rtc->desc->cnt_mo.reg, &v[4]);
+ if (ret) {
+ dev_err(rtc->dev, "failed to read month: %d\n", ret);
+ return -EINVAL;
+ }
+
+ ret = regmap_read(rtc->regmap, rtc->desc->cnt_y.reg, &v[5]);
+ if (ret) {
+ dev_err(rtc->dev, "failed to read year: %d\n", ret);
+ return -EINVAL;
+ }
+
+ if ((pre_v[0] == v[0]) && (pre_v[1] == v[1]) &&
+ (pre_v[2] == v[2]) && (pre_v[3] == v[3]) &&
+ (pre_v[4] == v[4]) && (pre_v[5] == v[5]))
+ break;
+ else {
+ pre_v[0] = v[0];
+ pre_v[1] = v[1];
+ pre_v[2] = v[2];
+ pre_v[3] = v[3];
+ pre_v[4] = v[4];
+ pre_v[5] = v[5];
+ }
+ }
+
+ tm->tm_sec = v[0] & rtc->desc->cnt_s.msk;
+ tm->tm_min = v[1] & rtc->desc->cnt_mi.msk;
+ tm->tm_hour = v[2] & rtc->desc->cnt_h.msk;
+ tm->tm_mday = (v[3] & rtc->desc->cnt_d.msk) + 1;
+ tm->tm_mon = (v[4] & rtc->desc->cnt_mo.msk);
+ tm->tm_year = (v[5] & rtc->desc->cnt_y.msk) + 100;
+
+ pr_debug("%s:%d, s:%d, min:%d, hour:%d, mday:%d, month:%d, year:%d\n",
+ __func__, __LINE__,
+ tm->tm_sec,
+ tm->tm_min,
+ tm->tm_hour,
+ tm->tm_mday,
+ tm->tm_mon,
+ tm->tm_year);
+
+ return 0;
+}
+
+static int spt_rtc_set_time(struct device *dev, struct rtc_time *tm)
+{
+ int ret;
+ unsigned int v[6];
+ union rtc_ctl_desc rtc_ctl;
+ struct spacemit_rtc *rtc = dev_get_drvdata(dev);
+
+ pr_debug("%s:%d, s:%d, min:%d, hour:%d, mday:%d, month:%d, year:%d\n",
+ __func__, __LINE__,
+ tm->tm_sec,
+ tm->tm_min,
+ tm->tm_hour,
+ tm->tm_mday,
+ tm->tm_mon,
+ tm->tm_year);
+
+ ret = regmap_read(rtc->regmap, rtc->desc->rtc_ctl.reg, (unsigned int *)&rtc_ctl.val);
+ if (ret) {
+ dev_err(rtc->dev, "failed to read rtc ctrl: %d\n", ret);
+ return -EINVAL;
+ }
+
+ /* disbale rtc first */
+ rtc_ctl.bits.rtc_en = 0;
+
+ ret = regmap_write_bits(rtc->regmap, rtc->desc->rtc_ctl.reg,
+ 0xff, rtc_ctl.val);
+ if (ret) {
+ dev_err(rtc->dev, "failed to set rtc ctrl register: %d\n", ret);
+ return -EINVAL;
+ }
+
+ while (1) {
+ ret = regmap_write_bits(rtc->regmap, rtc->desc->cnt_s.reg,
+ rtc->desc->cnt_s.msk, tm->tm_sec);
+ if (ret) {
+ dev_err(rtc->dev, "failed to update second: %d\n", ret);
+ return -EINVAL;
+ }
+
+ ret = regmap_write_bits(rtc->regmap, rtc->desc->cnt_mi.reg,
+ rtc->desc->cnt_mi.msk, tm->tm_min);
+ if (ret) {
+ dev_err(rtc->dev, "failed to update minutes: %d\n", ret);
+ return -EINVAL;
+ }
+
+ ret = regmap_write_bits(rtc->regmap, rtc->desc->cnt_h.reg,
+ rtc->desc->cnt_h.msk, tm->tm_hour);
+ if (ret) {
+ dev_err(rtc->dev, "failed to update hour: %d\n", ret);
+ return -EINVAL;
+ }
+
+ ret = regmap_write_bits(rtc->regmap, rtc->desc->cnt_d.reg,
+ rtc->desc->cnt_d.msk, tm->tm_mday - 1);
+ if (ret) {
+ dev_err(rtc->dev, "failed to update day: %d\n", ret);
+ return -EINVAL;
+ }
+
+ ret = regmap_write_bits(rtc->regmap, rtc->desc->cnt_mo.reg,
+ rtc->desc->cnt_mo.msk, tm->tm_mon);
+ if (ret) {
+ dev_err(rtc->dev, "failed to update month: %d\n", ret);
+ return -EINVAL;
+ }
+
+ ret = regmap_write_bits(rtc->regmap, rtc->desc->cnt_y.reg,
+ rtc->desc->cnt_y.msk, tm->tm_year - 100);
+ if (ret) {
+ dev_err(rtc->dev, "failed to update month: %d\n", ret);
+ return -EINVAL;
+ }
+
+ /* read again */
+ ret = regmap_read(rtc->regmap, rtc->desc->cnt_s.reg, &v[0]);
+ if (ret) {
+ dev_err(rtc->dev, "failed to read second: %d\n", ret);
+ return -EINVAL;
+ }
+ v[0] = v[0] & rtc->desc->cnt_s.msk;
+
+ ret = regmap_read(rtc->regmap, rtc->desc->cnt_mi.reg, &v[1]);
+ if (ret) {
+ dev_err(rtc->dev, "failed to read minute: %d\n", ret);
+ return -EINVAL;
+ }
+ v[1] = v[1] & rtc->desc->cnt_mi.msk;
+
+ ret = regmap_read(rtc->regmap, rtc->desc->cnt_h.reg, &v[2]);
+ if (ret) {
+ dev_err(rtc->dev, "failed to read hour: %d\n", ret);
+ return -EINVAL;
+ }
+ v[2] = v[2] & rtc->desc->cnt_h.msk;
+
+ ret = regmap_read(rtc->regmap, rtc->desc->cnt_d.reg, &v[3]);
+ if (ret) {
+ dev_err(rtc->dev, "failed to read day: %d\n", ret);
+ return -EINVAL;
+ }
+ v[3] = v[3] & rtc->desc->cnt_d.msk;
+
+ ret = regmap_read(rtc->regmap, rtc->desc->cnt_mo.reg, &v[4]);
+ if (ret) {
+ dev_err(rtc->dev, "failed to read month: %d\n", ret);
+ return -EINVAL;
+ }
+ v[4] = v[4] & rtc->desc->cnt_mo.msk;
+
+ ret = regmap_read(rtc->regmap, rtc->desc->cnt_y.reg, &v[5]);
+ if (ret) {
+ dev_err(rtc->dev, "failed to read year: %d\n", ret);
+ return -EINVAL;
+ }
+ v[5] = v[5] & rtc->desc->cnt_y.msk;
+
+ if ((v[0] == (rtc->desc->cnt_s.msk & tm->tm_sec)) &&
+ (v[1] == (rtc->desc->cnt_mi.msk & tm->tm_min)) &&
+ (v[2] == (rtc->desc->cnt_h.msk & tm->tm_hour)) &&
+ ((v[3] + 1) == (rtc->desc->cnt_d.msk & tm->tm_mday)) &&
+ (v[4] == (rtc->desc->cnt_mo.msk & tm->tm_mon)) &&
+ (v[5] == (rtc->desc->cnt_y.msk & (tm->tm_year - 100))))
+ break;
+ }
+
+ /* enable rtc last */
+ rtc_ctl.bits.rtc_en = 1;
+
+ ret = regmap_write_bits(rtc->regmap, rtc->desc->rtc_ctl.reg,
+ 0xff, rtc_ctl.val);
+ if (ret) {
+ dev_err(rtc->dev, "failed to set rtc ctrl register: %d\n", ret);
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int spt_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm)
+{
+ int ret;
+ unsigned int v[6];
+ union rtc_ctl_desc rtc_ctl;
+ struct spacemit_rtc *rtc = dev_get_drvdata(dev);
+
+ ret = regmap_read(rtc->regmap, rtc->desc->alarm_s.reg, &v[0]);
+ if (ret) {
+ dev_err(rtc->dev, "failed to read alarm second: %d\n", ret);
+ return -EINVAL;
+ }
+
+ ret = regmap_read(rtc->regmap, rtc->desc->alarm_mi.reg, &v[1]);
+ if (ret) {
+ dev_err(rtc->dev, "failed to read alarm minute: %d\n", ret);
+ return -EINVAL;
+ }
+
+ ret = regmap_read(rtc->regmap, rtc->desc->alarm_h.reg, &v[2]);
+ if (ret) {
+ dev_err(rtc->dev, "failed to read alarm hour: %d\n", ret);
+ return -EINVAL;
+ }
+
+ ret = regmap_read(rtc->regmap, rtc->desc->alarm_d.reg, &v[3]);
+ if (ret) {
+ dev_err(rtc->dev, "failed to read alarm day: %d\n", ret);
+ return -EINVAL;
+ }
+
+ ret = regmap_read(rtc->regmap, rtc->desc->alarm_mo.reg, &v[4]);
+ if (ret) {
+ dev_err(rtc->dev, "failed to read alarm month: %d\n", ret);
+ return -EINVAL;
+ }
+
+ ret = regmap_read(rtc->regmap, rtc->desc->alarm_y.reg, &v[5]);
+ if (ret) {
+ dev_err(rtc->dev, "failed to read alarm year: %d\n", ret);
+ return -EINVAL;
+ }
+
+ /* 2000:1:1:0:0:0 */
+ alrm->time.tm_sec = v[0] & rtc->desc->alarm_s.msk;
+ alrm->time.tm_min = v[1] & rtc->desc->alarm_mi.msk;
+ alrm->time.tm_hour = v[2] & rtc->desc->alarm_h.msk;
+ alrm->time.tm_mday = (v[3] & rtc->desc->alarm_d.msk) + 1;
+ alrm->time.tm_mon = (v[4] & rtc->desc->alarm_mo.msk);
+ alrm->time.tm_year = (v[5] & rtc->desc->alarm_y.msk) + 100;
+
+ pr_debug("%s:%d, s:%d, min:%d, hour:%d, mday:%d, month:%d, year:%d\n",
+ __func__, __LINE__,
+ alrm->time.tm_sec,
+ alrm->time.tm_min,
+ alrm->time.tm_hour,
+ alrm->time.tm_mday,
+ alrm->time.tm_mon,
+ alrm->time.tm_year);
+
+ ret = regmap_read(rtc->regmap, rtc->desc->rtc_ctl.reg, (unsigned int *)&rtc_ctl.val);
+ if (ret) {
+ dev_err(rtc->dev, "failed to read alarm second: %d\n", ret);
+ return -EINVAL;
+ }
+
+ alrm->enabled = rtc_ctl.bits.alarm_en;
+
+ return 0;
+}
+
+static int spt_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm)
+{
+ int ret;
+ union rtc_ctl_desc rtc_ctl;
+ struct spacemit_rtc *rtc = dev_get_drvdata(dev);
+
+ pr_debug("%s:%d, s:%d, min:%d, hour:%d, mday:%d, month:%d, year:%d\n",
+ __func__, __LINE__,
+ alrm->time.tm_sec,
+ alrm->time.tm_min,
+ alrm->time.tm_hour,
+ alrm->time.tm_mday,
+ alrm->time.tm_mon,
+ alrm->time.tm_year);
+
+ /* disable the alrm function first */
+ ret = regmap_read(rtc->regmap, rtc->desc->rtc_ctl.reg, (unsigned int *)&rtc_ctl.val);
+ if (ret) {
+ dev_err(rtc->dev, "failed to read rtc ctrl register: %d\n", ret);
+ return -EINVAL;
+ }
+
+ rtc_ctl.bits.alarm_en = 0;
+
+ ret = regmap_write_bits(rtc->regmap, rtc->desc->rtc_ctl.reg,
+ 0xff, rtc_ctl.val);
+ if (ret) {
+ dev_err(rtc->dev, "failed to set rtc ctrl register: %d\n", ret);
+ return -EINVAL;
+ }
+
+ ret = regmap_write_bits(rtc->regmap, rtc->desc->alarm_s.reg,
+ rtc->desc->alarm_s.msk, alrm->time.tm_sec);
+ if (ret) {
+ dev_err(rtc->dev, "failed to update alrm second: %d\n", ret);
+ return -EINVAL;
+ }
+
+ ret = regmap_write_bits(rtc->regmap, rtc->desc->alarm_mi.reg,
+ rtc->desc->alarm_mi.msk, alrm->time.tm_min);
+ if (ret) {
+ dev_err(rtc->dev, "failed to update alarm minutes: %d\n", ret);
+ return -EINVAL;
+ }
+
+ ret = regmap_write_bits(rtc->regmap, rtc->desc->alarm_h.reg,
+ rtc->desc->alarm_h.msk, alrm->time.tm_hour);
+ if (ret) {
+ dev_err(rtc->dev, "failed to update alarm hour: %d\n", ret);
+ return -EINVAL;
+ }
+
+ ret = regmap_write_bits(rtc->regmap, rtc->desc->alarm_d.reg,
+ rtc->desc->alarm_d.msk, alrm->time.tm_mday - 1);
+ if (ret) {
+ dev_err(rtc->dev, "failed to update alarm day: %d\n", ret);
+ return -EINVAL;
+ }
+
+ ret = regmap_write_bits(rtc->regmap, rtc->desc->alarm_mo.reg,
+ rtc->desc->alarm_mo.msk, alrm->time.tm_mon);
+ if (ret) {
+ dev_err(rtc->dev, "failed to update alarm month: %d\n", ret);
+ return -EINVAL;
+ }
+
+ ret = regmap_write_bits(rtc->regmap, rtc->desc->alarm_y.reg,
+ rtc->desc->alarm_y.msk, alrm->time.tm_year - 100);
+ if (ret) {
+ dev_err(rtc->dev, "failed to update month: %d\n", ret);
+ return -EINVAL;
+ }
+
+ if (alrm->enabled) {
+ rtc_ctl.bits.alarm_en = 1;
+
+ ret = regmap_write_bits(rtc->regmap, rtc->desc->rtc_ctl.reg,
+ 0xff, rtc_ctl.val);
+ if (ret) {
+ dev_err(rtc->dev, "failed to set rtc ctrl register: %d\n", ret);
+ return -EINVAL;
+ }
+ }
+
+ return 0;
+}
+
+static int spt_rtc_alarm_irq_enable(struct device *dev, unsigned int enabled)
+{
+ int ret;
+ union rtc_ctl_desc rtc_ctl;
+ struct spacemit_rtc *rtc = dev_get_drvdata(dev);
+
+ ret = regmap_read(rtc->regmap, rtc->desc->rtc_ctl.reg, (unsigned int *)&rtc_ctl.val);
+ if (ret) {
+ dev_err(rtc->dev, "failed to read rtc ctrl register: %d\n", ret);
+ return -EINVAL;
+ }
+
+ if (enabled)
+ rtc_ctl.bits.alarm_en = 1;
+ else
+ rtc_ctl.bits.alarm_en = 0;
+
+ ret = regmap_write_bits(rtc->regmap, rtc->desc->rtc_ctl.reg,
+ 0xff, rtc_ctl.val);
+ if (ret) {
+ dev_err(rtc->dev, "failed to set rtc ctrl register: %d\n", ret);
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static const struct rtc_class_ops spt_rtc_ops = {
+ .read_time = spt_rtc_read_time,
+ .set_time = spt_rtc_set_time,
+ .read_alarm = spt_rtc_read_alarm,
+ .set_alarm = spt_rtc_set_alarm,
+ .alarm_irq_enable = spt_rtc_alarm_irq_enable,
+};
+
+static int spacemit_rtc_probe(struct platform_device *pdev)
+{
+ int ret = 0;
+ struct spacemit_rtc *rtc;
+ union rtc_ctl_desc rtc_ctl;
+ const struct of_device_id *of_id;
+ struct spacemit_pmic *pmic = dev_get_drvdata(pdev->dev.parent);
+
+ rtc = devm_kzalloc(&pdev->dev, sizeof(struct spacemit_rtc), GFP_KERNEL);
+ if (!rtc)
+ return -ENOMEM;
+
+ of_id = of_match_device(spacemit_id_table, &pdev->dev);
+ if (!of_id) {
+ pr_err("Unable to match OF ID\n");
+ return -ENODEV;
+ }
+
+ rtc->regmap = pmic->regmap;
+ rtc->dev = &pdev->dev;
+ rtc->desc = (struct rtc_regdesc *)of_id->data;
+ rtc->irq = platform_get_irq(pdev, 0);
+ if (rtc->irq < 0) {
+ dev_err(&pdev->dev, "get rtc irq error: %d\n", rtc->irq);
+ return -EINVAL;
+ }
+
+ dev_set_drvdata(&pdev->dev, rtc);
+
+ ret = devm_request_any_context_irq(&pdev->dev, rtc->irq,
+ spt_rtc_irq,
+ IRQF_TRIGGER_NONE | IRQF_ONESHOT,
+ "rtc@pmic", rtc);
+ if (ret < 0) {
+ dev_err(&pdev->dev, "Can't register rtc irq: %d\n", ret);
+ return -EINVAL;
+ }
+
+ dev_pm_set_wake_irq(&pdev->dev, rtc->irq);
+ device_init_wakeup(&pdev->dev, 1);
+
+ rtc->rtc_dev = devm_rtc_allocate_device(&pdev->dev);
+ if (IS_ERR(rtc->rtc_dev))
+ return PTR_ERR(rtc->rtc_dev);
+
+ rtc->rtc_dev->ops = &spt_rtc_ops;
+ rtc->rtc_dev->range_min = RTC_TIMESTAMP_BEGIN_2000;
+ rtc->rtc_dev->range_max = RTC_TIMESTAMP_END_2063;
+
+ ret = devm_rtc_register_device(rtc->rtc_dev);
+ if (ret) {
+ dev_err(&pdev->dev, "register rtc device error: %d\n", ret);
+ return -EINVAL;
+ }
+
+ /* enable the rtc function */
+ ret = regmap_read(rtc->regmap, rtc->desc->rtc_ctl.reg, (unsigned int *)&rtc_ctl.val);
+ if (ret) {
+ dev_err(rtc->dev, "failed to read rtc ctrl register: %d\n", ret);
+ return -EINVAL;
+ }
+
+ /* internal 32k clk */
+ rtc_ctl.bits.rtc_clk_sel = 1;
+ /* enable rtc */
+ rtc_ctl.bits.rtc_en = 1;
+ /* rtc clk out enable */
+ rtc_ctl.bits.out_32k_en = 1;
+ /* enable external crystal */
+ rtc_ctl.bits.crystal_en = 1;
+
+ ret = regmap_update_bits(rtc->regmap, rtc->desc->rtc_ctl.reg,
+ 0xff, rtc_ctl.val);
+ if (ret) {
+ dev_err(rtc->dev, "failed to set rtc ctrl register: %d\n", ret);
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static struct platform_driver spacemit_pmic_rtc_driver = {
+ .probe = spacemit_rtc_probe,
+ .driver = {
+ .name = "spacemit-pmic-rtc",
+ .of_match_table = spacemit_id_table,
+ },
+};
+
+module_platform_driver(spacemit_pmic_rtc_driver);
+
+MODULE_ALIAS("platform:rtc-spt-pmic");
+MODULE_DESCRIPTION("PMIC RTC driver");
+MODULE_LICENSE("GPL v2");
--
Armbian

File diff suppressed because it is too large Load Diff

View File

@@ -1,53 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Patrick Yavitz <pyavitz@armbian.com>
Date: Fri, 21 Jun 2024 11:54:06 -0400
Subject: add spacemit patch set
source: https://gitee.com/bianbu-linux/linux-6.1
Signed-off-by: Patrick Yavitz <pyavitz@armbian.com>
---
drivers/target/target_core_transport.c | 13 ++++++++++
1 file changed, 13 insertions(+)
diff --git a/drivers/target/target_core_transport.c b/drivers/target/target_core_transport.c
index 111111111111..222222222222 100644
--- a/drivers/target/target_core_transport.c
+++ b/drivers/target/target_core_transport.c
@@ -2764,6 +2764,9 @@ target_alloc_sgl(struct scatterlist **sgl, unsigned int *nents, u32 length,
{
gfp_t gfp = GFP_KERNEL | (zero_page ? __GFP_ZERO : 0);
+#if defined(CONFIG_SOC_SPACEMIT_K1X)
+ gfp |= GFP_DMA32;
+#endif
*sgl = sgl_alloc_order(length, 0, chainable, gfp, nents);
return *sgl ? 0 : -ENOMEM;
}
@@ -3133,6 +3136,10 @@ static const char *target_tmf_name(enum tcm_tmreq_table tmf)
case TMR_TARGET_WARM_RESET: return "TARGET_WARM_RESET";
case TMR_TARGET_COLD_RESET: return "TARGET_COLD_RESET";
case TMR_LUN_RESET_PRO: return "LUN_RESET_PRO";
+ case TMR_I_T_NEXUS_RESET: return "I_T_NEXUS_RESET";
+ case TMR_QUERY_TASK: return "QUERY_TASK";
+ case TMR_QUERY_TASK_SET: return "QUERY_TASK_SET";
+ case TMR_QUERY_ASYNC_EVENT: return "QUERY_ASYNC_EVENT";
case TMR_UNKNOWN: break;
}
return "(?)";
@@ -3601,6 +3608,12 @@ static void target_tmr_work(struct work_struct *work)
case TMR_TARGET_COLD_RESET:
tmr->response = TMR_FUNCTION_REJECTED;
break;
+ case TMR_I_T_NEXUS_RESET:
+ case TMR_QUERY_TASK:
+ case TMR_QUERY_TASK_SET:
+ case TMR_QUERY_ASYNC_EVENT:
+ tmr->response = TMR_FUNCTION_REJECTED;
+ break;
default:
pr_err("Unknown TMR function: 0x%02x.\n",
tmr->function);
--
Armbian

View File

@@ -1,668 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Patrick Yavitz <pyavitz@armbian.com>
Date: Fri, 21 Jun 2024 11:54:06 -0400
Subject: add spacemit patch set
source: https://gitee.com/bianbu-linux/linux-6.1
Signed-off-by: Patrick Yavitz <pyavitz@armbian.com>
---
drivers/thermal/Kconfig | 14 +
drivers/thermal/Makefile | 2 +
drivers/thermal/hotplug_cooling.c | 160 +++++
drivers/thermal/k1x-thermal.c | 352 ++++++++++
drivers/thermal/k1x-thermal.h | 77 ++
5 files changed, 605 insertions(+)
diff --git a/drivers/thermal/Kconfig b/drivers/thermal/Kconfig
index 111111111111..222222222222 100644
--- a/drivers/thermal/Kconfig
+++ b/drivers/thermal/Kconfig
@@ -189,6 +189,13 @@ config CPU_IDLE_THERMAL
This implements the CPU cooling mechanism through
idle injection. This will throttle the CPU by injecting
idle cycle.
+
+config CPU_HOTPLUG_THERMAL
+ bool "CPU hotplug cooling device"
+ depends on HOTPLUG_CPU && SOC_SPACEMIT
+ help
+ This implements the CPU cooling mechanism through
+ cpu hotplug.
endif
config DEVFREQ_THERMAL
@@ -434,6 +441,13 @@ config AMLOGIC_THERMAL
This driver can also be built as a module. If so, the module will
be called amlogic_thermal.
+config K1X_THERMAL
+ tristate "Spacemit K1X Thermal Support"
+ depends on OF && SOC_SPACEMIT
+ help
+ Enable this option if you want to have support for thermal management
+ controller present in Spacemit SoCs
+
menu "Intel thermal drivers"
depends on X86 || X86_INTEL_QUARK || COMPILE_TEST
source "drivers/thermal/intel/Kconfig"
diff --git a/drivers/thermal/Makefile b/drivers/thermal/Makefile
index 111111111111..222222222222 100644
--- a/drivers/thermal/Makefile
+++ b/drivers/thermal/Makefile
@@ -61,3 +61,5 @@ obj-$(CONFIG_UNIPHIER_THERMAL) += uniphier_thermal.o
obj-$(CONFIG_AMLOGIC_THERMAL) += amlogic_thermal.o
obj-$(CONFIG_SPRD_THERMAL) += sprd_thermal.o
obj-$(CONFIG_KHADAS_MCU_FAN_THERMAL) += khadas_mcu_fan.o
+obj-$(CONFIG_K1X_THERMAL) += k1x-thermal.o
+obj-$(CONFIG_CPU_HOTPLUG_THERMAL) += hotplug_cooling.o
diff --git a/drivers/thermal/hotplug_cooling.c b/drivers/thermal/hotplug_cooling.c
new file mode 100644
index 000000000000..111111111111
--- /dev/null
+++ b/drivers/thermal/hotplug_cooling.c
@@ -0,0 +1,160 @@
+#include <linux/cpu.h>
+#include <linux/cpu_cooling.h>
+#include <linux/cpufreq.h>
+#include <linux/device.h>
+#include <linux/err.h>
+#include <linux/export.h>
+#include <linux/pm_opp.h>
+#include <linux/pm_qos.h>
+#include <linux/slab.h>
+#include <linux/thermal.h>
+#include <linux/units.h>
+
+struct hotplug_cooling_device {
+ unsigned int max_level;
+ unsigned int hotplug_state;
+ unsigned int cpu;
+ struct thermal_cooling_device_ops cooling_ops;
+};
+
+static int hotplug_get_max_state(struct thermal_cooling_device *cdev,
+ unsigned long *state)
+{
+ struct hotplug_cooling_device *hotplug_cdev = cdev->devdata;
+
+ *state = hotplug_cdev->max_level;
+ return 0;
+}
+
+static int hotplug_get_cur_state(struct thermal_cooling_device *cdev,
+ unsigned long *state)
+{
+ struct hotplug_cooling_device *hotplug_cdev = cdev->devdata;
+
+ *state = hotplug_cdev->hotplug_state;
+ return 0;
+}
+
+static int hotplug_set_cur_state(struct thermal_cooling_device *cdev,
+ unsigned long state)
+{
+ struct hotplug_cooling_device *hotplug_cdev = cdev->devdata;
+
+ /* Request state should be less than max_level */
+ if (state > hotplug_cdev->max_level)
+ return -EINVAL;
+
+ /* Check if the old cooling action is same as new cooling action */
+ if (hotplug_cdev->hotplug_state == state)
+ return 0;
+
+ hotplug_cdev->hotplug_state = state;
+
+ /* do some governors ? */
+ if (state == 1)
+ cpu_device_down(get_cpu_device(hotplug_cdev->cpu));
+ else
+ cpu_device_up(get_cpu_device(hotplug_cdev->cpu));
+
+ return 0;
+}
+
+static struct thermal_cooling_device *
+__hotplug_cooling_register(struct device_node *np, unsigned int cpu)
+{
+ char *name;
+ struct device *dev;
+ struct thermal_cooling_device *cdev;
+ struct hotplug_cooling_device *hotplug_cdev;
+ struct thermal_cooling_device_ops *cooling_ops;
+
+ dev = get_cpu_device(cpu);
+ if (unlikely(!dev)) {
+ pr_warn("No cpu device for cpu %d\n", cpu);
+ return ERR_PTR(-ENODEV);
+ }
+
+ hotplug_cdev = kzalloc(sizeof(*hotplug_cdev), GFP_KERNEL);
+ if (!hotplug_cdev)
+ return ERR_PTR(-ENOMEM);
+
+ hotplug_cdev->max_level = 1;
+ hotplug_cdev->cpu = cpu;
+ cooling_ops = &hotplug_cdev->cooling_ops;
+ cooling_ops->get_max_state = hotplug_get_max_state;
+ cooling_ops->get_cur_state = hotplug_get_cur_state;
+ cooling_ops->set_cur_state = hotplug_set_cur_state;
+
+ cdev = ERR_PTR(-ENOMEM);
+ name = kasprintf(GFP_KERNEL, "hotplug-%s", dev_name(dev));
+
+ cdev = thermal_of_cooling_device_register(np, name, hotplug_cdev,
+ cooling_ops);
+ kfree(name);
+
+ if (IS_ERR(cdev)) {
+ pr_err("%s: Failed to register hotplug cooling device (%p)\n", __func__, PTR_ERR(cdev));
+ return PTR_ERR(cdev);
+ }
+
+ return cdev;
+}
+
+struct thermal_cooling_device **
+of_hotplug_cooling_register(struct cpufreq_policy *policy)
+{
+ unsigned int cpu, num_cpus = 0, cpus = 0;
+ struct device_node *np = NULL;
+ struct device_node *cooling_node;
+ struct thermal_cooling_device **cdev = NULL;
+
+ for_each_cpu(cpu, policy->related_cpus)
+ ++ num_cpus;
+
+ cdev = kzalloc(sizeof(struct thermal_cooling_device *) * num_cpus, GFP_KERNEL);
+ if (!cdev) {
+ pr_err("hotplug_cooling: alloc cooling_device failed\n");
+ return NULL;
+ }
+
+ for_each_cpu(cpu, policy->related_cpus) {
+ np = of_get_cpu_node(cpu, NULL);
+ if (!np) {
+ pr_err("hotplug_cooling: OF node not available for cpu%d\n", cpu);
+ return NULL;
+ }
+
+ cooling_node = of_get_child_by_name(np, "thermal-hotplug");
+ if (of_find_property(cooling_node, "#cooling-cells", NULL)) {
+ cdev[cpus] = __hotplug_cooling_register(cooling_node, cpu);
+ if (IS_ERR(cdev)) {
+ pr_err("hotplug_cooling: cpu%d failed to register as cooling device: %ld\n",
+ cpu, PTR_ERR(cdev[cpus]));
+ cdev[cpus] = NULL;
+ }
+
+ ++cpus;
+ }
+
+ of_node_put(np);
+ }
+
+ return cdev;
+}
+EXPORT_SYMBOL_GPL(of_hotplug_cooling_register);
+
+void hotplug_cooling_unregister(struct cpufreq_policy *policy, struct thermal_cooling_device **cdev)
+{
+ unsigned int cpu;
+ struct hotplug_cooling_device *hotplug_cdev;
+
+ if (cdev)
+ return;
+
+ for_each_cpu(cpu, policy->related_cpus) {
+ hotplug_cdev = cdev[cpu]->devdata;
+ thermal_cooling_device_unregister(cdev[cpu]);
+ kfree(hotplug_cdev);
+ }
+}
+EXPORT_SYMBOL_GPL(hotplug_cooling_unregister);
diff --git a/drivers/thermal/k1x-thermal.c b/drivers/thermal/k1x-thermal.c
new file mode 100644
index 000000000000..111111111111
--- /dev/null
+++ b/drivers/thermal/k1x-thermal.c
@@ -0,0 +1,352 @@
+// SPDX-License-Identifier: GPL-2.0-only
+
+#include <linux/cpufreq.h>
+#include <linux/delay.h>
+#include <linux/interrupt.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/io.h>
+#include <linux/of_device.h>
+#include <linux/thermal.h>
+#include <linux/reset.h>
+#include "k1x-thermal.h"
+
+#define MAX_SENSOR_NUMBER 5
+
+static struct k1x_thermal_sensor_desc gsdesc[] = {
+ /* bjt0: local, sensor internal temperature */
+ [0] = {
+ .int_msk = 0x14, .int_clr = 0x10, .int_sta = 0x18, .offset = 0x0, .bit_msk = 0b110,
+ .se = { .bjt_en = 0x8, .en_val = 0x1, .offset = 0x0, .bit_msk = 0x1, },
+ .sd = { .data_reg = 0x20, .offset = 0x0, .bit_msk = 0xffff, },
+ .sr = { .temp_thrsh = 0x40, .low_offset = 0x0, .high_offset = 16, },
+ },
+
+ /* bjt1: top */
+ [1] = {
+ .int_msk = 0x14, .int_clr = 0x10, .int_sta = 0x18, .offset = 0x3, .bit_msk = 0b11000,
+ .se = { .bjt_en = 0x8, .en_val = 0x1, .offset = 0x1, .bit_msk = 0x2, },
+ .sd = { .data_reg = 0x20, .offset = 16, .bit_msk = 0xffff0000, },
+ .sr = { .temp_thrsh = 0x44, .low_offset = 0x0, .high_offset = 16, },
+ },
+
+ /* bjt2: gpu */
+ [2] = {
+ .int_msk = 0x14, .int_clr = 0x10, .int_sta = 0x18, .offset = 0x5, .bit_msk = 0b1100000,
+ .se = { .bjt_en = 0x8, .en_val = 0x1, .offset = 0x2, .bit_msk = 0x4, },
+ .sd = { .data_reg = 0x24, .offset = 0, .bit_msk = 0xffff, },
+ .sr = { .temp_thrsh = 0x48, .low_offset = 0x0, .high_offset = 16, },
+ },
+
+ /* bjt3: cluster0 */
+ [3] = {
+ .int_msk = 0x14, .int_clr = 0x10, .int_sta = 0x18, .offset = 0x7, .bit_msk = 0b110000000,
+ .se = { .bjt_en = 0x8, .en_val = 0x1, .offset = 0x3, .bit_msk = 0x8, },
+ .sd = { .data_reg = 0x24, .offset = 16, .bit_msk = 0xffff0000, },
+ .sr = { .temp_thrsh = 0x4c, .low_offset = 0x0, .high_offset = 16, },
+ },
+
+ /* bjt4: cluster1 */
+ [4] = {
+ .int_msk = 0x14, .int_clr = 0x10, .int_sta = 0x18, .offset = 0x9, .bit_msk = 0b11000000000,
+ .se = { .bjt_en = 0x8, .en_val = 0x1, .offset = 0x4, .bit_msk = 0x10, },
+ .sd = { .data_reg = 0x28, .offset = 0, .bit_msk = 0xffff, },
+ .sr = { .temp_thrsh = 0x50, .low_offset = 0x0, .high_offset = 16, },
+ },
+};
+
+static int init_sensors(struct platform_device *pdev)
+{
+ int ret, i;
+ unsigned int /* thresh, emrt, */ temp;
+ struct k1x_thermal_sensor *s = platform_get_drvdata(pdev);
+
+ /* read the sensor range */
+ ret = of_property_read_u32_array(pdev->dev.of_node, "sensor_range", s->sr, 2);
+ if (ret < 0) {
+ dev_err(&pdev->dev, "get sensor range error\n");
+ return ret;
+ }
+
+ if (s->sr[1] >= MAX_SENSOR_NUMBER) {
+ dev_err(&pdev->dev, "un-fitable sensor range\n");
+ return -EINVAL;
+ }
+
+#if 0
+ /* first get the emergent_reboot_thrsh */
+ ret = of_property_read_u32(pdev->dev.of_node,
+ "emergent_reboot_threshold",
+ &emrt);
+ if (ret) {
+ dev_err(&pdev->dev, "no emergent reboot threshold\n");
+ return ret;
+ }
+
+ thresh = (emrt + TEMPERATURE_OFFSET) & REG_EMERGENT_REBOOT_TEMP_THR_MSK;
+ writel(thresh, s->base + REG_EMERGENT_REBOOT_TEMP_THR);
+#endif
+
+ /* first: disable all the interrupts */
+ writel(0xffffffff, s->base + REG_TSEN_INT_MASK);
+
+#if 0
+ /* enable the emergent intterupt */
+ temp = readl(s->base + REG_TSEN_INT_MASK);
+ temp &= ~(1 << TSEN_EMERGENT_INT_OFFSET);
+ writel(temp, s->base + REG_TSEN_INT_MASK);
+#endif
+
+ /*
+ * Decrease filter period time from 0x4000 to 0x3000, that
+ * means decrease 1/4 ADC sampling time for each sensor.
+ */
+ temp = readl(s->base + REG_TSEN_TIME_CTRL);
+ temp &= ~BITS_TIME_CTRL_MASK;
+ temp |= VALUE_FILTER_PERIOD;
+ temp |= BITS_RST_ADC_CNT;
+ temp |= VALUE_WAIT_REF_CNT;
+ writel(temp, s->base + REG_TSEN_TIME_CTRL);
+
+ /*
+ * enable all sensors' auto mode, enable dither control,
+ * consecutive mode, and power up sensor.
+ */
+ temp = readl(s->base + REG_TSEN_PCTRL);
+ temp |= BIT_TSEN_RAW_SEL | BIT_TEMP_MODE | BIT_EN_SENSOR;
+ temp &= ~BITS_TSEN_SW_CTRL;
+ temp &= ~BITS_CTUNE;
+ writel(temp, s->base + REG_TSEN_PCTRL);
+
+ /* select 24M clk for high speed mode */
+ temp = readl(s->base + REG_TSEN_PCTRL2);
+ temp &= ~BITS_SDM_CLK_SEL;
+ temp |= BITS_SDM_CLK_SEL_24M;
+ writel(temp, s->base + REG_TSEN_PCTRL2);
+
+ /* enable the sensor interrupt */
+ for (i = s->sr[0]; i <= s->sr[1]; ++i) {
+ temp = readl(s->base + s->sdesc[i].se.bjt_en);
+ temp &= ~s->sdesc[i].se.bit_msk;
+ temp |= (s->sdesc[i].se.en_val << s->sdesc[i].se.offset);
+ writel(temp, s->base + s->sdesc[i].se.bjt_en);
+ }
+
+ return 0;
+}
+
+static void enable_sensors(struct platform_device *pdev)
+{
+ struct k1x_thermal_sensor *s = platform_get_drvdata(pdev);
+
+ writel(readl(s->base + REG_TSEN_INT_MASK) | TSEN_INT_MASK,
+ s->base + REG_TSEN_INT_MASK);
+ writel(readl(s->base + REG_TSEN_PCTRL) | BIT_HW_AUTO_MODE,
+ s->base + REG_TSEN_PCTRL);
+}
+
+static void enable_sensor_irq(struct k1x_thermal_sensor_desc *desc)
+{
+ unsigned int temp;
+
+ /* clear the interrupt */
+ temp = readl(desc->base + desc->int_clr);
+ temp |= desc->bit_msk;
+ writel(temp, desc->base + desc->int_clr);
+
+ /* enable the interrupt */
+ temp = readl(desc->base + desc->int_msk);
+ temp &= ~desc->bit_msk;
+ writel(temp, desc->base + desc->int_msk);
+}
+
+static int k1x_thermal_get_temp(struct thermal_zone_device *tz, int *temp)
+{
+ struct k1x_thermal_sensor_desc *desc = (struct k1x_thermal_sensor_desc *)tz->devdata;
+
+ *temp = readl(desc->base + desc->sd.data_reg);
+ *temp &= desc->sd.bit_msk;
+ *temp >>= desc->sd.offset;
+
+ *temp -= TEMPERATURE_OFFSET;
+
+ *temp *= 1000;
+
+ return 0;
+}
+
+static int k1x_thermal_set_trips(struct thermal_zone_device *tz, int low, int high)
+{
+ unsigned int temp;
+ int over_thrsh = high;
+ int under_thrsh = low;
+ struct k1x_thermal_sensor_desc *desc = (struct k1x_thermal_sensor_desc *)tz->devdata;
+
+ /* set overflow */
+ over_thrsh /= 1000;
+ over_thrsh += TEMPERATURE_OFFSET;
+
+ temp = readl(desc->base + desc->sr.temp_thrsh);
+ temp &= ~0xffff0000;
+ temp |= (over_thrsh << desc->sr.high_offset);
+ writel(temp, desc->base + desc->sr.temp_thrsh);
+
+ /* set underflow */
+ if (low < 0)
+ under_thrsh = 0;
+
+ under_thrsh /= 1000;
+ under_thrsh += TEMPERATURE_OFFSET;
+ temp = readl(desc->base + desc->sr.temp_thrsh);
+ temp &= ~0xffff;
+ temp |= (under_thrsh << desc->sr.low_offset);
+ writel(temp, desc->base + desc->sr.temp_thrsh);
+
+ return 0;
+}
+
+static const struct thermal_zone_device_ops k1x_of_thermal_ops = {
+ .get_temp = k1x_thermal_get_temp,
+ .set_trips = k1x_thermal_set_trips,
+};
+
+static irqreturn_t k1x_thermal_irq(int irq, void *data)
+{
+ unsigned int status, msk;
+ struct k1x_thermal_sensor_desc *desc = (struct k1x_thermal_sensor_desc *)data;
+
+ /* get the status */
+ status = readl(desc->base + desc->int_sta);
+ status &= desc->bit_msk;
+
+ if (status == 0x0)
+ return IRQ_HANDLED;
+
+ /* then clear the pending */
+ msk = readl(desc->base + desc->int_clr);
+ msk |= status;
+ writel(msk, desc->base + desc->int_clr);
+
+ return IRQ_WAKE_THREAD;
+}
+
+static irqreturn_t k1x_thermal_irq_thread(int irq, void *data)
+{
+ struct k1x_thermal_sensor_desc *desc = (struct k1x_thermal_sensor_desc *)data;
+
+ thermal_zone_device_update(desc->tzd, THERMAL_EVENT_UNSPECIFIED);
+
+ return IRQ_HANDLED;
+}
+
+static int k1x_thermal_probe(struct platform_device *pdev)
+{
+ int ret, i;
+ struct resource *res;
+ struct k1x_thermal_sensor *s;
+ struct device *dev = &pdev->dev;
+
+ s = devm_kzalloc(dev, sizeof(*s), GFP_KERNEL);
+ if (!s)
+ return -ENOMEM;
+
+ s->dev = dev;
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ s->base = devm_ioremap_resource(dev, res);
+ if (IS_ERR(s->base))
+ return PTR_ERR(s->base);
+
+ s->irq = platform_get_irq(pdev, 0);
+ if (s->irq < 0) {
+ dev_err(dev, "failed to get irq number\n");
+ return -EINVAL;
+ }
+
+ s->resets = devm_reset_control_get_optional(&pdev->dev, NULL);
+ if (IS_ERR(s->resets))
+ return PTR_ERR(s->resets);
+
+ reset_control_deassert(s->resets);
+
+ s->clk = devm_clk_get(dev, NULL);
+ if (IS_ERR(s->clk))
+ return PTR_ERR(s->clk);
+
+ clk_prepare_enable(s->clk);
+
+ s->sdesc = (struct k1x_thermal_sensor_desc *)of_device_get_match_data(dev);
+
+ platform_set_drvdata(pdev, s);
+
+ /* initialize the sensors */
+ ret = init_sensors(pdev);
+
+ /* then register the thermal zone */
+ for (i = s->sr[0]; i <= s->sr[1]; ++i) {
+ s->sdesc[i].base = s->base;
+
+ s->sdesc[i].tzd = devm_thermal_of_zone_register(dev,
+ i, s->sdesc + i, &k1x_of_thermal_ops);
+ if (IS_ERR(s->sdesc[i].tzd)) {
+ ret = PTR_ERR(s->sdesc[i].tzd);
+ dev_err(dev, "faild to register sensor id %d: %d\n",
+ i, ret);
+ return ret;
+ }
+
+ ret = devm_request_threaded_irq(dev, s->irq, k1x_thermal_irq,
+ k1x_thermal_irq_thread, IRQF_SHARED,
+ dev_name(&s->sdesc[i].tzd->device), s->sdesc + i);
+ if (ret < 0) {
+ dev_err(dev, "failed to request irq: %d\n", ret);
+ return ret;
+ }
+
+ /* enable sensor low & higth threshold interrupt */
+ enable_sensor_irq(s->sdesc + i);
+ }
+
+ /* enable the sensor interrupt & using auto mode */
+ enable_sensors(pdev);
+
+ return 0;
+}
+
+static int k1x_thermal_remove(struct platform_device *pdev)
+{
+ int i;
+ struct k1x_thermal_sensor *s = platform_get_drvdata(pdev);
+
+ /* disable the clk */
+ clk_disable_unprepare(s->clk);
+ reset_control_assert(s->resets);
+
+ for (i = s->sr[0]; i <= s->sr[1]; ++i) {
+ devm_thermal_of_zone_unregister(&pdev->dev, s->sdesc[i].tzd);
+ devm_free_irq(&pdev->dev, s->irq, s->sdesc + i);
+ }
+
+ return 0;
+}
+
+static const struct of_device_id of_k1x_thermal_match[] = {
+ {
+ .compatible = "spacemit,k1x-tsensor",
+ .data = (void *)gsdesc,
+ },
+ { /* end */ }
+};
+
+MODULE_DEVICE_TABLE(of, of_hisi_thermal_match);
+
+static struct platform_driver k1x_thermal_driver = {
+ .driver = {
+ .name = "k1x_thermal",
+ .of_match_table = of_k1x_thermal_match,
+ },
+ .probe = k1x_thermal_probe,
+ .remove = k1x_thermal_remove,
+};
+
+module_platform_driver(k1x_thermal_driver);
diff --git a/drivers/thermal/k1x-thermal.h b/drivers/thermal/k1x-thermal.h
new file mode 100644
index 000000000000..111111111111
--- /dev/null
+++ b/drivers/thermal/k1x-thermal.h
@@ -0,0 +1,77 @@
+#ifndef __K1X_THERMAL_H__
+#define __K1X_THERMAL_H__
+
+#define BITS(_start, _end) ((BIT(_end) - BIT(_start)) + BIT(_end))
+
+#define MAX_SENSOR_NUMBER 5
+#define TEMPERATURE_OFFSET 278
+
+#define REG_TSEN_INT_MASK 0x14
+#define TSEN_EMERGENT_INT_OFFSET 23
+#define REG_EMERGENT_REBOOT_TEMP_THR 0x68
+#define REG_EMERGENT_REBOOT_TEMP_THR_MSK 0xffff
+
+#define REG_TSEN_TIME_CTRL 0x0C
+#define BITS_TIME_CTRL_MASK BITS(0, 23)
+#define VALUE_FILTER_PERIOD (0x3000 << 8)
+#define BITS_RST_ADC_CNT BITS(4, 7)
+#define VALUE_WAIT_REF_CNT (0xf << 0)
+
+#define BIT_TSEN_RAW_SEL BIT(7)
+#define BIT_TEMP_MODE BIT(3)
+#define BIT_EN_SENSOR BIT(0)
+#define BITS_TSEN_SW_CTRL BITS(18, 21)
+#define BITS_CTUNE BITS(8, 11)
+#define REG_TSEN_PCTRL 0x00
+
+#define REG_TSEN_PCTRL2 0x04
+#define BITS_SDM_CLK_SEL BITS(14, 15)
+#define BITS_SDM_CLK_SEL_24M (0 << 14)
+
+#define TSEN_INT_MASK BIT(0)
+#define BIT_HW_AUTO_MODE BIT(23)
+
+struct sensor_enable {
+ unsigned int bjt_en;
+ unsigned int offset;
+ unsigned int bit_msk;
+ unsigned int en_val;
+};
+
+struct sensor_data {
+ unsigned int data_reg;
+ unsigned int offset;
+ unsigned int bit_msk;
+};
+
+struct sensor_thrsh {
+ unsigned int temp_thrsh;
+ unsigned int low_offset;
+ unsigned int high_offset;
+};
+
+struct k1x_thermal_sensor_desc {
+ void __iomem *base;
+ unsigned int int_msk;
+ unsigned int int_clr;
+ unsigned int int_sta;
+ unsigned int offset;
+ unsigned int bit_msk;
+ struct sensor_enable se;
+ struct sensor_data sd;
+ struct sensor_thrsh sr;
+ struct thermal_zone_device *tzd;
+};
+
+struct k1x_thermal_sensor {
+ int irq;
+ void __iomem *base;
+ struct clk *clk;
+ struct reset_control *resets;
+ struct device *dev;
+ /* sensor range */
+ unsigned int sr[2];
+ struct k1x_thermal_sensor_desc *sdesc;
+};
+
+#endif
--
Armbian

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -1,143 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Patrick Yavitz <pyavitz@armbian.com>
Date: Fri, 21 Jun 2024 11:54:06 -0400
Subject: add spacemit patch set
source: https://gitee.com/bianbu-linux/linux-6.1
Signed-off-by: Patrick Yavitz <pyavitz@armbian.com>
---
drivers/video/fbdev/core/fbcon.c | 24 +++++-----
drivers/video/fbdev/core/fbmem.c | 2 +
2 files changed, 14 insertions(+), 12 deletions(-)
diff --git a/drivers/video/fbdev/core/fbcon.c b/drivers/video/fbdev/core/fbcon.c
index 111111111111..222222222222 100644
--- a/drivers/video/fbdev/core/fbcon.c
+++ b/drivers/video/fbdev/core/fbcon.c
@@ -26,7 +26,7 @@
*
* Hardware cursor support added by Emmanuel Marty (core@ggi-project.org)
* Smart redraw scrolling, arbitrary font width support, 512char font support
- * and software scrollback added by
+ * and software scrollback added by
* Jakub Jelinek (jj@ultra.linux.cz)
*
* Random hacking by Martin Mares <mj@ucw.cz>
@@ -127,7 +127,7 @@ static int logo_shown = FBCON_LOGO_CANSHOW;
/* console mappings */
static unsigned int first_fb_vc;
static unsigned int last_fb_vc = MAX_NR_CONSOLES - 1;
-static int fbcon_is_default = 1;
+static int fbcon_is_default = 1;
static int primary_device = -1;
static int fbcon_has_console_bind;
@@ -415,12 +415,12 @@ static int __init fb_console_setup(char *this_opt)
strscpy(fontname, options + 5, sizeof(fontname));
continue;
}
-
+
if (!strncmp(options, "scrollback:", 11)) {
pr_warn("Ignoring scrollback size option\n");
continue;
}
-
+
if (!strncmp(options, "map:", 4)) {
options += 4;
if (*options) {
@@ -446,7 +446,7 @@ static int __init fb_console_setup(char *this_opt)
last_fb_vc = simple_strtoul(options, &options, 10) - 1;
if (last_fb_vc < first_fb_vc || last_fb_vc >= MAX_NR_CONSOLES)
last_fb_vc = MAX_NR_CONSOLES - 1;
- fbcon_is_default = 0;
+ fbcon_is_default = 0;
continue;
}
@@ -940,7 +940,7 @@ static const char *fbcon_startup(void)
info = fbcon_registered_fb[info_idx];
if (!info)
return NULL;
-
+
if (fbcon_open(info))
return NULL;
@@ -1994,7 +1994,7 @@ static void updatescrollmode(struct fbcon_display *p,
#define PITCH(w) (((w) + 7) >> 3)
#define CALC_FONTSZ(h, p, c) ((h) * (p) * (c)) /* size = height * pitch * charcount */
-static int fbcon_resize(struct vc_data *vc, unsigned int width,
+static int fbcon_resize(struct vc_data *vc, unsigned int width,
unsigned int height, unsigned int user)
{
struct fb_info *info = fbcon_info_from_console(vc->vc_num);
@@ -2169,7 +2169,7 @@ static int fbcon_switch(struct vc_data *vc)
ops->update_start(info);
}
- fbcon_set_palette(vc, color_table);
+ fbcon_set_palette(vc, color_table);
fbcon_clear_margins(vc, 0);
if (logo_shown == FBCON_LOGO_DRAW) {
@@ -2338,7 +2338,7 @@ static void set_vc_hi_font(struct vc_data *vc, bool set)
vc->vc_complement_mask >>= 1;
vc->vc_s_complement_mask >>= 1;
}
-
+
/* ++Edmund: reorder the attribute bits */
if (vc->vc_can_do_color) {
unsigned short *cp =
@@ -2361,7 +2361,7 @@ static void set_vc_hi_font(struct vc_data *vc, bool set)
vc->vc_complement_mask <<= 1;
vc->vc_s_complement_mask <<= 1;
}
-
+
/* ++Edmund: reorder the attribute bits */
{
unsigned short *cp =
@@ -2524,7 +2524,7 @@ static int fbcon_set_font(struct vc_data *vc, struct console_font *font,
/* Check if the same font is on some other console already */
for (i = first_fb_vc; i <= last_fb_vc; i++) {
struct vc_data *tmp = vc_cons[i].d;
-
+
if (fb_display[i].userfont &&
fb_display[i].fontdata &&
FNTSUM(fb_display[i].fontdata) == csum &&
@@ -3432,5 +3432,5 @@ void __exit fb_console_exit(void)
do_unregister_con_driver(&fb_con);
console_unlock();
-}
+}
#endif
diff --git a/drivers/video/fbdev/core/fbmem.c b/drivers/video/fbdev/core/fbmem.c
index 111111111111..222222222222 100644
--- a/drivers/video/fbdev/core/fbmem.c
+++ b/drivers/video/fbdev/core/fbmem.c
@@ -678,6 +678,7 @@ int fb_prepare_logo(struct fb_info *info, int rotate)
}
height = fb_logo.logo->height;
+
if (fb_center_logo)
height += (yres - fb_logo.logo->height) / 2;
@@ -693,6 +694,7 @@ int fb_show_logo(struct fb_info *info, int rotate)
return 0;
count = fb_logo_count < 0 ? num_online_cpus() : fb_logo_count;
+
y = fb_show_logo_line(info, rotate, fb_logo.logo, 0, count);
y = fb_show_extra_logos(info, y, rotate);
--
Armbian

View File

@@ -1,907 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Patrick Yavitz <pyavitz@armbian.com>
Date: Fri, 21 Jun 2024 11:54:06 -0400
Subject: add spacemit patch set
source: https://gitee.com/bianbu-linux/linux-6.1
Signed-off-by: Patrick Yavitz <pyavitz@armbian.com>
---
drivers/watchdog/Kconfig | 14 +
drivers/watchdog/Makefile | 1 +
drivers/watchdog/k1x_wdt.c | 835 ++++++++++
fs/btrfs/sysfs.c | 2 +-
4 files changed, 851 insertions(+), 1 deletion(-)
diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig
index 111111111111..222222222222 100644
--- a/drivers/watchdog/Kconfig
+++ b/drivers/watchdog/Kconfig
@@ -2204,4 +2204,18 @@ config KEEMBAY_WATCHDOG
To compile this driver as a module, choose M here: the
module will be called keembay_wdt.
+config SPACEMIT_WATCHDOG
+ tristate "Spacemit-k1x SoC Watchdog"
+ depends on SOC_SPACEMIT_K1X
+ select WATCHDOG_CORE
+ help
+ spacemit k1x plat SoC Watchdog timer. This will reboot your system when
+ the timeout is reached.
+
+config K1X_WDT_TEST
+ bool "Support K1X watchdog test"
+ depends on SOC_SPACEMIT_K1X && SPACEMIT_WATCHDOG
+ help
+ This will enable K1X watchdog timer test
+
endif # WATCHDOG
diff --git a/drivers/watchdog/Makefile b/drivers/watchdog/Makefile
index 111111111111..222222222222 100644
--- a/drivers/watchdog/Makefile
+++ b/drivers/watchdog/Makefile
@@ -37,6 +37,7 @@ obj-$(CONFIG_USBPCWATCHDOG) += pcwd_usb.o
# ALPHA Architecture
# ARM Architecture
+obj-$(CONFIG_SPACEMIT_WATCHDOG) += k1x_wdt.o
obj-$(CONFIG_ARM_SP805_WATCHDOG) += sp805_wdt.o
obj-$(CONFIG_ARM_SBSA_WATCHDOG) += sbsa_gwdt.o
obj-$(CONFIG_ARMADA_37XX_WATCHDOG) += armada_37xx_wdt.o
diff --git a/drivers/watchdog/k1x_wdt.c b/drivers/watchdog/k1x_wdt.c
new file mode 100644
index 000000000000..111111111111
--- /dev/null
+++ b/drivers/watchdog/k1x_wdt.c
@@ -0,0 +1,835 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * spacemit-k1x watchdog driver
+ *
+ * Copyright (C) 2023 Spacemit
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/types.h>
+#include <linux/timer.h>
+#include <linux/miscdevice.h> /* for MODULE_ALIAS_MISCDEV */
+#include <linux/watchdog.h>
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/interrupt.h>
+#include <linux/clk.h>
+#include <linux/reset.h>
+#include <linux/uaccess.h>
+#include <linux/io.h>
+#include <linux/cpufreq.h>
+#include <linux/slab.h>
+#include <linux/err.h>
+#include <linux/delay.h>
+#include <linux/hrtimer.h>
+#include <asm/cacheflush.h>
+
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/of_device.h>
+#include <linux/reboot.h>
+
+/* Watchdog Timer Registers Offset */
+#define WDT_WMER (0x00b8)
+#define WDT_WMR (0x00bc)
+#define WDT_WVR (0x00cc)
+#define WDT_WCR (0x00c8)
+#define WDT_WSR (0x00c0)
+#define WDT_WFAR (0x00b0)
+#define WDT_WSAR (0x00b4)
+#define WDT_WICR (0x00c4)
+
+#define CONFIG_SPACEMIT_WATCHDOG_ATBOOT (0)
+/* default timeout is 60s */
+#define CONFIG_SPACEMIT_WATCHDOG_DEFAULT_TIME (60)
+#define SPACEMIT_WATCHDOG_MAX_TIMEOUT (255)
+#define SPACEMIT_WATCHDOG_EXPIRE_TIME (100)
+/* touch watchdog every 30s */
+#define SPACEMIT_WATCHDOG_FEED_TIMEOUT (30)
+
+#ifdef CONFIG_K1X_WDT_TEST
+#define K1X_WATCHDOG_IRQ_EXPIRE_TIME (16)
+#define K1X_WATCHDOG_IRQ_TEST_TIME (64)
+#define K1X_WATCHDOG_IRQ_TEST_ID 0
+#define K1X_WATCHDOG_RESET_TEST_ID 1
+#endif
+
+#define MPMU_APRR (0x1020)
+#define MPMU_APRR_WDTR (1<<4)
+#define DEFAULT_SHIFT (8)
+/*
+ * MPMU_APSR is a dummy reg which is used to handle reboot
+ * cmds. Its layout is:
+ * bit0~7: untouchable
+ * bit8~11: set to 0x1 when normal boot with no parameter
+ * set to 0x5 for other valid cmds.
+ */
+#define MPMU_ARSR (0x1028)
+#define MPMU_ARSR_REBOOT_CMD(x) ((x) << 8)
+#define MPMU_ARSR_SWR_MASK (0xf << 8)
+#define REBOOT_CMD_NORMAL 0x1
+#define REBOOT_CMD_VALID 0x5
+
+static bool nowayout = WATCHDOG_NOWAYOUT ? true : false;
+static spinlock_t reboot_lock;
+static DEFINE_MUTEX(wdt_clk_lock);
+
+phys_addr_t reboot_cmd_mem = 0;
+uint32_t reboot_cmd_size = 0;
+
+#ifdef CONFIG_K1X_WDT_TEST
+static int wdt_irq_count;
+#endif
+
+module_param(nowayout, bool, 0);
+
+MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default="
+ __MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
+
+static struct spa_wdt_info *syscore_info;
+struct spa_wdt_info {
+ void __iomem *wdt_base;
+ void __iomem *mpmu_base;
+ struct device *dev;
+ struct clk *clk;
+ struct reset_control *reset;
+ struct hrtimer feed_timer;
+ ktime_t feed_timeout;
+ spinlock_t wdt_lock;
+ struct watchdog_device wdt_dev;
+ int ctrl;
+ bool wdt_clk_open;
+ int enable_restart_handler;
+ struct notifier_block restart_handler;
+};
+
+void spa_wdt_shutdown_reason(char *cmd)
+{
+ void __iomem *mpmu_arsr;
+ u32 reg;
+
+ if (!syscore_info) {
+ pr_err("syscore_info not ready\n");
+ return;
+ }
+
+ if (!reboot_cmd_mem || !reboot_cmd_size) {
+ pr_err("No reboot cmd buffer reserved, cmd omitted!\n");
+ cmd = NULL;
+ }
+
+ if (cmd) {
+ if ((strlen(cmd) + 1) > reboot_cmd_size) {
+ pr_err("Reboot cmd len(%lu bytes) oversizes reserved mem (%d bytes), \
+ cmd omitted!\n", strlen(cmd) + 1, reboot_cmd_size);
+ cmd = NULL;
+ } else {
+ /* save cmd to reserved memory */
+ memcpy(phys_to_virt(reboot_cmd_mem), cmd, strlen(cmd) + 1);
+ printk("cmd = %s\n", cmd);
+ }
+ }
+
+ //set reboot flag
+ mpmu_arsr = syscore_info->mpmu_base + MPMU_ARSR;
+ reg = readl(mpmu_arsr);
+ reg &= ~MPMU_ARSR_SWR_MASK;
+ if (!cmd)
+ reg |= MPMU_ARSR_REBOOT_CMD(REBOOT_CMD_NORMAL);
+ else
+ reg |= MPMU_ARSR_REBOOT_CMD(REBOOT_CMD_VALID);
+ writel(reg, mpmu_arsr);
+}
+EXPORT_SYMBOL(spa_wdt_shutdown_reason);
+
+static inline u32 spa_wdt_read(struct spa_wdt_info *info,
+ unsigned reg)
+{
+ return readl(info->wdt_base + reg);
+}
+
+static inline void spa_wdt_write_access(struct spa_wdt_info *info)
+{
+ writel(0xbaba, info->wdt_base + WDT_WFAR);
+ writel(0xeb10, info->wdt_base + WDT_WSAR);
+}
+
+static inline void spa_wdt_write(struct spa_wdt_info *info,
+ unsigned reg, u32 val)
+{
+ spa_wdt_write_access(info);
+ writel(val, info->wdt_base + reg);
+}
+
+static int spa_wdt_set_timeout(struct watchdog_device *wdd, unsigned timeout)
+{
+ struct spa_wdt_info *info =
+ container_of(wdd, struct spa_wdt_info, wdt_dev);
+ /*
+ * the wdt timer is 16 bit,
+ * frequence is 256HZ
+ */
+ unsigned int tick = timeout << DEFAULT_SHIFT;
+ if ((long long)tick > 0xffff) {
+ dev_info(info->dev, "use default value!\n");
+ timeout = SPACEMIT_WATCHDOG_MAX_TIMEOUT;
+ tick = timeout << DEFAULT_SHIFT;
+ }
+
+ spa_wdt_write(info, WDT_WMR, tick);
+
+ wdd->timeout = timeout;
+
+ return 0;
+}
+
+static void spa_enable_wdt_clk(struct spa_wdt_info *info)
+{
+ mutex_lock(&wdt_clk_lock);
+ if (!info->wdt_clk_open) {
+ clk_prepare_enable(info->clk);
+ reset_control_deassert(info->reset);
+ info->wdt_clk_open = true;
+ }
+ mutex_unlock(&wdt_clk_lock);
+}
+
+static void spa_disable_wdt_clk(struct spa_wdt_info *info)
+{
+ mutex_lock(&wdt_clk_lock);
+ if (info->wdt_clk_open) {
+ clk_disable_unprepare(info->clk);
+ reset_control_assert(info->reset);
+ info->wdt_clk_open = false;
+ }
+ mutex_unlock(&wdt_clk_lock);
+}
+
+static int spa_wdt_stop(struct watchdog_device *wdd)
+{
+ struct spa_wdt_info *info =
+ container_of(wdd, struct spa_wdt_info, wdt_dev);
+ spin_lock(&info->wdt_lock);
+ dev_dbg(info->dev, "cnt = 0x%x , match = 0x%x\n", spa_wdt_read(info, WDT_WVR), spa_wdt_read(info, WDT_WMR));
+
+ /* reset counter */
+ spa_wdt_write(info, WDT_WCR, 0x1);
+
+ /* disable WDT */
+ spa_wdt_write(info, WDT_WMER, 0x0);
+
+ spin_unlock(&info->wdt_lock);
+
+ msleep(3);
+
+ spa_disable_wdt_clk(info);
+
+ return 0;
+}
+
+static int spa_wdt_start(struct watchdog_device *wdd)
+{
+ struct spa_wdt_info *info =
+ container_of(wdd, struct spa_wdt_info, wdt_dev);
+ void __iomem *mpmu_aprr;
+ u32 reg;
+
+ spa_enable_wdt_clk(info);
+
+ spin_lock(&info->wdt_lock);
+
+ /* set timeout = 100s */
+ spa_wdt_set_timeout(&info->wdt_dev,
+ SPACEMIT_WATCHDOG_EXPIRE_TIME);
+
+ /* enable counter and reset/interrupt */
+ spa_wdt_write(info, WDT_WMER, 0x3);
+
+ /* negate hardware reset to the WDT after system reset */
+ mpmu_aprr = info->mpmu_base + MPMU_APRR;
+ reg = readl(mpmu_aprr);
+ reg |= MPMU_APRR_WDTR;
+ writel(reg, mpmu_aprr);
+
+ /* clear previous WDT status */
+ spa_wdt_write(info, WDT_WSR, 0x0);
+
+ spin_unlock(&info->wdt_lock);
+
+ return 0;
+}
+
+#ifdef CONFIG_K1X_WDT_TEST
+static int spa_wdt_start_irq(struct watchdog_device *wdd)
+{
+ struct spa_wdt_info *info =container_of(wdd, struct spa_wdt_info, wdt_dev);
+
+ spa_enable_wdt_clk(info);
+
+ spin_lock(&info->wdt_lock);
+
+ /* set timeout = 2/256 s */
+ spa_wdt_set_timeout(&info->wdt_dev, K1X_WATCHDOG_IRQ_EXPIRE_TIME);
+ /* enable counter and reset/interrupt */
+ spa_wdt_write(info, WDT_WMER, 0x1);
+
+ spin_unlock(&info->wdt_lock);
+
+ return 0;
+}
+
+static void spa_wdt_stop_irq(struct watchdog_device *wdd)
+{
+ struct spa_wdt_info *info =container_of(wdd, struct spa_wdt_info, wdt_dev);
+
+ spin_lock(&info->wdt_lock);
+
+ /* reset counter */
+ spa_wdt_write(info, WDT_WCR, 0x1);
+
+ /* disable WDT */
+ spa_wdt_write(info, WDT_WMER, 0x0);
+
+ spin_unlock(&info->wdt_lock);
+
+ msleep(3);
+
+ spa_disable_wdt_clk(info);
+}
+#endif
+
+static int spa_wdt_ping(struct watchdog_device *wdd)
+{
+ int ret = 0;
+
+ struct spa_wdt_info *info =
+ container_of(wdd, struct spa_wdt_info, wdt_dev);
+
+ spin_lock(&reboot_lock);
+ spin_lock(&info->wdt_lock);
+
+ /* reset counter */
+ if (wdd->timeout > 0) {
+ spa_wdt_write(info, WDT_WCR, 0x1);
+ } else
+ ret = -EINVAL;
+
+ spin_unlock(&info->wdt_lock);
+ spin_unlock(&reboot_lock);
+
+ return ret;
+}
+
+#define OPTIONS (WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING)
+
+static const struct watchdog_info spa_wdt_ident = {
+ .options = OPTIONS,
+ .firmware_version = 0,
+ .identity = "K1X Watchdog",
+};
+
+static struct watchdog_ops spa_wdt_ops = {
+ .owner = THIS_MODULE,
+ .start = spa_wdt_start,
+ .stop = spa_wdt_stop,
+ .ping = spa_wdt_ping,
+ .set_timeout = spa_wdt_set_timeout,
+};
+
+static struct watchdog_device spa_wdt = {
+ .info = &spa_wdt_ident,
+ .ops = &spa_wdt_ops,
+};
+
+static void spa_init_wdt(struct spa_wdt_info *info)
+{
+
+ if (info->ctrl) {
+ spa_wdt_start(&info->wdt_dev);
+ hrtimer_start(&info->feed_timer, info->feed_timeout, HRTIMER_MODE_REL);
+ } else
+ spa_wdt_stop(&info->wdt_dev);
+
+ if (test_bit(WDOG_ACTIVE, &((info->wdt_dev).status)))
+ spa_wdt_ping(&info->wdt_dev);
+}
+
+static const struct of_device_id spa_wdt_match[] = {
+ { .compatible = "spacemit,soc-wdt", .data = NULL},
+ {},
+};
+MODULE_DEVICE_TABLE(of, spa_wdt_match);
+
+static ssize_t wdt_ctrl_show(struct device *dev, struct device_attribute *attr,
+ char *buf)
+{
+ struct spa_wdt_info *info = dev_get_drvdata(dev);
+ int s = 0;
+
+ s += sprintf(buf, "wdt control: %d\n", info->ctrl);
+ return s;
+}
+
+static ssize_t wdt_ctrl_store(struct device *dev, struct device_attribute *attr,
+ const char *buf, size_t size)
+{
+ struct spa_wdt_info *info = dev_get_drvdata(dev);
+ ssize_t ret = 0;
+ int ctrl;
+
+ if (info == NULL) {
+ pr_err("device info is empty!\n");
+ return 0;
+ }
+ ret = sscanf(buf, "%d", &ctrl);
+ if (ret == 0) {
+ pr_err("sscanf() error, try again\n");
+ ret = -EINVAL;
+ }
+ dev_info(dev, "%s: wdt control %s\n",
+ __func__, (ctrl ? "enabled" : "disabled"));
+ if (ret < 0)
+ return ret;
+
+ if (ctrl && (info->ctrl == 0)) {
+ spa_wdt_start(&info->wdt_dev);
+ hrtimer_start(&info->feed_timer, info->feed_timeout, HRTIMER_MODE_REL);
+ } else if ((ctrl == 0) && info->ctrl) {
+ hrtimer_cancel(&info->feed_timer);
+ spa_wdt_stop(&info->wdt_dev);
+ }
+
+ info->ctrl = ctrl;
+ return size;
+}
+static DEVICE_ATTR(wdt_ctrl, S_IRUGO | S_IWUSR, wdt_ctrl_show, wdt_ctrl_store);
+
+#ifdef CONFIG_K1X_WDT_TEST
+static void spa_wdt_reset_test(struct spa_wdt_info *info)
+{
+ void __iomem *mpmu_aprr;
+ unsigned long flags = 0;
+ u32 reg;
+
+ mpmu_aprr = info->mpmu_base + MPMU_APRR;
+
+ spin_lock_irqsave(&info->wdt_lock, flags);
+ spa_wdt_shutdown_reason(NULL);
+
+ spa_wdt_write(info, WDT_WSR, 0x0);
+ spa_wdt_set_timeout(&info->wdt_dev, 0);
+ spa_wdt_write(info, WDT_WMER, 0x3);
+ spa_wdt_write(info, WDT_WCR, 0x1);
+
+ reg = readl(mpmu_aprr);
+ reg |= MPMU_APRR_WDTR;
+ writel(reg, mpmu_aprr);
+ spin_unlock_irqrestore(&info->wdt_lock, flags);
+
+ mdelay(5000);
+ panic("reboot system failed");
+
+ pr_err("reboot system failed: this line shouldn't appear.\n");
+}
+
+static void spa_wdt_irq_test(struct spa_wdt_info *info)
+{
+ int expected_irq_count;
+
+ wdt_irq_count = 0;
+ expected_irq_count = K1X_WATCHDOG_IRQ_TEST_TIME / K1X_WATCHDOG_IRQ_EXPIRE_TIME;
+
+ /* avoid suspend within 15 seconds */
+ pm_wakeup_event(info->dev, 15000);
+ if (info->ctrl) {
+ hrtimer_cancel(&info->feed_timer);
+ spa_wdt_stop(&info->wdt_dev);
+ info->ctrl = 0;
+ }
+ /* start watchdog timer with irq mode */
+ spa_wdt_start_irq(&info->wdt_dev);
+
+ mdelay((K1X_WATCHDOG_IRQ_TEST_TIME) * 1000 / 256 + 50);
+ /* stop watchdog timer with irq mode */
+ spa_wdt_stop_irq(&info->wdt_dev);
+
+ if (!info->ctrl) {
+ spa_wdt_start(&info->wdt_dev);
+ hrtimer_start(&info->feed_timer, info->feed_timeout, HRTIMER_MODE_REL);
+ info->ctrl = 1;
+ }
+ pr_err("irq count: expected(%d), actual(%d) %s\n", expected_irq_count, wdt_irq_count,
+ (expected_irq_count == wdt_irq_count) ? "PASS" : "FAIL");
+}
+
+static ssize_t wdt_debug_show(struct device *dev, struct device_attribute *attr,
+ char *buf)
+{
+ int s = 0;
+
+ s += sprintf(buf, "wdt irq count: %d\n", wdt_irq_count);
+ return s;
+}
+
+static ssize_t wdt_debug_store(struct device *dev, struct device_attribute *attr,
+ const char *buf, size_t size)
+{
+ struct spa_wdt_info *info = dev_get_drvdata(dev);
+ ssize_t ret = 0;
+ int test_id;
+
+ if (info == NULL) {
+ pr_err("device info is empty!\n");
+ return 0;
+ }
+ ret = sscanf(buf, "%d", &test_id);
+ if (ret == 0) {
+ pr_err("sscanf() error, try again\n");
+ ret = -EINVAL;
+ }
+
+ if (test_id == K1X_WATCHDOG_IRQ_TEST_ID)
+ spa_wdt_irq_test(info);
+ else
+ spa_wdt_reset_test(info);
+
+ return size;
+}
+static DEVICE_ATTR(wdt_debug, S_IRUGO | S_IWUSR, wdt_debug_show, wdt_debug_store);
+
+static irqreturn_t wdt_irq_handler(int irq, void *data)
+{
+ struct spa_wdt_info *info = data;
+
+ wdt_irq_count++;
+ /* clear irq flag */
+ spin_lock(&info->wdt_lock);
+ spa_wdt_write(info, WDT_WICR, 0x1);
+ spa_wdt_write(info, WDT_WCR, 0x1);
+ spin_unlock(&info->wdt_lock);
+
+ return IRQ_HANDLED;
+}
+#endif
+
+static int spa_wdt_restart_handler(struct notifier_block *this, unsigned long mode,
+ void *cmd)
+{
+ struct spa_wdt_info *info = container_of(this, struct spa_wdt_info,
+ restart_handler);
+ void __iomem *mpmu_aprr;
+ u32 reg;
+
+ spin_lock(&reboot_lock);
+ spa_wdt_shutdown_reason(cmd);
+
+ spa_enable_wdt_clk(info);
+
+ spa_wdt_write(info, WDT_WSR, 0x0);
+ spa_wdt_write(info, WDT_WMR, 0x1);
+ spa_wdt_write(info, WDT_WMER, 0x3);
+ spa_wdt_write(info, WDT_WCR, 0x1);
+
+ mpmu_aprr = info->mpmu_base + MPMU_APRR;
+ reg = readl(mpmu_aprr);
+ reg |= MPMU_APRR_WDTR;
+ writel(reg, mpmu_aprr);
+
+ mdelay(5000);
+ panic("reboot system failed");
+ spin_unlock(&reboot_lock);
+
+ pr_err("reboot system failed: this line shouldn't appear.\n");
+ return NOTIFY_DONE;
+}
+
+static int spa_wdt_dt_init(struct device_node *np, struct device *dev,
+ struct spa_wdt_info *info)
+{
+ if (info == NULL) {
+ pr_err("watchdog dt is empty!\n");
+ return -EINVAL;
+ }
+ if (of_get_property(np, "spa,wdt-disabled", NULL))
+ info->ctrl = 0;
+ else
+ info->ctrl = 1;
+
+ if (of_get_property(np, "spa,wdt-enable-restart-handler", NULL))
+ info->enable_restart_handler = 1;
+ else
+ info->enable_restart_handler = 0;
+ return 0;
+}
+
+static enum hrtimer_restart spa_wdt_feed(struct hrtimer *timer)
+{
+ struct spa_wdt_info *info = container_of(timer, struct spa_wdt_info, feed_timer);
+
+ /* reset counter value */
+ if (likely(info->ctrl)) {
+ spa_wdt_ping(&info->wdt_dev);
+ hrtimer_forward_now(timer, info->feed_timeout);
+ } else
+ return HRTIMER_NORESTART;
+
+ return HRTIMER_RESTART;
+}
+
+static int spa_wdt_probe(struct platform_device *pdev)
+{
+ struct device_node *np = pdev->dev.of_node;
+ struct resource wdt_mem;
+ struct resource mpmu_mem;
+ void __iomem *mpmu_arsr;
+ u32 reg;
+
+ int ret;
+#ifdef CONFIG_K1X_WDT_TEST
+ int irq;
+#endif
+ static int is_wdt_reset;
+ struct spa_wdt_info *info;
+ info = devm_kzalloc(&pdev->dev, sizeof(struct spa_wdt_info),
+ GFP_KERNEL);
+ if (info == NULL) {
+ dev_err(&pdev->dev, "Cannot allocate memory.\n");
+ return -ENOMEM;
+ }
+
+ info->dev = &pdev->dev;
+
+#ifdef CONFIG_K1X_WDT_TEST
+ irq = platform_get_irq(pdev, 0);
+ ret = devm_request_irq(&pdev->dev, irq, wdt_irq_handler,
+ IRQF_TIMER | IRQF_IRQPOLL,
+ "watchdog",
+ info);
+ if (ret) {
+ dev_err(&pdev->dev, "%s: Failed to request irq!\n", __func__);
+ return ret;
+ }
+#endif
+
+ ret = of_address_to_resource(np, 0, &wdt_mem);
+ if (ret < 0) {
+ dev_err(info->dev, "no memory resource specified for WDT\n");
+ return -ENOENT;
+ }
+
+ info->wdt_base = devm_ioremap(&pdev->dev, wdt_mem.start,
+ resource_size(&wdt_mem));
+ if (IS_ERR(info->wdt_base))
+ return PTR_ERR(info->wdt_base);
+
+ ret = of_address_to_resource(np, 1, &mpmu_mem);
+ if (ret < 0) {
+ dev_err(info->dev, "no memory resource specified for MPMU\n");
+ return -ENOENT;
+ }
+
+ info->mpmu_base = devm_ioremap(&pdev->dev,
+ mpmu_mem.start, resource_size(&mpmu_mem));
+ if (IS_ERR(info->mpmu_base))
+ return PTR_ERR(info->mpmu_base);
+
+ mpmu_arsr = info->mpmu_base + MPMU_ARSR;
+ reg = readl(mpmu_arsr);
+ reg &= ~MPMU_ARSR_SWR_MASK;
+ writel(reg, mpmu_arsr);
+
+ /* get WDT clock */
+ info->clk = devm_clk_get(info->dev, NULL);
+ if (IS_ERR(info->clk)) {
+ dev_err(info->dev, "failed to get WDT clock\n");
+ return PTR_ERR(info->clk);
+ }
+
+ info->reset = devm_reset_control_get_optional(info->dev,NULL);
+ if(IS_ERR(info->reset)) {
+ dev_err(info->dev, "watchdog get reset failed\n");
+ return PTR_ERR(info->reset);
+ }
+ /*
+ * the writing of some WDT registers must be
+ * under the condition of that WDT clock is on
+ */
+ spa_enable_wdt_clk(info);
+
+ /* check before the watchdog is initialized */
+ is_wdt_reset = spa_wdt_read(info, WDT_WSR);
+ if (is_wdt_reset)
+ pr_info("System boots up because of SoC watchdog reset.\n");
+ else
+ pr_info("System boots up not because of SoC watchdog reset.\n");
+
+ spin_lock_init(&info->wdt_lock);
+
+ watchdog_set_nowayout(&spa_wdt, nowayout);
+
+ info->wdt_dev = spa_wdt;
+ ret = watchdog_register_device(&info->wdt_dev);
+ if (ret) {
+ dev_err(info->dev, "cannot register watchdog (%d)\n", ret);
+ goto err_register_fail;
+ }
+
+ info->feed_timeout = ktime_set(SPACEMIT_WATCHDOG_FEED_TIMEOUT, 0);
+ hrtimer_init(&info->feed_timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
+ info->feed_timer.function = spa_wdt_feed;
+
+ platform_set_drvdata(pdev, info);
+
+ spa_wdt_dt_init(np, info->dev, info);
+
+ spa_init_wdt(info);
+
+ ret = device_create_file(info->dev, &dev_attr_wdt_ctrl);
+ if (ret < 0) {
+ dev_err(&pdev->dev, "device attr create fail: %d\n", ret);
+ goto err_alloc;
+ }
+
+#ifdef CONFIG_K1X_WDT_TEST
+ ret = device_create_file(info->dev, &dev_attr_wdt_debug);
+ if (ret < 0) {
+ dev_err(&pdev->dev, "device attr create fail: %d\n", ret);
+ goto err_alloc;
+ }
+#endif
+
+ if (info->enable_restart_handler) {
+ info->restart_handler.notifier_call = spa_wdt_restart_handler;
+ info->restart_handler.priority = 0;
+ ret = register_restart_handler(&info->restart_handler);
+ if (ret)
+ dev_warn(&pdev->dev,
+ "cannot register restart handler (err=%d)\n", ret);
+ }
+
+ syscore_info = info;
+ return 0;
+
+err_alloc:
+ if (info->ctrl) {
+ hrtimer_cancel(&info->feed_timer);
+ spa_wdt_stop(&info->wdt_dev);
+ }
+
+ watchdog_unregister_device(&info->wdt_dev);
+err_register_fail:
+ spa_disable_wdt_clk(info);
+ clk_put(info->clk);
+
+ return ret;
+}
+
+static int spa_wdt_remove(struct platform_device *pdev)
+{
+ struct spa_wdt_info *info = platform_get_drvdata(pdev);
+
+ watchdog_unregister_device(&info->wdt_dev);
+
+ if (info->ctrl) {
+ hrtimer_cancel(&info->feed_timer);
+ spa_wdt_stop(&info->wdt_dev);
+ }
+
+ spa_disable_wdt_clk(info);
+ clk_put(info->clk);
+
+ return 0;
+}
+
+static void spa_wdt_shutdown(struct platform_device *pdev)
+{
+ struct spa_wdt_info *info = platform_get_drvdata(pdev);
+
+ if (info->ctrl)
+ hrtimer_cancel(&info->feed_timer);
+
+ spa_wdt_stop(&info->wdt_dev);
+
+ /* no need to disable clk if enable restart_handler */
+ if (info->enable_restart_handler)
+ spa_enable_wdt_clk(info);
+}
+
+#ifdef CONFIG_PM
+static int spa_wdt_suspend(struct platform_device *pdev, pm_message_t state)
+{
+ struct spa_wdt_info *info = platform_get_drvdata(pdev);
+
+ if (info->ctrl) {
+ /* turn watchdog off */
+ hrtimer_cancel(&info->feed_timer);
+ spa_wdt_stop(&info->wdt_dev);
+ }
+
+ return 0;
+}
+
+static int spa_wdt_resume(struct platform_device *pdev)
+{
+ struct spa_wdt_info *info = platform_get_drvdata(pdev);
+
+ if (info->ctrl) {
+ spa_wdt_start(&info->wdt_dev);
+ hrtimer_start(&info->feed_timer, info->feed_timeout, HRTIMER_MODE_REL);
+ }
+
+ return 0;
+}
+
+#else
+#define spa_wdt_suspend NULL
+#define spa_wdt_resume NULL
+#endif /* CONFIG_PM */
+
+#ifdef CONFIG_OF_RESERVED_MEM
+#include <linux/of.h>
+#include <linux/of_fdt.h>
+#include <linux/of_reserved_mem.h>
+
+static int __init rmem_reboot_setup(struct reserved_mem *rmem)
+{
+ phys_addr_t mask = PAGE_SIZE - 1;
+
+ if ((rmem->base & mask) || (rmem->size & mask)) {
+ pr_err("Reserved memory: incorrect alignment of reboot region\n");
+ return -EINVAL;
+ }
+
+ pr_info("Reserved memory: detected reboot memory at %pa, size %ld KiB\n",
+ &rmem->base, (unsigned long)rmem->size / SZ_1K);
+
+ reboot_cmd_mem = rmem->base;
+ reboot_cmd_size = rmem->size;
+
+ return 0;
+}
+RESERVEDMEM_OF_DECLARE(reboot, "reboot_page", rmem_reboot_setup);
+#endif
+
+
+static struct platform_driver spa_wdt_driver = {
+ .probe = spa_wdt_probe,
+ .remove = spa_wdt_remove,
+ .shutdown = spa_wdt_shutdown,
+ .suspend = spa_wdt_suspend,
+ .resume = spa_wdt_resume,
+ .driver = {
+ .name = "spa-wdt",
+ .of_match_table = of_match_ptr(spa_wdt_match),
+ },
+};
+
+
+module_platform_driver(spa_wdt_driver);
+
+MODULE_DESCRIPTION("Spacemit k1x-plat Watchdog Device Driver");
+MODULE_LICENSE("GPL-v2");
+MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR);
+MODULE_ALIAS("platform:soc-wdt");
diff --git a/fs/btrfs/sysfs.c b/fs/btrfs/sysfs.c
index 111111111111..222222222222 100644
--- a/fs/btrfs/sysfs.c
+++ b/fs/btrfs/sysfs.c
@@ -626,7 +626,7 @@ static const struct attribute_group btrfs_debug_feature_attr_group = {
#endif
-static ssize_t btrfs_show_u64(u64 *value_ptr, spinlock_t *lock, char *buf)
+static noinline ssize_t btrfs_show_u64(u64 *value_ptr, spinlock_t *lock, char *buf)
{
u64 val;
if (lock)
--
Armbian

View File

@@ -1,773 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Patrick Yavitz <pyavitz@armbian.com>
Date: Fri, 21 Jun 2024 11:54:06 -0400
Subject: add spacemit patch set
source: https://gitee.com/bianbu-linux/linux-6.1
Signed-off-by: Patrick Yavitz <pyavitz@armbian.com>
---
include/dt-bindings/clock/spacemit-k1x-clock.h | 201 ++++++++++
include/dt-bindings/display/spacemit-dpu.h | 40 ++
include/dt-bindings/dma/k1x-dmac.h | 58 +++
include/dt-bindings/mmc/k1x_sdhci.h | 53 +++
include/dt-bindings/pinctrl/k1-x-pinctrl.h | 198 +++++++++
include/dt-bindings/pmu/k1x_pmu.h | 16 +
include/dt-bindings/reset/spacemit-k1x-reset.h | 122 ++++++
include/dt-bindings/usb/k1x_ci_usb.h | 15 +
8 files changed, 703 insertions(+)
diff --git a/include/dt-bindings/clock/spacemit-k1x-clock.h b/include/dt-bindings/clock/spacemit-k1x-clock.h
new file mode 100644
index 000000000000..111111111111
--- /dev/null
+++ b/include/dt-bindings/clock/spacemit-k1x-clock.h
@@ -0,0 +1,201 @@
+// SPDX-License-Identifier: (GPL-2.0+ or MIT)
+
+#ifndef _DT_BINDINGS_CLK_SPACEMIT_K1X_H_
+#define _DT_BINDINGS_CLK_SPACEMIT_K1X_H_
+
+#define CLK_PLL2 0
+#define CLK_PLL3 1
+#define CLK_PLL1_D2 2
+#define CLK_PLL1_D3 3
+#define CLK_PLL1_D4 4
+#define CLK_PLL1_D5 5
+#define CLK_PLL1_D6 6
+#define CLK_PLL1_D7 7
+#define CLK_PLL1_D8 8
+#define CLK_PLL1_D11 9
+#define CLK_PLL1_D13 10
+#define CLK_PLL1_D23 11
+#define CLK_PLL1_D64 12
+#define CLK_PLL1_D10_AUD 13
+#define CLK_PLL1_D100_AUD 14
+#define CLK_PLL2_D1 15
+#define CLK_PLL2_D2 16
+#define CLK_PLL2_D3 17
+#define CLK_PLL2_D4 18
+#define CLK_PLL2_D5 19
+#define CLK_PLL2_D6 20
+#define CLK_PLL2_D7 21
+#define CLK_PLL2_D8 22
+#define CLK_PLL3_D1 23
+#define CLK_PLL3_D2 24
+#define CLK_PLL3_D3 25
+#define CLK_PLL3_D4 26
+#define CLK_PLL3_D5 27
+#define CLK_PLL3_D6 28
+#define CLK_PLL3_D7 29
+#define CLK_PLL3_D8 30
+#define CLK_PLL1_307P2 31
+#define CLK_PLL1_76P8 32
+#define CLK_PLL1_61P44 33
+#define CLK_PLL1_153P6 34
+#define CLK_PLL1_102P4 35
+#define CLK_PLL1_51P2 36
+#define CLK_PLL1_51P2_AP 37
+#define CLK_PLL1_57P6 38
+#define CLK_PLL1_25P6 39
+#define CLK_PLL1_12P8 40
+#define CLK_PLL1_12P8_WDT 41
+#define CLK_PLL1_6P4 42
+#define CLK_PLL1_3P2 43
+#define CLK_PLL1_1P6 44
+#define CLK_PLL1_0P8 45
+#define CLK_PLL1_351 46
+#define CLK_PLL1_409P6 47
+#define CLK_PLL1_204P8 48
+#define CLK_PLL1_491 49
+#define CLK_PLL1_245P76 50
+#define CLK_PLL1_614 51
+#define CLK_PLL1_47P26 52
+#define CLK_PLL1_31P5 53
+#define CLK_PLL1_819 54
+#define CLK_PLL1_1228 55
+#define CLK_SLOW_UART1 56
+#define CLK_SLOW_UART2 57
+#define CLK_UART1 58
+#define CLK_UART2 59
+#define CLK_UART3 60
+#define CLK_UART4 61
+#define CLK_UART5 62
+#define CLK_UART6 63
+#define CLK_UART7 64
+#define CLK_UART8 65
+#define CLK_UART9 66
+#define CLK_GPIO 67
+#define CLK_PWM0 68
+#define CLK_PWM1 69
+#define CLK_PWM2 70
+#define CLK_PWM3 71
+#define CLK_PWM4 72
+#define CLK_PWM5 73
+#define CLK_PWM6 74
+#define CLK_PWM7 75
+#define CLK_PWM8 76
+#define CLK_PWM9 77
+#define CLK_PWM10 78
+#define CLK_PWM11 79
+#define CLK_PWM12 80
+#define CLK_PWM13 81
+#define CLK_PWM14 82
+#define CLK_PWM15 83
+#define CLK_PWM16 84
+#define CLK_PWM17 85
+#define CLK_PWM18 86
+#define CLK_PWM19 87
+#define CLK_SSP3 88
+#define CLK_RTC 89
+#define CLK_TWSI0 90
+#define CLK_TWSI1 91
+#define CLK_TWSI2 92
+#define CLK_TWSI4 93
+#define CLK_TWSI5 94
+#define CLK_TWSI6 95
+#define CLK_TWSI7 96
+#define CLK_TWSI8 97
+#define CLK_TIMERS1 98
+#define CLK_TIMERS2 99
+#define CLK_AIB 100
+#define CLK_ONEWIRE 101
+#define CLK_SSPA0 102
+#define CLK_SSPA1 103
+#define CLK_DRO 104
+#define CLK_IR 105
+#define CLK_TSEN 106
+#define CLK_IPC_AP2AUD 107
+#define CLK_CAN0 108
+#define CLK_CAN0_BUS 109
+#define CLK_WDT 110
+#define CLK_RIPC 111
+#define CLK_JPG 112
+#define CLK_JPF_4KAFBC 113
+#define CLK_JPF_2KAFBC 114
+#define CLK_CCIC2PHY 115
+#define CLK_CCIC3PHY 116
+#define CLK_CSI 117
+#define CLK_CAMM0 118
+#define CLK_CAMM1 119
+#define CLK_CAMM2 120
+#define CLK_ISP_CPP 121
+#define CLK_ISP_BUS 122
+#define CLK_ISP 123
+#define CLK_DPU_MCLK 124
+#define CLK_DPU_ESC 125
+#define CLK_DPU_BIT 126
+#define CLK_DPU_PXCLK 127
+#define CLK_DPU_HCLK 128
+#define CLK_DPU_SPI 129
+#define CLK_DPU_SPI_HBUS 130
+#define CLK_DPU_SPIBUS 131
+#define CLK_SPU_SPI_ACLK 132
+#define CLK_V2D 133
+#define CLK_CCIC_4X 134
+#define CLK_CCIC1PHY 135
+#define CLK_SDH_AXI 136
+#define CLK_SDH0 137
+#define CLK_SDH1 138
+#define CLK_SDH2 139
+#define CLK_USB_P1 140
+#define CLK_USB_AXI 141
+#define CLK_USB30 142
+#define CLK_QSPI 143
+#define CLK_QSPI_BUS 144
+#define CLK_DMA 145
+#define CLK_AES 146
+#define CLK_VPU 147
+#define CLK_GPU 148
+#define CLK_EMMC 149
+#define CLK_EMMC_X 150
+#define CLK_AUDIO 151
+#define CLK_HDMI 152
+#define CLK_CCI550 153
+#define CLK_PMUA_ACLK 154
+#define CLK_CPU_C0_HI 155
+#define CLK_CPU_C0_CORE 156
+#define CLK_CPU_C0_ACE 157
+#define CLK_CPU_C0_TCM 158
+#define CLK_CPU_C1_HI 159
+#define CLK_CPU_C1_CORE 160
+#define CLK_CPU_C1_ACE 161
+#define CLK_PCIE0 162
+#define CLK_PCIE1 163
+#define CLK_PCIE2 164
+#define CLK_EMAC0_BUS 165
+#define CLK_EMAC0_PTP 166
+#define CLK_EMAC1_BUS 167
+#define CLK_EMAC1_PTP 168
+
+#define CLK_SEC_UART1 169
+#define CLK_SEC_SSP2 170
+#define CLK_SEC_TWSI3 171
+#define CLK_SEC_RTC 172
+#define CLK_SEC_TIMERS0 173
+#define CLK_SEC_KPC 174
+#define CLK_SEC_GPIO 175
+
+#define CLK_APB 176
+
+#define CLK_PLL3_80 177
+#define CLK_PLL3_40 178
+#define CLK_PLL3_20 179
+
+#define CLK_SLOW_UART 180
+
+#define CLK_I2S_SYSCLK 181
+#define CLK_I2S_BCLK 182
+#define CLK_RCPU_HDMIAUDIO 183
+#define CLK_RCPU_CAN 184
+#define CLK_RCPU_CAN_BUS 185
+
+#define CLK_RCPU2_PWM 186
+
+#define CLK_MAX_NO 187
+#endif /* _DT_BINDINGS_CLK_SPACEMIT_K1X_H_ */
diff --git a/include/dt-bindings/display/spacemit-dpu.h b/include/dt-bindings/display/spacemit-dpu.h
new file mode 100644
index 000000000000..111111111111
--- /dev/null
+++ b/include/dt-bindings/display/spacemit-dpu.h
@@ -0,0 +1,40 @@
+// SPDX-License-Identifier: GPL-2.0
+
+#ifndef SPACEMIT_DT_BINDINGS_DISPLAY_DPU_H
+#define SPACEMIT_DT_BINDINGS_DISPLAY_DPU_H
+
+/* DPU type */
+#define HDMI 0
+#define DSI 1
+
+/* DPU sub component */
+#define ONLINE0 0
+#define ONLINE1 1
+#define ONLINE2 2
+#define OFFLINE0 3
+#define OFFLINE1 4
+
+/* online/offline path id */
+#define WB0 (1<<0)
+#define WB1 (1<<1)
+#define COMPOSER0 (1<<2)
+#define COMPOSER1 (1<<3)
+#define COMPOSER2 (1<<4)
+#define COMPOSER3 (1<<5)
+#define PP0 (1<<6)
+#define PP1 (1<<7)
+#define PP2 (1<<8)
+#define SCALER0 (1<<9)
+#define SCALER1 (1<<10)
+#define SCALER2 (1<<11)
+#define SCALER3 (1<<12)
+#define SCALER4 (1<<13)
+#define ACAD0 (1<<14)
+#define ACAD1 (1<<15)
+#define ACAD2 (1<<16)
+#define LUT3D0 (1<<17)
+#define LUT3D1 (1<<18)
+#define LUT3D2 (1<<19)
+
+#endif /* SPACEMIT_DT_BINDINGS_DISPLAY_DPU_H */
+
diff --git a/include/dt-bindings/dma/k1x-dmac.h b/include/dt-bindings/dma/k1x-dmac.h
new file mode 100644
index 000000000000..111111111111
--- /dev/null
+++ b/include/dt-bindings/dma/k1x-dmac.h
@@ -0,0 +1,58 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * This header provides constants for SPACEMIT DMA channel map table.
+ *
+ * Copyright (C) 2023 Spacemit
+ */
+
+#ifndef __DTS_K1X_DMAC_H
+#define __DTS_K1X_DMAC_H
+
+#define DMA_UART0_TX 3
+#define DMA_UART0_RX 4
+#define DMA_UART2_TX 5
+#define DMA_UART2_RX 6
+#define DMA_UART3_TX 7
+#define DMA_UART3_RX 8
+#define DMA_UART4_TX 9
+#define DMA_UART4_RX 10
+#define DMA_UART5_TX 25
+#define DMA_UART5_RX 26
+#define DMA_UART6_TX 27
+#define DMA_UART6_RX 28
+#define DMA_UART7_TX 29
+#define DMA_UART7_RX 30
+#define DMA_UART8_TX 31
+#define DMA_UART8_RX 32
+#define DMA_UART9_TX 33
+#define DMA_UART9_RX 34
+
+#define DMA_I2C0_TX 11
+#define DMA_I2C0_RX 12
+#define DMA_I2C1_TX 13
+#define DMA_I2C1_RX 14
+#define DMA_I2C2_TX 15
+#define DMA_I2C2_RX 16
+#define DMA_I2C4_TX 17
+#define DMA_I2C4_RX 18
+#define DMA_I2C5_TX 35
+#define DMA_I2C5_RX 36
+#define DMA_I2C6_TX 37
+#define DMA_I2C6_RX 38
+#define DMA_I2C7_TX 39
+#define DMA_I2C7_RX 40
+#define DMA_I2C8_TX 41
+#define DMA_I2C8_RX 42
+
+#define DMA_SSP3_TX 19
+#define DMA_SSP3_RX 20
+#define DMA_SSPA0_TX 21
+#define DMA_SSPA0_RX 22
+#define DMA_SSPA1_TX 23
+#define DMA_SSPA1_RX 24
+#define DMA_QSPI_RX 44
+#define DMA_QSPI_TX 45
+
+#define DMA_CAN0_RX 43
+
+#endif /*__DTS_K1X_DMAC_H*/
diff --git a/include/dt-bindings/mmc/k1x_sdhci.h b/include/dt-bindings/mmc/k1x_sdhci.h
new file mode 100644
index 000000000000..111111111111
--- /dev/null
+++ b/include/dt-bindings/mmc/k1x_sdhci.h
@@ -0,0 +1,53 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * include/linux/dt-bindings/mmc/k1x_sdhci.h
+ *
+ * SDH driver for SPACEMIT K1X SDCHI
+ * Copyright (C) 2023 Spacemit
+ */
+
+#ifndef K1X_DT_BINDINGS_MMC_SDHCI_H
+#define K1X_DT_BINDINGS_MMC_SDHCI_H
+
+/* K1x specific flag */
+
+/* MMC Quirks */
+/* Controller has an unusable ADMA engine */
+#define SDHCI_QUIRK_BROKEN_ADMA (1<<6)
+#define SDHCI_QUIRK2_PRESET_VALUE_BROKEN (1<<3)
+/* Controller does not support HS200 */
+#define SDHCI_QUIRK2_BROKEN_HS200 (1<<6)
+/* Support SDH controller on FPGA */
+#define SDHCI_QUIRK2_SUPPORT_PHY_BYPASS (1<<25)
+/* Disable scan card at probe phase */
+#define SDHCI_QUIRK2_DISABLE_PROBE_CDSCAN (1<<26)
+/* Need to set IO capability by SOC part register */
+#define SDHCI_QUIRK2_SET_AIB_MMC (1<<27)
+/* Controller not support phy module */
+#define SDHCI_QUIRK2_BROKEN_PHY_MODULE (1<<28)
+/* Controller support encrypt module */
+#define SDHCI_QUIRK2_SUPPORT_ENCRYPT (1<<29)
+
+/* Common flag */
+/* Controller provides an incorrect timeout value for transfers */
+#define SDHCI_QUIRK_BROKEN_TIMEOUT_VAL (1<<12)
+/* Controller has unreliable card detection */
+#define SDHCI_QUIRK_BROKEN_CARD_DETECTION (1<<15)
+
+/* Controller reports inverted write-protect state */
+#define SDHCI_QUIRK_INVERTED_WRITE_PROTECT (1<<16)
+
+/* MMC caps */
+#define MMC_CAP2_CRC_SW_RETRY (1 << 30)
+
+/* for SDIO */
+#define MMC_CAP_NEEDS_POLL (1 << 5) /* Needs polling for card-detection */
+
+/* for SD card */
+#define MMC_CAP_UHS_SDR12 (1 << 16) /* Host supports UHS SDR12 mode */
+#define MMC_CAP_UHS_SDR25 (1 << 17) /* Host supports UHS SDR25 mode */
+#define MMC_CAP_UHS_SDR50 (1 << 18) /* Host supports UHS SDR50 mode */
+#define MMC_CAP_UHS_SDR104 (1 << 19) /* Host supports UHS SDR104 mode */
+#define MMC_CAP_UHS_DDR50 (1 << 20) /* Host supports UHS DDR50 mode */
+#endif /* K1X_DT_BINDINGS_MMC_SDHCI_H */
+
diff --git a/include/dt-bindings/pinctrl/k1-x-pinctrl.h b/include/dt-bindings/pinctrl/k1-x-pinctrl.h
new file mode 100644
index 000000000000..111111111111
--- /dev/null
+++ b/include/dt-bindings/pinctrl/k1-x-pinctrl.h
@@ -0,0 +1,198 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+
+#ifndef __DT_BINDINGS_K1X_PINCTRL_H
+#define __DT_BINDINGS_K1X_PINCTRL_H
+
+/* pin offset */
+#define PINID(x) ((x) + 1)
+
+#define GPIO_00 PINID(0)
+#define GPIO_01 PINID(1)
+#define GPIO_02 PINID(2)
+#define GPIO_03 PINID(3)
+#define GPIO_04 PINID(4)
+#define GPIO_05 PINID(5)
+#define GPIO_06 PINID(6)
+#define GPIO_07 PINID(7)
+#define GPIO_08 PINID(8)
+#define GPIO_09 PINID(9)
+#define GPIO_10 PINID(10)
+#define GPIO_11 PINID(11)
+#define GPIO_12 PINID(12)
+#define GPIO_13 PINID(13)
+#define GPIO_14 PINID(14)
+#define GPIO_15 PINID(15)
+#define GPIO_16 PINID(16)
+#define GPIO_17 PINID(17)
+#define GPIO_18 PINID(18)
+#define GPIO_19 PINID(19)
+#define GPIO_20 PINID(20)
+#define GPIO_21 PINID(21)
+#define GPIO_22 PINID(22)
+#define GPIO_23 PINID(23)
+#define GPIO_24 PINID(24)
+#define GPIO_25 PINID(25)
+#define GPIO_26 PINID(26)
+#define GPIO_27 PINID(27)
+#define GPIO_28 PINID(28)
+#define GPIO_29 PINID(29)
+#define GPIO_30 PINID(30)
+#define GPIO_31 PINID(31)
+
+#define GPIO_32 PINID(32)
+#define GPIO_33 PINID(33)
+#define GPIO_34 PINID(34)
+#define GPIO_35 PINID(35)
+#define GPIO_36 PINID(36)
+#define GPIO_37 PINID(37)
+#define GPIO_38 PINID(38)
+#define GPIO_39 PINID(39)
+#define GPIO_40 PINID(40)
+#define GPIO_41 PINID(41)
+#define GPIO_42 PINID(42)
+#define GPIO_43 PINID(43)
+#define GPIO_44 PINID(44)
+#define GPIO_45 PINID(45)
+#define GPIO_46 PINID(46)
+#define GPIO_47 PINID(47)
+#define GPIO_48 PINID(48)
+#define GPIO_49 PINID(49)
+#define GPIO_50 PINID(50)
+#define GPIO_51 PINID(51)
+#define GPIO_52 PINID(52)
+#define GPIO_53 PINID(53)
+#define GPIO_54 PINID(54)
+#define GPIO_55 PINID(55)
+#define GPIO_56 PINID(56)
+#define GPIO_57 PINID(57)
+#define GPIO_58 PINID(58)
+#define GPIO_59 PINID(59)
+#define GPIO_60 PINID(60)
+#define GPIO_61 PINID(61)
+#define GPIO_62 PINID(62)
+#define GPIO_63 PINID(63)
+
+#define GPIO_64 PINID(64)
+#define GPIO_65 PINID(65)
+#define GPIO_66 PINID(66)
+#define GPIO_67 PINID(67)
+#define GPIO_68 PINID(68)
+#define GPIO_69 PINID(69)
+#define PRI_TDI PINID(70)
+#define PRI_TMS PINID(71)
+#define PRI_TCK PINID(72)
+#define PRI_TDO PINID(73)
+#define GPIO_74 PINID(74)
+#define GPIO_75 PINID(75)
+#define GPIO_76 PINID(76)
+#define GPIO_77 PINID(77)
+#define GPIO_78 PINID(78)
+#define GPIO_79 PINID(79)
+#define GPIO_80 PINID(80)
+#define GPIO_81 PINID(81)
+#define GPIO_82 PINID(82)
+#define GPIO_83 PINID(83)
+#define GPIO_84 PINID(84)
+#define GPIO_85 PINID(85)
+
+#define QSPI_DAT0 PINID(89)
+#define QSPI_DAT1 PINID(90)
+#define QSPI_DAT2 PINID(91)
+#define QSPI_DAT3 PINID(92)
+#define QSPI_CSI PINID(93)
+#define QSPI_CLK PINID(94)
+
+#define MMC1_DAT3 PINID(109)
+#define MMC1_DAT2 PINID(110)
+#define MMC1_DAT1 PINID(111)
+#define MMC1_DAT0 PINID(112)
+#define MMC1_CMD PINID(113)
+#define MMC1_CLK PINID(114)
+#define GPIO_110 PINID(115)
+#define PWR_SCL PINID(116)
+#define PWR_SDA PINID(117)
+#define VCXO_EN PINID(118)
+#define DVL0 PINID(119)
+#define DVL1 PINID(120)
+#define PMIC_INT_N PINID(121)
+#define GPIO_86 PINID(122)
+#define GPIO_87 PINID(123)
+#define GPIO_88 PINID(124)
+#define GPIO_89 PINID(125)
+#define GPIO_90 PINID(126)
+#define GPIO_91 PINID(127)
+#define GPIO_92 PINID(128)
+
+#define GPIO_111 PINID(130)
+#define GPIO_112 PINID(131)
+#define GPIO_113 PINID(132)
+#define GPIO_114 PINID(133)
+#define GPIO_115 PINID(134)
+#define GPIO_116 PINID(135)
+#define GPIO_117 PINID(136)
+#define GPIO_118 PINID(137)
+#define GPIO_119 PINID(138)
+#define GPIO_120 PINID(139)
+#define GPIO_121 PINID(140)
+#define GPIO_122 PINID(141)
+#define GPIO_123 PINID(142)
+#define GPIO_124 PINID(143)
+#define GPIO_125 PINID(144)
+#define GPIO_126 PINID(145)
+#define GPIO_127 PINID(146)
+
+/* pin mux */
+#define MUX_MODE0 0
+#define MUX_MODE1 1
+#define MUX_MODE2 2
+#define MUX_MODE3 3
+#define MUX_MODE4 4
+#define MUX_MODE5 5
+#define MUX_MODE6 6
+#define MUX_MODE7 7
+
+/* strong pull resistor */
+#define SPU_EN (1 << 3)
+
+/* edge detect */
+#define EDGE_NONE (1 << 6)
+#define EDGE_RISE (1 << 4)
+#define EDGE_FALL (1 << 5)
+#define EDGE_BOTH (3 << 4)
+
+/* slew rate output control */
+#define SLE_EN (1 << 7)
+
+/* schmitter trigger input threshhold */
+#define ST00 (0 << 8)
+#define ST01 (1 << 8)
+#define ST02 (2 << 8)
+#define ST03 (3 << 8)
+
+/* driver strength*/
+#define PAD_1V8_DS0 (0 << 11)
+#define PAD_1V8_DS1 (1 << 11)
+#define PAD_1V8_DS2 (2 << 11)
+#define PAD_1V8_DS3 (3 << 11)
+
+/*
+ * notice: !!!
+ * ds2 ---> bit10, ds1 ----> bit12, ds0 ----> bit11
+*/
+#define PAD_3V_DS0 (0 << 10) /* bit[12:10] 000 */
+#define PAD_3V_DS1 (2 << 10) /* bit[12:10] 010 */
+#define PAD_3V_DS2 (4 << 10) /* bit[12:10] 100 */
+#define PAD_3V_DS3 (6 << 10) /* bit[12:10] 110 */
+#define PAD_3V_DS4 (1 << 10) /* bit[12:10] 001 */
+#define PAD_3V_DS5 (3 << 10) /* bit[12:10] 011 */
+#define PAD_3V_DS6 (5 << 10) /* bit[12:10] 101 */
+#define PAD_3V_DS7 (7 << 10) /* bit[12:10] 111 */
+
+/* pull up/down */
+#define PULL_DIS (0 << 13) /* bit[15:13] 000 */
+#define PULL_UP (6 << 13) /* bit[15:13] 110 */
+#define PULL_DOWN (5 << 13) /* bit[15:13] 101 */
+
+#define K1X_PADCONF(pinid, conf, mux) ((pinid) * 4) (conf) (mux)
+
+#endif /* __DT_BINDINGS_K1PRO_PINCTRL_H */
diff --git a/include/dt-bindings/pmu/k1x_pmu.h b/include/dt-bindings/pmu/k1x_pmu.h
new file mode 100644
index 000000000000..111111111111
--- /dev/null
+++ b/include/dt-bindings/pmu/k1x_pmu.h
@@ -0,0 +1,16 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+
+#ifndef __DT_BINDINGS_PMU_K1X_H__
+#define __DT_BINDINGS_PMU_K1X_H__
+
+#define K1X_PMU_BUS_PWR_DOMAIN 0
+#define K1X_PMU_VPU_PWR_DOMAIN 1
+#define K1X_PMU_GPU_PWR_DOMAIN 2
+#define K1X_PMU_LCD_PWR_DOMAIN 3
+#define K1X_PMU_ISP_PWR_DOMAIN 4
+#define K1X_PMU_AUD_PWR_DOMAIN 5
+#define K1X_PMU_GNSS_PWR_DOMAIN 6
+#define K1X_PMU_HDMI_PWR_DOMAIN 7
+#define K1X_PMU_DUMMY_PWR_DOMAIN 8
+
+#endif
diff --git a/include/dt-bindings/reset/spacemit-k1x-reset.h b/include/dt-bindings/reset/spacemit-k1x-reset.h
new file mode 100644
index 000000000000..111111111111
--- /dev/null
+++ b/include/dt-bindings/reset/spacemit-k1x-reset.h
@@ -0,0 +1,122 @@
+// SPDX-License-Identifier: GPL-2.0-only
+
+#ifndef __DT_BINDINGS_RESET_SAPCEMIT_K1X_H__
+#define __DT_BINDINGS_RESET_SAPCEMIT_K1X_H__
+//APBC
+#define RESET_UART1 1
+#define RESET_UART2 2
+#define RESET_GPIO 3
+#define RESET_PWM0 4
+#define RESET_PWM1 5
+#define RESET_PWM2 6
+#define RESET_PWM3 7
+#define RESET_PWM4 8
+#define RESET_PWM5 9
+#define RESET_PWM6 10
+#define RESET_PWM7 11
+#define RESET_PWM8 12
+#define RESET_PWM9 13
+#define RESET_PWM10 14
+#define RESET_PWM11 15
+#define RESET_PWM12 16
+#define RESET_PWM13 17
+#define RESET_PWM14 18
+#define RESET_PWM15 19
+#define RESET_PWM16 20
+#define RESET_PWM17 21
+#define RESET_PWM18 22
+#define RESET_PWM19 23
+#define RESET_SSP3 24
+#define RESET_UART3 25
+#define RESET_RTC 26
+#define RESET_TWSI0 27
+
+#define RESET_TIMERS1 28
+#define RESET_AIB 29
+#define RESET_TIMERS2 30
+#define RESET_ONEWIRE 31
+#define RESET_SSPA0 32
+#define RESET_SSPA1 33
+#define RESET_DRO 34
+#define RESET_IR 35
+#define RESET_TWSI1 36
+
+#define RESET_TSEN 37
+#define RESET_TWSI2 38
+#define RESET_TWSI4 39
+#define RESET_TWSI5 40
+#define RESET_TWSI6 41
+#define RESET_TWSI7 42
+#define RESET_TWSI8 43
+#define RESET_IPC_AP2AUD 44
+#define RESET_UART4 45
+#define RESET_UART5 46
+#define RESET_UART6 47
+#define RESET_UART7 48
+#define RESET_UART8 49
+#define RESET_UART9 50
+#define RESET_CAN0 51
+
+//MPMU
+#define RESET_WDT 52
+
+//APMU
+#define RESET_JPG 53
+#define RESET_CSI 54
+#define RESET_CCIC2_PHY 55
+#define RESET_CCIC3_PHY 56
+#define RESET_ISP 57
+#define RESET_ISP_AHB 58
+#define RESET_ISP_CI 59
+#define RESET_ISP_CPP 60
+#define RESET_LCD 61
+#define RESET_DSI_ESC 62
+#define RESET_V2D 63
+#define RESET_MIPI 64
+#define RESET_LCD_SPI 65
+#define RESET_LCD_SPI_BUS 66
+#define RESET_LCD_SPI_HBUS 67
+#define RESET_LCD_MCLK 68
+#define RESET_CCIC_4X 69
+#define RESET_CCIC1_PHY 70
+#define RESET_SDH_AXI 71
+#define RESET_SDH0 72
+#define RESET_SDH1 73
+#define RESET_USB_AXI 74
+#define RESET_USBP1_AXI 75
+#define RESET_USB3_0 76
+#define RESET_QSPI 77
+#define RESET_QSPI_BUS 78
+#define RESET_DMA 79
+#define RESET_AES 80
+#define RESET_VPU 81
+#define RESET_GPU 82
+#define RESET_SDH2 83
+#define RESET_MC 84
+#define RESET_EM_AXI 85
+#define RESET_EM 86
+#define RESET_AUDIO_SYS 87
+#define RESET_HDMI 88
+#define RESET_PCIE0 89
+#define RESET_PCIE1 90
+#define RESET_PCIE2 91
+#define RESET_EMAC0 92
+#define RESET_EMAC1 93
+
+//APBC2
+#define RESET_SEC_UART1 94
+#define RESET_SEC_SSP2 95
+#define RESET_SEC_TWSI3 96
+#define RESET_SEC_RTC 97
+#define RESET_SEC_TIMERS0 98
+#define RESET_SEC_KPC 99
+#define RESET_SEC_GPIO 100
+
+#define RESET_RCPU_HDMIAUDIO 101
+#define RESET_RCPU_CAN 102
+
+#define RESET_RCPU2_PWM 103
+
+#define RESET_NUMBER 104
+
+#endif /* __DT_BINDINGS_RESET_SAPCEMIT_K1X_H__ */
diff --git a/include/dt-bindings/usb/k1x_ci_usb.h b/include/dt-bindings/usb/k1x_ci_usb.h
new file mode 100644
index 000000000000..111111111111
--- /dev/null
+++ b/include/dt-bindings/usb/k1x_ci_usb.h
@@ -0,0 +1,15 @@
+// SPDX-License-Identifier: GPL-2.0
+
+#ifndef _DT_BINDINGS_USB_MV_USB_H
+#define _DT_BINDINGS_USB_MV_USB_H
+
+#define MV_USB_HAS_VBUS_DETECTION (1 << 0)
+#define MV_USB_HAS_IDPIN_DETECTION (1 << 1)
+#define MV_USB_HAS_VBUS_IDPIN_DETECTION \
+ (MV_USB_HAS_VBUS_DETECTION | MV_USB_HAS_IDPIN_DETECTION)
+
+#define MV_USB_MODE_UDC (0)
+#define MV_USB_MODE_OTG (1)
+#define MV_USB_MODE_HOST (2)
+
+#endif
--
Armbian

File diff suppressed because it is too large Load Diff

View File

@@ -1,38 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Patrick Yavitz <pyavitz@armbian.com>
Date: Fri, 21 Jun 2024 11:54:06 -0400
Subject: add spacemit patch set
source: https://gitee.com/bianbu-linux/linux-6.1
Signed-off-by: Patrick Yavitz <pyavitz@armbian.com>
---
include/target/target_core_base.h | 5 +++++
1 file changed, 5 insertions(+)
diff --git a/include/target/target_core_base.h b/include/target/target_core_base.h
index 111111111111..222222222222 100644
--- a/include/target/target_core_base.h
+++ b/include/target/target_core_base.h
@@ -211,6 +211,10 @@ enum tcm_tmreq_table {
TMR_LUN_RESET = 5,
TMR_TARGET_WARM_RESET = 6,
TMR_TARGET_COLD_RESET = 7,
+ TMR_I_T_NEXUS_RESET = 8,
+ TMR_QUERY_TASK = 9,
+ TMR_QUERY_TASK_SET = 10,
+ TMR_QUERY_ASYNC_EVENT = 11,
TMR_LUN_RESET_PRO = 0x80,
TMR_UNKNOWN = 0xff,
};
@@ -223,6 +227,7 @@ enum tcm_tmrsp_table {
TMR_LUN_DOES_NOT_EXIST = 3,
TMR_TASK_MGMT_FUNCTION_NOT_SUPPORTED = 4,
TMR_FUNCTION_REJECTED = 5,
+ TMR_OVERLAPPED_TAG_ATTEMPTED = 6,
};
/*
--
Armbian

View File

@@ -1,780 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Patrick Yavitz <pyavitz@armbian.com>
Date: Fri, 21 Jun 2024 11:54:06 -0400
Subject: add spacemit patch set
source: https://gitee.com/bianbu-linux/linux-6.1
Signed-off-by: Patrick Yavitz <pyavitz@armbian.com>
---
include/uapi/linux/elf.h | 1 +
include/uapi/media/k1x/cam_sensor_uapi.h | 117 +++++
include/uapi/media/k1x/k1x_cpp_uapi.h | 157 ++++++
include/uapi/media/k1x/k1x_isp_drv_uapi.h | 248 ++++++++++
include/uapi/media/k1x/k1x_media_bus_format.h | 45 ++
include/uapi/media/k1x/k1x_plat_cam.h | 19 +
include/uapi/media/k1x/k1x_videodev2.h | 125 +++++
7 files changed, 712 insertions(+)
diff --git a/include/uapi/linux/elf.h b/include/uapi/linux/elf.h
index 111111111111..222222222222 100644
--- a/include/uapi/linux/elf.h
+++ b/include/uapi/linux/elf.h
@@ -439,6 +439,7 @@ typedef struct elf64_shdr {
#define NT_MIPS_DSP 0x800 /* MIPS DSP ASE registers */
#define NT_MIPS_FP_MODE 0x801 /* MIPS floating-point mode */
#define NT_MIPS_MSA 0x802 /* MIPS SIMD registers */
+#define NT_RISCV_VECTOR 0x900 /* RISC-V vector registers */
#define NT_LOONGARCH_CPUCFG 0xa00 /* LoongArch CPU config registers */
#define NT_LOONGARCH_CSR 0xa01 /* LoongArch control and status registers */
#define NT_LOONGARCH_LSX 0xa02 /* LoongArch Loongson SIMD Extension registers */
diff --git a/include/uapi/media/k1x/cam_sensor_uapi.h b/include/uapi/media/k1x/cam_sensor_uapi.h
new file mode 100644
index 000000000000..111111111111
--- /dev/null
+++ b/include/uapi/media/k1x/cam_sensor_uapi.h
@@ -0,0 +1,117 @@
+/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
+/*
+ * cam_sensor_uapi.h.c - Driver uapi for camera sensor driver
+ *
+ * Copyright (C) 2022 SPACEMIT Micro Limited
+ * All Rights Reserved.
+ */
+#ifndef __CAM_SENSOR_UAPI_H__
+#define __CAM_SENSOR_UAPI_H__
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+#define CAM_SNS_MAX_DEV_NUM 3
+
+#define CAM_SENSOR_DEV_NAME "/dev/cam_sensor"
+
+#define CAM_SENSOR_IOC_MAGIC 'I'
+
+typedef enum CAM_SENSOR_IOC {
+ SENSOR_IOC_RESET = 1,
+ SENSOR_IOC_UNRESET,
+ SENSOR_IOC_I2C_WRITE,
+ SENSOR_IOC_I2C_READ,
+ SENSOR_IOC_I2C_BURST_WRITE,
+ SENSOR_IOC_I2C_BURST_READ,
+ SENSOR_IOC_GET_INFO,
+ SENSOR_IOC_SET_MIPI_CLOCK,
+ SENSOR_IOC_SET_POWER_VOLTAGE,
+ SENSOR_IOC_SET_POWER_ON,
+ SENSOR_IOC_SET_GPIO_ENABLE,
+ SENSOR_IOC_SET_MCLK_ENABLE,
+ SENSOR_IOC_SET_MCLK_RATE,
+} CAM_SENSOR_IOC_E;
+
+typedef unsigned int sns_rst_source_t;
+typedef unsigned int sns_mipi_clock_t;
+
+struct regval_tab {
+ uint16_t reg;
+ uint16_t val;
+};
+
+enum sensor_i2c_len {
+ I2C_8BIT = 1,
+ I2C_16BIT = 2,
+ //I2C_24BIT = 3,
+ //I2C_32BIT = 4,
+};
+
+struct cam_i2c_data {
+ //uint8_t twsi_no;
+ enum sensor_i2c_len reg_len;
+ enum sensor_i2c_len val_len;
+ uint8_t addr; /* 7 bit i2c address*/
+ struct regval_tab tab;
+};
+
+struct cam_burst_i2c_data {
+ //uint8_t twsi_no;
+ enum sensor_i2c_len reg_len;
+ enum sensor_i2c_len val_len;
+ uint8_t addr; /* 7 bit i2c address*/
+ struct regval_tab *tab;
+ uint32_t num; /* the number of sensor regs*/
+};
+
+struct cam_sensor_info {
+ uint8_t twsi_no;
+};
+
+typedef enum {
+ SENSOR_REGULATOR_AFVDD,
+ SENSOR_REGULATOR_AVDD,
+ SENSOR_REGULATOR_DOVDD,
+ SENSOR_REGULATOR_DVDD,
+} cam_sensor_power_regulator_id;
+
+typedef enum {
+ SENSOR_GPIO_PWDN,
+ SENSOR_GPIO_RST,
+ SENSOR_GPIO_DVDDEN,
+ SENSOR_GPIO_DCDCEN,
+} cam_sensor_gpio_id;
+
+struct cam_sensor_power {
+ cam_sensor_power_regulator_id regulator_id;
+ uint32_t voltage;
+ uint8_t on;
+};
+
+struct cam_sensor_gpio {
+ cam_sensor_gpio_id gpio_id;
+ uint8_t enable;
+};
+
+#define CAM_SENSOR_RESET _IOW(CAM_SENSOR_IOC_MAGIC, SENSOR_IOC_RESET, sns_rst_source_t)
+#define CAM_SENSOR_UNRESET _IOW(CAM_SENSOR_IOC_MAGIC, SENSOR_IOC_UNRESET, sns_rst_source_t)
+#define CAM_SENSOR_I2C_WRITE _IOW(CAM_SENSOR_IOC_MAGIC, SENSOR_IOC_I2C_WRITE, struct cam_i2c_data)
+#define CAM_SENSOR_I2C_READ _IOW(CAM_SENSOR_IOC_MAGIC, SENSOR_IOC_I2C_READ, struct cam_i2c_data)
+#define CAM_SENSOR_I2C_BURST_WRITE _IOW(CAM_SENSOR_IOC_MAGIC, SENSOR_IOC_I2C_BURST_WRITE, struct cam_burst_i2c_data)
+#define CAM_SENSOR_I2C_BURST_READ _IOW(CAM_SENSOR_IOC_MAGIC, SENSOR_IOC_I2C_BURST_READ, struct cam_burst_i2c_data)
+#define CAM_SENSOR_GET_INFO _IOW(CAM_SENSOR_IOC_MAGIC, SENSOR_IOC_GET_INFO, struct cam_sensor_info)
+#define CAM_SENSOR_SET_MIPI_CLOCK _IOW(CAM_SENSOR_IOC_MAGIC, SENSOR_IOC_SET_MIPI_CLOCK, sns_mipi_clock_t)
+
+#define CAM_SENSOR_SET_POWER_VOLTAGE _IOW(CAM_SENSOR_IOC_MAGIC, SENSOR_IOC_SET_POWER_VOLTAGE, struct cam_sensor_power)
+#define CAM_SENSOR_SET_POWER_ON _IOW(CAM_SENSOR_IOC_MAGIC, SENSOR_IOC_SET_POWER_ON, struct cam_sensor_power)
+#define CAM_SENSOR_SET_GPIO_ENABLE _IOW(CAM_SENSOR_IOC_MAGIC, SENSOR_IOC_SET_GPIO_ENABLE, struct cam_sensor_gpio)
+#define CAM_SENSOR_SET_MCLK_ENABLE _IOW(CAM_SENSOR_IOC_MAGIC, SENSOR_IOC_SET_MCLK_ENABLE, uint32_t)
+#define CAM_SENSOR_SET_MCLK_RATE _IOW(CAM_SENSOR_IOC_MAGIC, SENSOR_IOC_SET_MCLK_RATE, uint32_t)
+
+#if defined(__cplusplus)
+}
+#endif
+
+#endif /* __CAM_SENSOR_UAPI_H__ */
diff --git a/include/uapi/media/k1x/k1x_cpp_uapi.h b/include/uapi/media/k1x/k1x_cpp_uapi.h
new file mode 100644
index 000000000000..111111111111
--- /dev/null
+++ b/include/uapi/media/k1x/k1x_cpp_uapi.h
@@ -0,0 +1,157 @@
+/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
+/*
+ * k1x_cpp_uapi.h - Driver uapi for SPACEMIT K1X Camera Post Process
+ *
+ * Copyright (C) 2022 SPACEMIT Micro Limited
+ */
+
+#ifndef __K1X_CPP_UAPI_H__
+#define __K1X_CPP_UAPI_H__
+
+#include <linux/videodev2.h>
+
+/*
+ * hw version info:
+ * 31:16 Version bits
+ * 15:0 Revision bits
+ */
+#define CPP_HW_VERSION_1_0 (0x00010000)
+#define CPP_HW_VERSION_1_1 (0x00010001)
+#define CPP_HW_VERSION_2_0 (0x00020000)
+#define CPP_HW_VERSION_2_1 (0x00020001)
+
+typedef struct reg_val_mask_info {
+ uint32_t reg_offset;
+ uint32_t val;
+ uint32_t mask;
+} hw_reg_t;
+
+enum cpp_reg_cfg_type {
+ CPP_WRITE32,
+ CPP_READ32,
+ CPP_WRITE32_RLX,
+ CPP_WRITE32_NOP,
+};
+
+enum cpp_pix_format {
+ PIXFMT_NV12_DWT = 0,
+ PIXFMT_FBC_DWT,
+};
+
+#define CPP_MAX_PLANAR (2)
+#define CPP_MAX_LAYERS (5)
+
+typedef struct cpp_reg_cfg_cmd {
+ enum cpp_reg_cfg_type reg_type;
+ uint32_t reg_len;
+ struct reg_val_mask_info *reg_data;
+} cpp_reg_cfg_cmd_t;
+
+typedef struct cpp_plane_info {
+ uint32_t type;
+ uint32_t bytesused;
+ uint32_t length;
+ union {
+ uint64_t userptr;
+ int32_t fd;
+ uint64_t phyAddr;
+ } m;
+ uint32_t data_offset;
+} cpp_plane_info_t;
+
+typedef struct cpp_buffer_info {
+ unsigned int index;
+ unsigned int num_layers;
+ unsigned int kgain_used;
+ enum cpp_pix_format format;
+ struct cpp_plane_info dwt_planes[CPP_MAX_LAYERS][CPP_MAX_PLANAR];
+ struct cpp_plane_info kgain_planes[CPP_MAX_LAYERS];
+} cpp_buffer_info_t;
+
+#define MAX_REG_CMDS (3)
+#define MAX_REG_DATA (640)
+typedef struct cpp_frame_info {
+ uint32_t frame_id;
+ uint32_t client_id;
+ struct cpp_reg_cfg_cmd regs[MAX_REG_CMDS];
+ struct cpp_buffer_info src_buf_info;
+ struct cpp_buffer_info dst_buf_info;
+ struct cpp_buffer_info pre_buf_info;
+} cpp_frame_info_t;
+
+struct k1x_cpp_reg_cfg {
+ enum cpp_reg_cfg_type cmd_type;
+ union {
+ struct reg_val_mask_info rw_info;
+ } u;
+};
+
+struct cpp_hw_info {
+ uint32_t cpp_hw_version;
+ uint32_t low_pwr_mode;
+};
+
+struct cpp_bandwidth_info {
+ int32_t rsum;
+ int32_t wsum;
+};
+
+struct cpp_clock_info {
+ uint32_t func_rate;
+};
+
+#define VIDIOC_K1X_CPP_REG_CFG \
+ _IOWR('V', BASE_VIDIOC_PRIVATE, struct k1x_cpp_reg_cfg)
+
+#define VIDIOC_K1X_CPP_PROCESS_FRAME \
+ _IOWR('V', BASE_VIDIOC_PRIVATE + 1, struct cpp_frame_info)
+
+#define VIDIOC_K1X_CPP_HW_RST \
+ _IO('V', BASE_VIDIOC_PRIVATE + 2)
+
+#define VIDIOC_K1X_CPP_LOW_PWR \
+ _IOWR('V', BASE_VIDIOC_PRIVATE + 3, int)
+
+#define VIDIOC_K1X_CPP_FLUSH_QUEUE \
+ _IO('V', BASE_VIDIOC_PRIVATE + 4)
+
+#define VIDIOC_K1X_CPP_HW_INFO \
+ _IOWR('V', BASE_VIDIOC_PRIVATE + 5, struct cpp_hw_info)
+
+#define VIDIOC_K1X_CPP_IOMMU_ATTACH \
+ _IO('V', BASE_VIDIOC_PRIVATE + 6)
+
+#define VIDIOC_K1X_CPP_IOMMU_DETACH \
+ _IO('V', BASE_VIDIOC_PRIVATE + 7)
+
+#define VIDIOC_K1X_CPP_UPDATE_BANDWIDTH \
+ _IOWR('V', BASE_VIDIOC_PRIVATE + 8, struct cpp_bandwidth_info)
+
+#define VIDIOC_K1X_CPP_UPDATE_CLOCKRATE \
+ _IOWR('V', BASE_VIDIOC_PRIVATE + 9, struct cpp_clock_info)
+
+struct k1x_cpp_done_info {
+ uint32_t frame_id;
+ uint32_t client_id;
+ uint64_t seg_reg_cfg;
+ uint64_t seg_stream;
+ uint8_t success;
+};
+
+struct k1x_cpp_error_info {
+ uint32_t frame_id;
+ uint32_t client_id;
+ uint32_t err_type;
+};
+
+struct k1x_cpp_event_data {
+ union {
+ struct k1x_cpp_done_info done_info;
+ struct k1x_cpp_error_info err_info;
+ } u; /* union can have max 64 bytes */
+};
+
+#define V4L2_EVENT_CPP_FRAME_DONE (V4L2_EVENT_PRIVATE_START + 0)
+#define V4L2_EVENT_CPP_FRAME_ERR (V4L2_EVENT_PRIVATE_START + 1)
+
+#endif /* __K1X_CPP_UAPI_H__ */
diff --git a/include/uapi/media/k1x/k1x_isp_drv_uapi.h b/include/uapi/media/k1x/k1x_isp_drv_uapi.h
new file mode 100644
index 000000000000..111111111111
--- /dev/null
+++ b/include/uapi/media/k1x/k1x_isp_drv_uapi.h
@@ -0,0 +1,248 @@
+/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
+
+#ifndef K1XISP_DEV_DRV_API_H
+#define K1XISP_DEV_DRV_API_H
+
+#include <linux/types.h>
+
+#define IOC_K1X_ISP_TYPE 'D'
+//#define K1X_ISP_DEV_NAME "k1xisp"
+//#define K1X_ISP_PIPE_DEV_NAME "k1xisp-pipe"
+#define K1X_ISP_DEV_NAME "mars11isp"
+#define K1X_ISP_PIPE_DEV_NAME "mars11isp-pipe"
+
+#define K1X_ISP_MAX_PLANE_NUM 4
+#define K1X_ISP_MAX_BUFFER_NUM 4
+
+#define K1X_ISP_PDC_CHANNEL_NUM 4
+
+#define K1XISP_SLICE_MAX_NUM 6
+#define K1XISP_SLICE_REG_MAX_NUM 30
+
+/*----------------------- struct define ----------------------- */
+enum isp_pipe_work_type {
+ ISP_PIPE_WORK_TYPE_INIT,
+ ISP_PIPE_WORK_TYPE_PREVIEW,
+ ISP_PIPE_WORK_TYPE_CAPTURE,
+ ISP_PIPE_WORK_TYPE_MAX,
+};
+
+enum isp_hw_pipeline_id {
+ ISP_HW_PIPELINE_ID_0,
+ ISP_HW_PIPELINE_ID_1,
+ ISP_HW_PIPELINE_ID_MAX,
+};
+
+enum isp_stat_id {
+ ISP_STAT_ID_AE,
+ ISP_STAT_ID_AWB,
+ ISP_STAT_ID_LTM,
+ ISP_STAT_ID_AF,
+ ISP_STAT_ID_PDC,
+ ISP_STAT_ID_EIS, //5
+ ISP_STAT_ID_MAX,
+};
+
+enum isp_pipe_task_type {
+ ISP_PIPE_TASK_TYPE_SOF, //firmware calc task at sof
+ ISP_PIPE_TASK_TYPE_EOF, //firmware calc task at eof
+ ISP_PIPE_TASK_TYPE_AF, //firmware calc AF stat task
+ ISP_PIPE_TASK_TYPE_MAX,
+};
+
+/**
+ * struct isp_buffer_plane - description of buffer plane used in k1xisp.
+ *
+ * @m: the id of the buffer, phy_addr(physical address) or fd(ion buffer).
+ * @pitch: the pitch of this plane
+ * @offset: the plane's offset of this buffer, usually is zero; .
+ * @length: the length of this plane.
+ * @reserved: reserve for private use, such as pdc can use for channel_cnt(0) and channel_width(1).
+ */
+struct isp_buffer_plane {
+ union {
+ __u64 phy_addr;
+ __s32 fd;
+ } m;
+ __u32 pitch;
+ __u32 offset;
+ __u32 length;
+ __u32 reserved[2];
+};
+
+/**
+ * struct isp_ubuf_uint - the description of buffer used in user space.
+ *
+ * @plane_count: the count of planes in this buffer.
+ * @buf_index: the index of this buffer in the queue.
+ * @buf_planes: planes in this buffer.
+ */
+struct isp_ubuf_uint {
+ __u32 plane_count;
+ __s32 buf_index; /* the index of this buffer in the queue. */
+ struct isp_buffer_plane buf_planes[K1X_ISP_MAX_PLANE_NUM];
+};
+
+/**
+ * struct isp_buffer_enqueue_info - the info of buffer enqueued by user space.
+ *
+ * @ubuf_uint: the buffer info enqueued by user space.
+ */
+struct isp_buffer_enqueue_info {
+ struct isp_ubuf_uint ubuf_uint[ISP_STAT_ID_MAX];
+};
+
+/**
+ * struct isp_buffer_request_info - the info of buffer requested by user space.
+ *
+ * @stat_buf_count: count of buffer used in the stat's queue.
+ */
+struct isp_buffer_request_info {
+ __u32 stat_buf_count[ISP_STAT_ID_MAX];
+};
+
+struct isp_reg_unit {
+ __u32 reg_addr;
+ __u32 reg_value;
+ __u32 reg_mask;
+};
+
+struct isp_regs_info {
+ union {
+ __u64 phy_addr;
+ __s32 fd;
+ } mem;
+ __u32 size;
+ void *data; /* contains some isp_reg_unit */
+ __u32 mem_index;
+};
+
+struct isp_slice_regs {
+ __u32 reg_count;
+ void *data; /* contains some isp_reg_unit */
+};
+
+struct isp_capture_slice_pack {
+ __s32 slice_width;
+ __s32 raw_read_offset;
+ __s32 yuv_out_offset;
+ __s32 dwt_offset[4];
+ struct isp_slice_regs slice_reg;
+};
+
+struct isp_capture_package {
+ __u32 slice_count;
+ struct isp_capture_slice_pack capture_slice_packs[K1XISP_SLICE_MAX_NUM];
+};
+
+enum isp_work_status {
+ ISP_WORK_STATUS_INIT,
+ ISP_WORK_STATUS_START,
+ ISP_WORK_STATUS_STOP,
+ ISP_WORK_STATUS_DONE, //for once work, licke capture
+ ISP_WORK_STATUS_RESTART,//isp hardware error happen, need to reset
+};
+
+enum isp_job_action {
+ ISP_JOB_ACTION_START,
+ ISP_JOB_ACTION_SWITCH,
+ ISP_JOB_ACTION_STOP,
+ ISP_JOB_ACTION_RESTART,
+};
+
+/**
+ * struct isp_job_describer - the job info of isp determined by user space.
+ *
+ * @work_type: the work type of the hw pipeline, which is defined by &enum isp_pipe_work_type
+ * @action: the action of job, which is defined by &enum isp_job_action.
+ */
+struct isp_job_describer {
+ __u32 work_type;
+ __u32 action;
+};
+
+/**
+ * struct isp_drv_deployment - the setting of isp driver setted by user space.
+ *
+ * @reg_mem: the ID of the buffer(fd or phy addr).
+ * @fd_buffer: the buffer use fd to transfer if true.
+ * @reg_mem_size: the size of buffer filled with registers.
+ * @reg_mem_index: the index of reg memory.
+ */
+struct isp_drv_deployment {
+ union {
+ __u64 phy_addr;
+ __s32 fd;
+ } reg_mem;
+ __u32 fd_buffer;
+ __u32 reg_mem_size;
+ __u32 work_type;
+ __u32 reg_mem_index;
+};
+
+/**
+ * struct isp_user_task_info - the info of task run user space.
+ *
+ * @task_type: the type fo this user task, whose value defined by &enum isp_pipe_task_type
+ * @frame_number: the current frame number of the hw pipeline
+ * @work_status: the current work status of the hw pipeline, defined by &isp_work_status
+ */
+struct isp_user_task_info {
+ __u32 task_type;
+ __u32 frame_number;
+ __u32 work_status;
+ __u8 result_valid;
+ union {
+ struct {
+ struct isp_ubuf_uint ltm_result;
+ struct isp_ubuf_uint awb_result;
+ struct isp_ubuf_uint eis_result;
+ struct isp_ubuf_uint ae_result;
+ // __u32 rgbir_avg[2]; /* AVG0 and AVG1 */
+ } sof_task;
+ struct {
+ struct isp_ubuf_uint ae_result;
+ } eof_task;
+ struct {
+ struct isp_ubuf_uint af_result;
+ struct isp_ubuf_uint pdc_result;
+ } af_task;
+ } stats_result;
+};
+
+struct isp_endframe_work_info {
+ __u32 process_ae_by_sof;
+ __u32 get_frameinfo_by_eof;
+};
+
+/*----------------------- ioctl command ----------------------- */
+typedef enum ISP_IOC_NR {
+ ISP_IOC_NR_DEPLOY_DRV = 1,
+ ISP_IOC_NR_UNDEPLOY_DRV,
+ ISP_IOC_NR_SET_REG,
+ ISP_IOC_NR_GET_REG,
+ ISP_IOC_NR_ENABLE_PDC,
+ ISP_IOC_NR_SET_JOB,
+ ISP_IOC_NR_GET_INTERRUPT,
+ ISP_IOC_NR_REQUEST_BUFFER,
+ ISP_IOC_NR_ENQUEUE_BUFFER,
+ ISP_IOC_NR_FLUSH_BUFFER,
+ ISP_IOC_NR_TRIGGER_CAPTURE,
+ ISP_IOC_NR_SET_SINGLE_REG,
+ ISP_IOC_NR_SET_END_FRAME_WORK,
+} ISP_IOC_NR_E;
+
+#define ISP_IOC_DEPLOY_DRV _IOWR(IOC_K1X_ISP_TYPE, ISP_IOC_NR_DEPLOY_DRV, struct isp_drv_deployment)
+#define ISP_IOC_UNDEPLOY_DRV _IOWR(IOC_K1X_ISP_TYPE, ISP_IOC_NR_UNDEPLOY_DRV, __u32)
+#define ISP_IOC_SET_REG _IOW(IOC_K1X_ISP_TYPE, ISP_IOC_NR_SET_REG, struct isp_regs_info)
+#define ISP_IOC_GET_REG _IOWR(IOC_K1X_ISP_TYPE, ISP_IOC_NR_GET_REG, struct isp_regs_info)
+#define ISP_IOC_SET_PDC _IOW(IOC_K1X_ISP_TYPE, ISP_IOC_NR_ENABLE_PDC, __u32)
+#define ISP_IOC_SET_JOB _IOW(IOC_K1X_ISP_TYPE, ISP_IOC_NR_SET_JOB, struct isp_job_describer)
+#define ISP_IOC_GET_INTERRUPT _IOWR(IOC_K1X_ISP_TYPE, ISP_IOC_NR_GET_INTERRUPT, struct isp_user_task_info)
+#define ISP_IOC_REQUEST_BUFFER _IOWR(IOC_K1X_ISP_TYPE, ISP_IOC_NR_REQUEST_BUFFER, struct isp_buffer_request_info)
+#define ISP_IOC_ENQUEUE_BUFFER _IOWR(IOC_K1X_ISP_TYPE, ISP_IOC_NR_ENQUEUE_BUFFER, struct isp_buffer_enqueue_info)
+#define ISP_IOC_FLUSH_BUFFER _IOWR(IOC_K1X_ISP_TYPE, ISP_IOC_NR_FLUSH_BUFFER, __u32)
+#define ISP_IOC_TRIGGER_CAPTURE _IOWR(IOC_K1X_ISP_TYPE, ISP_IOC_NR_TRIGGER_CAPTURE, struct isp_capture_package)
+#define ISP_IOC_SET_SINGLE_REG _IOW(IOC_K1X_ISP_TYPE, ISP_IOC_NR_SET_SINGLE_REG, struct isp_reg_unit)
+#define ISP_IOC_SET_END_FRAME_WORK _IOW(IOC_K1X_ISP_TYPE, ISP_IOC_NR_SET_END_FRAME_WORK, struct isp_endframe_work_info)
+#endif
diff --git a/include/uapi/media/k1x/k1x_media_bus_format.h b/include/uapi/media/k1x/k1x_media_bus_format.h
new file mode 100644
index 000000000000..111111111111
--- /dev/null
+++ b/include/uapi/media/k1x/k1x_media_bus_format.h
@@ -0,0 +1,45 @@
+/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
+/*
+ * k1x_videodev2 - Driver uapi for SPACEMIT K1X media bus format
+ *
+ * Copyright (C) 2019 SPACEMIT Micro Limited
+ */
+
+#ifndef __LINUX_K1X_MEDIA_BUS_FORMAT_H
+#define __LINUX_K1X_MEDIA_BUS_FORMAT_H
+
+#ifndef BIT
+#define BIT(nr) (1 << (nr))
+#endif
+#define SPACEMIT_VI_SWITCH_FLAGS_SHIFT (8)
+#define SPACEMIT_VI_FLAG_BACK_TO_PREVIEW BIT(0)
+#define SPACEMIT_VI_FLAG_CLK_HIGH BIT(1)
+#define SPACEMIT_VI_FLAG_FORCE_SW_GAP BIT(2)
+#define SPACEMIT_VI_PRI_DATA_MASK (0xff)
+#define SPACEMIT_VI_MIPI_LANE_MASK (BIT(0) | BIT(1) | BIT(2))
+#define SPACEMIT_VI_SENSOR_ID_SHIFT (3)
+#define SPACEMIT_VI_SENSOR_ID_MASK (BIT(3) | BIT(4))
+
+#define MEDIA_BUS_FMT_UYVY10_1_5X10 0x3104
+#define MEDIA_BUS_FMT_VYUY10_1_5X10 0x3105
+#define MEDIA_BUS_FMT_YUYV10_1_5X10 0x3106
+#define MEDIA_BUS_FMT_YVYU10_1_5X10 0x3107
+//nv12 dwt
+#define MEDIA_BUS_FMT_YUYV10_1_5X10_D1 0x3108
+#define MEDIA_BUS_FMT_YUYV10_1_5X10_D2 0x3109
+#define MEDIA_BUS_FMT_YUYV10_1_5X10_D3 0x310A
+#define MEDIA_BUS_FMT_YUYV10_1_5X10_D4 0x310B
+//Bayer raw
+#define MEDIA_BUS_FMT_SRGB8_SPACEMITPACK_1X8 0x310C
+#define MEDIA_BUS_FMT_SRGB10_SPACEMITPACK_1X10 0x310D
+#define MEDIA_BUS_FMT_SRGB12_SPACEMITPACK_1X12 0x310E
+#define MEDIA_BUS_FMT_SRGB14_SPACEMITPACK_1X14 0x310F
+//afbc
+#define MEDIA_BUS_FMT_YUYV8_1_5X8_AFBC 0x3110
+//nv21 dwt
+#define MEDIA_BUS_FMT_YVYU10_1_5X10_D1 0x3111
+#define MEDIA_BUS_FMT_YVYU10_1_5X10_D2 0x3112
+#define MEDIA_BUS_FMT_YVYU10_1_5X10_D3 0x3113
+#define MEDIA_BUS_FMT_YVYU10_1_5X10_D4 0x3114
+
+#endif
diff --git a/include/uapi/media/k1x/k1x_plat_cam.h b/include/uapi/media/k1x/k1x_plat_cam.h
new file mode 100644
index 000000000000..111111111111
--- /dev/null
+++ b/include/uapi/media/k1x/k1x_plat_cam.h
@@ -0,0 +1,19 @@
+/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
+#ifndef _UAPI_K1X_PLAT_CAM_H
+#define _UAPI_K1X_PLAT_CAM_H
+
+#define PLAT_CAM_NAME "platform-cam"
+
+/*
+ * Base number ranges for k1x entity functions
+ * belong to either MEDIA_ENT_F_OLD_BASE or MEDIA_ENT_F_TUNER
+ * ranges
+ */
+#define MEDIA_ENT_F_K1X_BASE 0x00010000
+
+#define MEDIA_ENT_F_K1X_VI (MEDIA_ENT_F_K1X_BASE + 0x1001)
+#define MEDIA_ENT_F_K1X_CPP (MEDIA_ENT_F_K1X_BASE + 0x1002)
+#define MEDIA_ENT_F_K1X_VBE (MEDIA_ENT_F_K1X_BASE + 0x1003)
+#define MEDIA_ENT_F_K1X_SENSOR (MEDIA_ENT_F_K1X_BASE + 0x1004)
+
+#endif /* _UAPI_K1X_PLAT_CAM_H */
diff --git a/include/uapi/media/k1x/k1x_videodev2.h b/include/uapi/media/k1x/k1x_videodev2.h
new file mode 100644
index 000000000000..111111111111
--- /dev/null
+++ b/include/uapi/media/k1x/k1x_videodev2.h
@@ -0,0 +1,125 @@
+/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
+/*
+ * k1x_videodev2.h - Driver uapi for SPACEMIT K1X videvdev2
+ *
+ * Copyright (C) 2019 SPACEMIT Micro Limited
+ */
+
+#ifndef _UAPI_LINUX_K1X_VIDEODEV2_H_
+#define _UAPI_LINUX_K1X_VIDEODEV2_H_
+#include <linux/videodev2.h>
+
+/* afbc yuv */
+#define V4L2_PIX_FMT_NV12_AFBC v4l2_fourcc('A', 'F', '1', '2')
+/* 10bit yuv */
+#define V4L2_PIX_FMT_Y210 v4l2_fourcc('Y', '2', '1', '0')
+#define V4L2_PIX_FMT_P210 v4l2_fourcc('P', '2', '1', '0')
+#define V4L2_PIX_FMT_P010 v4l2_fourcc('P', '0', '1', '0')
+#define V4L2_PIX_FMT_D010_1 v4l2_fourcc('D', '0', '1', '1')
+#define V4L2_PIX_FMT_D010_2 v4l2_fourcc('D', '0', '1', '2')
+#define V4L2_PIX_FMT_D010_3 v4l2_fourcc('D', '0', '1', '3')
+#define V4L2_PIX_FMT_D010_4 v4l2_fourcc('D', '0', '1', '4')
+#define V4L2_PIX_FMT_D210_1 v4l2_fourcc('D', '2', '1', '1')
+#define V4L2_PIX_FMT_D210_2 v4l2_fourcc('D', '2', '1', '2')
+#define V4L2_PIX_FMT_D210_3 v4l2_fourcc('D', '2', '1', '3')
+#define V4L2_PIX_FMT_D210_4 v4l2_fourcc('D', '2', '1', '4')
+/* Bayer raw spacemit packed */
+#define V4L2_PIX_FMT_SPACEMITGB8P v4l2_fourcc('p', 'R', 'W', '8')
+#define V4L2_PIX_FMT_SPACEMITGB10P v4l2_fourcc('p', 'R', 'W', 'A')
+#define V4L2_PIX_FMT_SPACEMITGB12P v4l2_fourcc('p', 'R', 'W', 'C')
+#define V4L2_PIX_FMT_SPACEMITGB14P v4l2_fourcc('p', 'R', 'W', 'E')
+
+#define V4L2_BUF_FLAG_IGNOR (1 << 31)
+#define V4L2_BUF_FLAG_ERROR_HW (1 << 30)
+#define V4L2_BUF_FLAG_IDI_OVERRUN (1 << 29)
+#define V4L2_BUF_FLAG_SLICES_DONE (1 << 28)
+#define V4L2_BUF_FLAG_CLOSE_DOWN (1 << 27)
+#define V4l2_BUF_FLAG_FORCE_SHADOW (1 << 26)
+#define V4L2_BUF_FLAG_ERROR_SW (0)
+
+#define V4L2_VI_PORT_USAGE_SNAPSHOT (1 << 0)
+
+struct v4l2_vi_port_cfg {
+ unsigned int port_entity_id;
+ unsigned int offset;
+ unsigned int depth;
+ unsigned int weight;
+ unsigned int div_mode;
+ unsigned int usage;
+};
+
+#define SPACEMIT_VI_ENTITY_NAME_LEN (32)
+
+struct v4l2_vi_entity_info {
+ unsigned int id;
+ char name[SPACEMIT_VI_ENTITY_NAME_LEN];
+};
+
+struct v4l2_vi_dbg_reg {
+ unsigned int addr;
+ unsigned int value;
+ unsigned int mask;
+};
+
+struct v4l2_vi_input_interface {
+ unsigned int type;
+ unsigned int ccic_idx;
+ unsigned int ccic_trigger_line;
+};
+
+struct v4l2_vi_selection {
+ unsigned int pad;
+ struct v4l2_selection v4l2_sel;
+};
+
+enum {
+ VI_INPUT_INTERFACE_OFFLINE = 0,
+ VI_INPUT_INTERFACE_OFFLINE_SLICE,
+ VI_INPUT_INTERFACE_MIPI,
+};
+
+enum {
+ VI_PIPE_RESET_STAGE1 = 0,
+ VI_PIPE_RESET_STAGE2,
+ VI_PIPE_RESET_STAGE3,
+ VI_PIPE_RESET_STAGE_CNT,
+};
+
+struct v4l2_vi_bandwidth_info {
+ int rsum;
+ int wsum;
+};
+
+struct v4l2_vi_slice_info {
+ unsigned int timeout;
+ int slice_id;
+ int total_slice_cnt;
+};
+
+struct v4l2_vi_debug_dump {
+ int reason;
+};
+
+#define BASE_VIDIOC_VI (BASE_VIDIOC_PRIVATE + 20)
+#define VIDIOC_GET_PIPELINE _IO('V', BASE_VIDIOC_VI + 1)
+#define VIDIOC_PUT_PIPELINE _IOW('V', BASE_VIDIOC_VI + 2, int)
+#define VIDIOC_APPLY_PIPELINE _IO('V', BASE_VIDIOC_VI + 3)
+#define VIDIOC_START_PIPELINE _IO('V', BASE_VIDIOC_VI + 4)
+#define VIDIOC_STOP_PIPELINE _IO('V', BASE_VIDIOC_VI + 5)
+#define VIDIOC_S_PORT_CFG _IOW('V', BASE_VIDIOC_VI + 6, struct v4l2_vi_port_cfg)
+#define VIDIOC_DBG_REG_WRITE _IOWR('V', BASE_VIDIOC_VI + 7, struct v4l2_vi_dbg_reg)
+#define VIDIOC_DBG_REG_READ _IOWR('V', BASE_VIDIOC_VI + 8, struct v4l2_vi_dbg_reg)
+#define VIDIOC_CFG_INPUT_INTF _IOW('V', BASE_VIDIOC_VI + 9, struct v4l2_vi_input_interface)
+#define VIDIOC_RESET_PIPELINE _IOW('V', BASE_VIDIOC_VI + 10, int)
+#define VIDIOC_G_PIPE_STATUS _IOR('V', BASE_VIDIOC_VI + 11, unsigned int)
+#define VIDIOC_SET_SELECTION _IOW('V', BASE_VIDIOC_VI + 12, struct v4l2_vi_selection)
+#define VIDIOC_G_SLICE_MODE _IOR('V', BASE_VIDIOC_VI + 13, int)
+#define VIDIOC_QUERY_SLICE_READY _IOWR('V', BASE_VIDIOC_VI + 14, struct v4l2_vi_slice_info)
+#define VIDIOC_S_SLICE_DONE _IOW('V', BASE_VIDIOC_VI + 15, int)
+#define VIDIOC_GLOBAL_RESET _IO('V', BASE_VIDIOC_VI + 16)
+#define VIDIOC_FLUSH_BUFFERS _IO('V', BASE_VIDIOC_VI + 17)
+#define VIDIOC_CPU_Z1 _IOR('V', BASE_VIDIOC_VI + 18, int)
+#define VIDIOC_DEBUG_DUMP _IOWR('V', BASE_VIDIOC_VI + 19, struct v4l2_vi_debug_dump)
+#define VIDIOC_S_BANDWIDTH _IOW('V', BASE_VIDIOC_VI + 39, struct v4l2_vi_bandwidth_info)
+#define VIDIOC_G_ENTITY_INFO _IOWR('V', BASE_VIDIOC_VI + 40, struct v4l2_vi_entity_info)
+#endif
--
Armbian

View File

@@ -1,31 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Patrick Yavitz <pyavitz@armbian.com>
Date: Fri, 21 Jun 2024 11:54:06 -0400
Subject: add spacemit patch set
source: https://gitee.com/bianbu-linux/linux-6.1
Signed-off-by: Patrick Yavitz <pyavitz@armbian.com>
---
lib/scatterlist.c | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/lib/scatterlist.c b/lib/scatterlist.c
index 111111111111..222222222222 100644
--- a/lib/scatterlist.c
+++ b/lib/scatterlist.c
@@ -616,7 +616,11 @@ struct scatterlist *sgl_alloc_order(unsigned long long length,
nalloc++;
}
sgl = kmalloc_array(nalloc, sizeof(struct scatterlist),
+#if defined(CONFIG_SOC_SPACEMIT_K1X)
+ gfp & ~(GFP_DMA | GFP_DMA32));
+#else
gfp & ~GFP_DMA);
+#endif
if (!sgl)
return NULL;
--
Armbian

View File

@@ -1,28 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Patrick Yavitz <pyavitz@armbian.com>
Date: Fri, 21 Jun 2024 11:54:06 -0400
Subject: add spacemit patch set
source: https://gitee.com/bianbu-linux/linux-6.1
Signed-off-by: Patrick Yavitz <pyavitz@armbian.com>
---
net/wireless/reg.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/net/wireless/reg.c b/net/wireless/reg.c
index 111111111111..222222222222 100644
--- a/net/wireless/reg.c
+++ b/net/wireless/reg.c
@@ -1043,7 +1043,7 @@ static void regdb_fw_cb(const struct firmware *fw, void *context)
void *db;
if (!fw) {
- pr_info("failed to load regulatory.db\n");
+ pr_debug("failed to load regulatory.db\n");
set_error = -ENODATA;
} else if (!valid_regdb(fw->data, fw->size)) {
pr_info("loaded regulatory.db is malformed or signature is missing/invalid\n");
--
Armbian

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -1,71 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Patrick Yavitz <pyavitz@armbian.com>
Date: Wed, 26 Jun 2024 06:01:30 -0400
Subject: Bluetooth: hci_h5: Add support for RTL8852BS
Signed-off-by: Patrick Yavitz <pyavitz@armbian.com>
---
drivers/bluetooth/hci_h5.c | 2 ++
1 file changed, 2 insertions(+)
diff --git a/drivers/bluetooth/hci_h5.c b/drivers/bluetooth/hci_h5.c
index 111111111111..222222222222 100644
--- a/drivers/bluetooth/hci_h5.c
+++ b/drivers/bluetooth/hci_h5.c
@@ -1106,6 +1106,8 @@ static const struct of_device_id rtl_bluetooth_of_match[] = {
.data = (const void *)&h5_data_rtl8723bs },
{ .compatible = "realtek,rtl8723ds-bt",
.data = (const void *)&h5_data_rtl8723bs },
+ { .compatible = "realtek,rtl8852bs-bt",
+ .data = (const void *)&h5_data_rtl8723bs },
#endif
{ },
};
--
Armbian
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Victor Hassan <victor@allwinnertech.com>
Date: Wed, 22 Feb 2023 17:47:20 +0800
Subject: Bluetooth: btrtl: Add support for RTL8852BS
Add the support for RTL8852BS BT controller on UART interface.
The necessary firmware file will be submitted to linux-firmware.
Signed-off-by: Victor Hassan <victor@allwinnertech.com>
Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
---
drivers/bluetooth/btrtl.c | 10 ++++++++++
1 file changed, 10 insertions(+)
diff --git a/drivers/bluetooth/btrtl.c b/drivers/bluetooth/btrtl.c
index 111111111111..222222222222 100644
--- a/drivers/bluetooth/btrtl.c
+++ b/drivers/bluetooth/btrtl.c
@@ -231,6 +231,14 @@ static const struct id_table ic_id_table[] = {
.fw_name = "rtl_bt/rtl8852au_fw.bin",
.cfg_name = "rtl_bt/rtl8852au_config" },
+ /* 8852B with UART interface */
+ { IC_INFO(RTL_ROM_LMP_8852A, 0xb, 0xb, HCI_UART),
+ .config_needed = true,
+ .has_rom_version = true,
+ .has_msft_ext = true,
+ .fw_name = "rtl_bt/rtl8852bs_fw.bin",
+ .cfg_name = "rtl_bt/rtl8852bs_config" },
+
/* 8852B */
{ IC_INFO(RTL_ROM_LMP_8852A, 0xb, 0xb, HCI_USB),
.config_needed = false,
@@ -1100,6 +1108,8 @@ MODULE_FIRMWARE("rtl_bt/rtl8851bu_fw.bin");
MODULE_FIRMWARE("rtl_bt/rtl8851bu_config.bin");
MODULE_FIRMWARE("rtl_bt/rtl8852au_fw.bin");
MODULE_FIRMWARE("rtl_bt/rtl8852au_config.bin");
+MODULE_FIRMWARE("rtl_bt/rtl8852bs_fw.bin");
+MODULE_FIRMWARE("rtl_bt/rtl8852bs_config.bin");
MODULE_FIRMWARE("rtl_bt/rtl8852bu_fw.bin");
MODULE_FIRMWARE("rtl_bt/rtl8852bu_config.bin");
MODULE_FIRMWARE("rtl_bt/rtl8852cu_fw.bin");
--
Armbian

View File

@@ -1,56 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Luca Barbato <noone@nowhere.com>
Date: Thu, 6 Jun 2024 03:49:34 -0400
Subject: add minimal hwmon support
Signed-off-by: Luca Barbato
---
drivers/thermal/k1x-thermal.c | 22 +++++++---
1 file changed, 16 insertions(+), 6 deletions(-)
diff --git a/drivers/thermal/k1x-thermal.c b/drivers/thermal/k1x-thermal.c
index 111111111111..222222222222 100644
--- a/drivers/thermal/k1x-thermal.c
+++ b/drivers/thermal/k1x-thermal.c
@@ -10,6 +10,7 @@
#include <linux/thermal.h>
#include <linux/reset.h>
#include "k1x-thermal.h"
+#include "thermal_hwmon.h"
#define MAX_SENSOR_NUMBER 5
@@ -286,15 +287,24 @@ static int k1x_thermal_probe(struct platform_device *pdev)
for (i = s->sr[0]; i <= s->sr[1]; ++i) {
s->sdesc[i].base = s->base;
- s->sdesc[i].tzd = devm_thermal_of_zone_register(dev,
- i, s->sdesc + i, &k1x_of_thermal_ops);
- if (IS_ERR(s->sdesc[i].tzd)) {
- ret = PTR_ERR(s->sdesc[i].tzd);
- dev_err(dev, "faild to register sensor id %d: %d\n",
- i, ret);
+ struct thermal_zone_device *tzd =
+ devm_thermal_of_zone_register(dev, i, s->sdesc + i, &k1x_of_thermal_ops);
+ if (IS_ERR(tzd)) {
+ ret = PTR_ERR(tzd);
+ dev_err_probe(dev, ret, "faild to register sensor id %d", i);
return ret;
}
+ tzd->tzp->no_hwmon = false;
+
+ ret = devm_thermal_add_hwmon_sysfs(tzd);
+ if (ret < 0) {
+ dev_err_probe(dev, ret, "failed to register the hwmon entry");
+ return ret;
+ }
+
+ s->sdesc[i].tzd = tzd;
+
ret = devm_request_threaded_irq(dev, s->irq, k1x_thermal_irq,
k1x_thermal_irq_thread, IRQF_SHARED,
dev_name(&s->sdesc[i].tzd->device), s->sdesc + i);
--
Armbian

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -1,443 +0,0 @@
From 05bebc19949413beb180f86c3efb10957713658a Mon Sep 17 00:00:00 2001
From: Patrick Yavitz <pyavitz@armbian.com>
Date: Tue, 16 Jul 2024 08:47:05 -0400
Subject: [PATCH] update to v1.0.8
source: https://gitee.com/bianbu-linux/linux-6.1
Signed-off-by: James Deng <james.deng@spacemit.com>
Signed-off-by: Patrick Yavitz <pyavitz@armbian.com>
---
drivers/cpufreq/spacemit-cpufreq.c | 35 +++-
drivers/crypto/spacemit/spacemit_ce_engine.c | 13 +-
drivers/i2c/busses/i2c-k1x.c | 5 +-
drivers/pwm/pwm-pxa.c | 6 +-
.../soc/spacemit/pm_domain/k1x-pm_domain.c | 8 +
drivers/usb/phy/Makefile | 2 +-
scripts/package/generic | 16 ++
sound/soc/spacemit/spacemit-snd-pcm-dma.c | 150 +++++++-----------
8 files changed, 124 insertions(+), 111 deletions(-)
create mode 100644 scripts/package/generic
diff --git a/drivers/cpufreq/spacemit-cpufreq.c b/drivers/cpufreq/spacemit-cpufreq.c
index 52d40d7f25fe..ce81b344a1c6 100644
--- a/drivers/cpufreq/spacemit-cpufreq.c
+++ b/drivers/cpufreq/spacemit-cpufreq.c
@@ -36,9 +36,15 @@ of_hotplug_cooling_register(struct cpufreq_policy *policy);
#define TURBO_FREQUENCY (1600000000)
#define STABLE_FREQUENCY (1200000000)
-#define FILTER_POINTS (140)
+
+#define FILTER_POINTS_0 (135)
+#define FILTER_POINTS_1 (142)
+
#define FREQ_TABLE_0 (0)
#define FREQ_TABLE_1 (1)
+#define FREQ_TABLE_2 (2)
+
+#define PRODUCT_ID_M1 (0x36070000)
static int spacemit_policy_notifier(struct notifier_block *nb,
unsigned long event, void *data)
@@ -390,7 +396,9 @@ static int spacemit_dt_cpufreq_pre_probe(struct platform_device *pdev)
{
int cpu;
struct device_node *cpus;
+ struct device_node *product_id, *wafer_id;
u32 prop = 0;
+ u32 product_prop, wafer_prop;
if (strncmp(pdev->name, "cpufreq-dt", 10) != 0)
return 0;
@@ -400,8 +408,29 @@ static int spacemit_dt_cpufreq_pre_probe(struct platform_device *pdev)
pr_info("Spacemit Platform with no 'svt-dro' in DTS, using defualt frequency Table0\n");
}
- for_each_possible_cpu(cpu) {
- spacemit_dt_cpufreq_pre_early_init(&pdev->dev, cpu, prop >= FILTER_POINTS ? FREQ_TABLE_1 : FREQ_TABLE_0);
+ product_id = of_find_node_by_path("/");
+ if (!product_id || of_property_read_u32(product_id, "product-id", &product_prop)) {
+ pr_info("Spacemit Platform with no 'product-id' in DTS\n");
+ }
+
+ wafer_id = of_find_node_by_path("/");
+ if (!wafer_id || of_property_read_u32(product_id, "wafer-id", &wafer_prop)) {
+ pr_info("Spacemit Platform with no 'product-id' in DTS\n");
+ }
+
+ if ((wafer_prop << 16 | product_prop) == PRODUCT_ID_M1) {
+ for_each_possible_cpu(cpu) {
+ if (prop <= FILTER_POINTS_0)
+ spacemit_dt_cpufreq_pre_early_init(&pdev->dev, cpu, FREQ_TABLE_0);
+ else if (prop <= FILTER_POINTS_1)
+ spacemit_dt_cpufreq_pre_early_init(&pdev->dev, cpu, FREQ_TABLE_1);
+ else
+ spacemit_dt_cpufreq_pre_early_init(&pdev->dev, cpu, FREQ_TABLE_2);
+ }
+ } else {
+ for_each_possible_cpu(cpu) {
+ spacemit_dt_cpufreq_pre_early_init(&pdev->dev, cpu, FREQ_TABLE_0);
+ }
}
return 0;
diff --git a/drivers/crypto/spacemit/spacemit_ce_engine.c b/drivers/crypto/spacemit/spacemit_ce_engine.c
index 8623eb4843dd..8ebdd842532b 100644
--- a/drivers/crypto/spacemit/spacemit_ce_engine.c
+++ b/drivers/crypto/spacemit/spacemit_ce_engine.c
@@ -1733,6 +1733,12 @@ static int crypto_engine_probe(struct platform_device *pdev)
return -ENODEV;
}
+ ret = dma_set_mask_and_coherent(dev, DMA_BIT_MASK(32));
+ if (ret) {
+ dev_err(dev, "Unable to set dma mask\n");
+ return ret;
+ }
+
in_buffer = dma_alloc_noncoherent(dev, SPACEMIT_AES_BUFFER_LEN, &dma_addr_in, DMA_TO_DEVICE, GFP_KERNEL);
out_buffer = dma_alloc_noncoherent(dev, SPACEMIT_AES_BUFFER_LEN, &dma_addr_out, DMA_FROM_DEVICE, GFP_KERNEL);
ctrl = kmalloc(sizeof(struct aes_clk_reset_ctrl), GFP_KERNEL);
@@ -1829,13 +1835,6 @@ static int crypto_engine_probe(struct platform_device *pdev)
return ret;
}
-
- ret = dma_set_mask_and_coherent(dev, DMA_BIT_MASK(32));
- if (ret) {
- dev_err(dev, "Unable to set dma mask\n");
- return ret;
- }
-
#ifdef CONFIG_SPACEMIT_CRYPTO_SELF_TEST
ce_aes_test(num_engines);
#endif
diff --git a/drivers/i2c/busses/i2c-k1x.c b/drivers/i2c/busses/i2c-k1x.c
index eda79cfb2422..f0b6e9d36fe3 100644
--- a/drivers/i2c/busses/i2c-k1x.c
+++ b/drivers/i2c/busses/i2c-k1x.c
@@ -1245,15 +1245,12 @@ spacemit_i2c_xfer(struct i2c_adapter *adapt, struct i2c_msg msgs[], int num)
* software power down command to pmic via i2c interface
* with local irq disabled, so just enter PIO mode at once
*/
- if (unlikely(irqs_disabled()
+ if (unlikely(spacemit_i2c_restart_notify == true
#ifdef CONFIG_DEBUG_FS
|| spacemit_i2c->dbgfs_mode == SPACEMIT_I2C_MODE_PIO
#endif
)) {
- if(!spacemit_i2c_restart_notify)
- dev_warn(spacemit_i2c->dev, "%s: i2c transfer called with irq off!\n", __func__);
-
spacemit_i2c->msgs = msgs;
spacemit_i2c->num = num;
diff --git a/drivers/pwm/pwm-pxa.c b/drivers/pwm/pwm-pxa.c
index 4fd778f7a608..a571c207c1a9 100644
--- a/drivers/pwm/pwm-pxa.c
+++ b/drivers/pwm/pwm-pxa.c
@@ -308,10 +308,6 @@ static struct platform_driver pwm_driver = {
.id_table = pwm_id_table,
};
-static int k1x_pwm_driver_init(void)
-{
- return platform_driver_register(&pwm_driver);
-}
-late_initcall_sync(k1x_pwm_driver_init);
+module_platform_driver(pwm_driver);
MODULE_LICENSE("GPL v2");
diff --git a/drivers/soc/spacemit/pm_domain/k1x-pm_domain.c b/drivers/soc/spacemit/pm_domain/k1x-pm_domain.c
index de03e2e2e5d9..5cb23eb36019 100644
--- a/drivers/soc/spacemit/pm_domain/k1x-pm_domain.c
+++ b/drivers/soc/spacemit/pm_domain/k1x-pm_domain.c
@@ -45,6 +45,9 @@
/* gpio */
#define WAKEUP_SOURCE_WAKEUP_2 2
+/* usb & others */
+#define WAKEUP_SOURCE_WAKEUP_5 5
+
#define PM_QOS_BLOCK_C1 0x0 /* core wfi */
#define PM_QOS_BLOCK_C2 0x2 /* core power off */
#define PM_QOS_BLOCK_M2 0x6 /* core l2 off */
@@ -818,6 +821,11 @@ static int acpr_per_suspend(void)
apcr_per |= (1 << WAKEUP_SOURCE_WAKEUP_2);
regmap_write(gpmu->regmap[MPMU_REGMAP_INDEX], MPMU_AWUCRM_REG, apcr_per);
+ /* enable usb/rcpu/ap2audio */
+ regmap_read(gpmu->regmap[MPMU_REGMAP_INDEX], MPMU_AWUCRM_REG, &apcr_per);
+ apcr_per |= (1 << WAKEUP_SOURCE_WAKEUP_5);
+ regmap_write(gpmu->regmap[MPMU_REGMAP_INDEX], MPMU_AWUCRM_REG, apcr_per);
+
return 0;
}
diff --git a/drivers/usb/phy/Makefile b/drivers/usb/phy/Makefile
index 01b40aa3f8b7..b6d549df71f4 100644
--- a/drivers/usb/phy/Makefile
+++ b/drivers/usb/phy/Makefile
@@ -25,5 +25,5 @@ obj-$(CONFIG_USB_ULPI) += phy-ulpi.o
obj-$(CONFIG_USB_ULPI_VIEWPORT) += phy-ulpi-viewport.o
obj-$(CONFIG_KEYSTONE_USB_PHY) += phy-keystone.o
obj-$(CONFIG_JZ4770_PHY) += phy-jz4770.o
-obj-$(CONFIG_USB_K1XCI_OTG) += phy-k1x-ci-otg.o
obj-$(CONFIG_K1XCI_USB2_PHY) += phy-k1x-ci-usb2.o
+obj-$(CONFIG_USB_K1XCI_OTG) += phy-k1x-ci-otg.o
diff --git a/scripts/package/generic b/scripts/package/generic
new file mode 100644
index 000000000000..3b0286cd0e5a
--- /dev/null
+++ b/scripts/package/generic
@@ -0,0 +1,16 @@
+#!/bin/bash
+full_version=`uname -r`
+
+# First check for a fully qualified version.
+this="/usr/lib/linux-tools/$full_version/`basename $0`"
+if [ -f "$this" ]; then
+ exec "$this" "$@"
+fi
+
+# Give them a hint as to what to install.
+echo "WARNING: `basename $0` not found for kernel $full_version" >&2
+echo "" >&2
+echo " You may need to install the following packages for this specific kernel:" >&2
+echo " linux-tools-$full_version" >&2
+
+exit 2
\ No newline at end of file
diff --git a/sound/soc/spacemit/spacemit-snd-pcm-dma.c b/sound/soc/spacemit/spacemit-snd-pcm-dma.c
index 4dbd81098f7f..192927837cf6 100644
--- a/sound/soc/spacemit/spacemit-snd-pcm-dma.c
+++ b/sound/soc/spacemit/spacemit-snd-pcm-dma.c
@@ -34,32 +34,18 @@
#define HDMI_TXDATA 0x80
#define HDMI_PERIOD_SIZE 480
-#define L_CH 0
-#define R_CH 1
#define SAMPLE_PRESENT_FLAG_OFFSET 31
#define AUDIO_FRAME_START_BIT_OFFSET 30
-#define SAMPLE_FLAT_BIT_OFFSET 29
-#define NOT_USED_OFFSET 28
#define PARITY_BIT_OFFSET 27
#define CHANNEL_STATUS_OFFSET 26
-#define USER_DATA_OFFSET 25
#define VALID_OFFSET 24
-#define IEC958_AES0_CONSUMER (0<<0) /* 0 = consumer, 1 = professional */
-#define IEC958_AES0_AUDIO (0<<1) /* 0 = audio, 1 = non-audio */
-#define IEC958_AES3_CON_FS_48000 (2<<0) /* 48kHz */
-#define IEC958_AES0_CON_NOT_COPYRIGHT (1<<2) /* 0 = copyright, 1 = not copyright */
-#define IEC958_AES0_CON_EMPHASIS_NONE (0<<3) /* none emphasis */
-#define IEC958_AES1_CON_GENERAL (0x00)
-#define IEC958_AES2_CON_SOURCE_UNSPEC (0<<0) /* unspecified */
-#define IEC958_AES2_CON_CHANNEL_UNSPEC (0<<4) /* unspecified */
-#define IEC958_AES3_CON_CLOCK_1000PPM (0<<4) /* 1000 ppm */
-#define IEC958_AES4_CON_WORDLEN_24_20 (5<<1) /* 24-bit or 20-bit */
-#define IEC958_AES4_CON_MAX_WORDLEN_24 (1<<0) /* 0 = 20-bit, 1 = 24-bit */
-
#define CS_CTRL1 ((1 << SAMPLE_PRESENT_FLAG_OFFSET) | (1 << AUDIO_FRAME_START_BIT_OFFSET))
#define CS_CTRL2 ((1 << SAMPLE_PRESENT_FLAG_OFFSET) | (0 << AUDIO_FRAME_START_BIT_OFFSET))
+#define CS_SAMPLING_FREQUENCY 25
+#define CS_MAX_SAMPLE_WORD 32
+
#define P2(n) n, n^1, n^1, n
#define P4(n) P2(n), P2(n^1), P2(n^1), P2(n)
#define P6(n) P4(n), P4(n^1), P4(n^1), P4(n)
@@ -96,11 +82,9 @@ struct hdmi_codec_priv {
uint32_t srate;
uint32_t channels;
uint8_t iec_offset;
- uint8_t ch_sn;
- uint8_t cs[24];
};
-struct hdmi_codec_priv hdmi_ptr = {0};
+static struct hdmi_codec_priv hdmi_ptr = {0};
static const bool ParityTable256[256] =
{
P6(0), P6(1), P6(1), P6(0)
@@ -567,8 +551,12 @@ static int spacemit_snd_pcm_trigger(struct snd_soc_component *component, struct
case SNDRV_PCM_TRIGGER_SUSPEND:
if (runtime->info & SNDRV_PCM_INFO_PAUSE)
dmaengine_pause(dmadata->dma_chan);
- else
+ else {
dmaengine_terminate_async(dmadata->dma_chan);
+ dmadata->playback_data = 0;
+ dmadata->pos = 0;
+ spacemit_update_stream_status(dev, dmadata->stream, false);
+ }
break;
case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
case SNDRV_PCM_TRIGGER_RESUME:
@@ -623,18 +611,7 @@ spacemit_snd_pcm_hdmi_pointer(struct snd_soc_component *component, struct snd_pc
struct spacemit_snd_dmadata *dmadata = substream->runtime->private_data;
return bytes_to_frames(substream->runtime, dmadata->pos);
}
-static void hdmi_create_cs(struct hdmi_codec_priv *hdmi_priv)
-{
- uint8_t *cs;
- memset(hdmi_priv->cs, 0, sizeof(hdmi_priv->cs));
- cs = hdmi_priv->cs;
- cs[0] = IEC958_AES0_CONSUMER | IEC958_AES0_AUDIO | IEC958_AES0_CON_NOT_COPYRIGHT | IEC958_AES0_CON_EMPHASIS_NONE;
- cs[1] = IEC958_AES1_CON_GENERAL;
- cs[2] = IEC958_AES2_CON_SOURCE_UNSPEC | IEC958_AES2_CON_CHANNEL_UNSPEC;
- cs[3] = IEC958_AES3_CON_CLOCK_1000PPM | IEC958_AES3_CON_FS_48000;
- cs[4] = IEC958_AES4_CON_WORDLEN_24_20 | IEC958_AES4_CON_MAX_WORDLEN_24; //24bits
-}
static int spacemit_snd_pcm_open(struct snd_soc_component *component, struct snd_pcm_substream *substream)
{
int ret = 0;
@@ -677,10 +654,8 @@ static int spacemit_snd_pcm_open(struct snd_soc_component *component, struct snd
substream->runtime->private_data = dmadata;
if (dmadata->dma_id == DMA_HDMI) {
- hdmi_ptr.ch_sn = L_CH;
hdmi_ptr.iec_offset = 0;
hdmi_ptr.srate = 48000;
- hdmi_create_cs(&hdmi_ptr);
}
unlock:
spin_unlock_irqrestore(&dev->lock, flags);
@@ -704,7 +679,6 @@ static int spacemit_snd_pcm_close(struct snd_soc_component *component, struct sn
}
dmaengine_terminate_all(chan);
if (dmadata->dma_id == DMA_HDMI) {
- hdmi_ptr.ch_sn = L_CH;
hdmi_ptr.iec_offset = 0;
}
unlock:
@@ -830,72 +804,66 @@ static void spacemit_snd_pcm_remove(struct snd_soc_component *component)
dev->dmadata[i].dma_chan = NULL;
}
}
-static void hdmi_set_cs_channel_sn(struct hdmi_codec_priv *hdmi_priv)
-{
- hdmi_priv->cs[2] &= 0x0f;
- if (hdmi_priv->ch_sn == L_CH) {
- hdmi_priv->cs[2] |= (0x1 << 4);
- hdmi_priv->ch_sn = R_CH;
- } else if (hdmi_priv->ch_sn == R_CH) {
- hdmi_priv->cs[2] |= (0x2 << 4);
- hdmi_priv->ch_sn = L_CH;
- }
-}
-static uint32_t get_cs_bit(struct hdmi_codec_priv *hdmi_priv)
+static uint32_t parity_even(uint32_t sample)
{
- unsigned long tmp = 0;
- int cs_idx;
- int bit_idx;
- cs_idx = hdmi_priv->iec_offset >> 3;
- bit_idx = hdmi_priv->iec_offset - (cs_idx << 3);
-
- tmp = hdmi_priv->cs[cs_idx] >> bit_idx;
-
- return (uint32_t)tmp&0x1;
+ bool parity = 0;
+ sample ^= sample >> 16;
+ sample ^= sample >> 8;
+ parity = ParityTable256[sample & 0xff];
+ if (parity)
+ return 1;
+ else
+ return 0;
}
-static uint32_t parity_even(uint32_t sample)
+static int32_t cal_cs_status_48kHz(int32_t offset)
{
- bool parity = 0;
- sample ^= sample >> 16;
- sample ^= sample >> 8;
- parity = ParityTable256[sample & 0xff];
- if (parity)
- return 1;
- else
- return 0;
+ if ((offset == CS_SAMPLING_FREQUENCY) || (offset == CS_MAX_SAMPLE_WORD))
+ {
+ return 1;
+ } else {
+ return 0;
+ }
}
static void hdmi_reformat(void *dst, void *src, int len)
{
- uint32_t *dst32 = (uint32_t *)dst;
- uint16_t *src16 = (uint16_t *)src;
- struct hdmi_codec_priv *dw = &hdmi_ptr;
- uint16_t frm_cnt = len;
- uint32_t ctrl;
- uint32_t sample,parity;
- dw->channels = 2;
- while (frm_cnt--) {
- for (int i = 0; i < dw->channels; i++) {
- hdmi_set_cs_channel_sn(dw);
- if (dw->iec_offset == 0) {
- ctrl = CS_CTRL1 | (get_cs_bit(dw) << CHANNEL_STATUS_OFFSET);
- } else {
- ctrl = CS_CTRL2 | (get_cs_bit(dw) << CHANNEL_STATUS_OFFSET);
- }
-
- sample = ((uint32_t)(*src16++) << 8)| ctrl;
- parity = parity_even(sample);
- sample = sample | (parity << PARITY_BIT_OFFSET);
- *dst32++ = sample;
- }
-
- dw->iec_offset++;
- if (dw->iec_offset >= 192){
- dw->iec_offset = 0;
+ uint32_t *dst32 = (uint32_t *)dst;
+ uint16_t *src16 = (uint16_t *)src;
+ struct hdmi_codec_priv *dw = &hdmi_ptr;
+ uint16_t frm_cnt = len;
+ uint32_t ctrl;
+ uint32_t sample,parity;
+ dw->channels = 2;
+ while (frm_cnt--) {
+ for (int i = 0; i < dw->channels; i++) {
+ //bit 0-23
+ sample = ((uint32_t)(*src16++) << 8);
+ //bit 24
+ sample = sample | (1 << VALID_OFFSET);
+ //bit 26
+ sample = sample | (cal_cs_status_48kHz(dw->iec_offset) << CHANNEL_STATUS_OFFSET);
+ //bit 27
+ parity = parity_even(sample);
+ sample = sample | (parity << PARITY_BIT_OFFSET);
+
+ //bit 30 31
+ if (dw->iec_offset == 0) {
+ ctrl = CS_CTRL1;
+ } else {
+ ctrl = CS_CTRL2;
+ }
+ sample = sample | ctrl;
+
+ *dst32++ = sample;
}
- };
+
+ dw->iec_offset++;
+ if (dw->iec_offset >= 192){
+ dw->iec_offset = 0;
+ }
+ }
}
static int spacemit_snd_pcm_copy(struct snd_soc_component *component, struct snd_pcm_substream *substream, int channel,
--
2.39.2

View File

@@ -1,21 +0,0 @@
// SPDX-License-Identifier: (GPL-2.0 OR MIT)
/* Copyright (c) 2024 Spacemit, Inc */
/dts-v1/;
#include "k1-x_deb1.dts"
/ {
model = "BananaPi BPI-F3";
};
&uart2 {
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_uart2>;
status = "disabled";
bluetooth {
compatible = "realtek,rtl8852bs-bt";
device-wake-gpios = <&gpio 64 GPIO_ACTIVE_HIGH>;
};
};

View File

@@ -1,17 +0,0 @@
// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (C) 2023 SPACEMIT Micro Limited
*/
/ {
reserved-memory {
#address-cells = <2>;
#size-cells = <2>;
ranges;
spacemitzreserved: spacemit-mmz-@50000000 {
no-map;
reg = <0x0 0x50000000 0x0 0x28000000>;
};
};
};

View File

@@ -1,187 +0,0 @@
// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (C) 2023 SPACEMIT Micro Limited
*/
//#include "k1-x-camera-reserved-mm.dtsi"
#include "k1-x-camera-sensor.dtsi"
&soc {
plat-cam {
compatible = "spacemit,plat-cam", "simple-bus";
#address-cells = <2>;
#size-cells = <2>;
interconnects = <&dram_range3>;
interconnect-names = "dma-mem";
status = "okay";
};
csiphy0: csiphy@d420a000 {
compatible = "spacemit,csi-dphy";
cell-index = <0>;
reg = <0x0 0xd420a000 0x0 0x13f>;
reg-names = "csiphy-regs";
clocks = <&ccu CLK_CCIC1PHY>;
clock-names = "csi_dphy";
resets = <&reset RESET_CCIC1_PHY>;
reset-names = "cphy_reset";
interconnects = <&dram_range3>;
interconnect-names = "dma-mem";
status = "okay";
};
csiphy1: csiphy@d420a800 {
compatible = "spacemit,csi-dphy";
cell-index = <1>;
reg = <0x0 0xd420a800 0x0 0x13f>;
reg-names = "csiphy-regs";
clocks = <&ccu CLK_CCIC2PHY>;
clock-names = "csi_dphy";
resets = <&reset RESET_CCIC2_PHY>;
reset-names = "cphy_reset";
interconnects = <&dram_range3>;
interconnect-names = "dma-mem";
status = "okay";
};
csiphy2: csiphy@d4206000 {
compatible = "spacemit,csi-dphy";
cell-index = <2>;
spacemit,bifmode-enable;
reg = <0x0 0xd4206000 0x0 0x13f>;
reg-names = "csiphy-regs";
clocks = <&ccu CLK_CCIC3PHY>;
clock-names = "csi_dphy";
resets = <&reset RESET_CCIC3_PHY>;
reset-names = "cphy_reset";
interconnects = <&dram_range3>;
interconnect-names = "dma-mem";
status = "okay";
};
ccic0: ccic@d420a000 {
compatible = "spacemit,k1xccic";
cell-index = <0>;
spacemit,csiphy = <&csiphy0>;
reg = <0x0 0xd420a000 0x0 0x3ff>;
reg-names = "ccic-regs";
interrupt-parent = <&intc>;
interrupts = <81>;
interrupt-names = "ipe-irq";
clocks = <&ccu CLK_CSI>,
<&ccu CLK_CCIC_4X>,
<&ccu CLK_ISP_BUS>;
clock-names = "csi_func", "ccic_func", "isp_axi";
resets = <&reset RESET_ISP_AHB>, <&reset RESET_CSI>,
<&reset RESET_CCIC_4X>, <&reset RESET_ISP_CI>;
reset-names = "isp_ahb_reset", "csi_reset",
"ccic_4x_reset", "isp_ci_reset";
interconnects = <&dram_range3>;
interconnect-names = "dma-mem";
status = "okay";
};
ccic1: ccic@d420a800 {
compatible = "spacemit,k1xccic";
cell-index = <1>;
spacemit,csiphy = <&csiphy2>;
reg = <0x0 0xd420a800 0x0 0x3ff>;
reg-names = "ccic-regs";
interrupt-parent = <&intc>;
interrupts = <82>;
interrupt-names = "ipe-irq";
clocks = <&ccu CLK_CSI>, <&ccu CLK_CCIC_4X>,
<&ccu CLK_ISP_BUS>;
clock-names = "csi_func", "ccic_func",
"isp_axi";
resets = <&reset RESET_ISP_AHB>, <&reset RESET_CSI>,
<&reset RESET_CCIC_4X>, <&reset RESET_ISP_CI>;
reset-names = "isp_ahb_reset", "csi_reset",
"ccic_4x_reset", "isp_ci_reset";
interconnects = <&dram_range3>;
interconnect-names = "dma-mem";
status = "okay";
};
ccic2: ccic@d4206000 {
compatible = "spacemit,k1xccic";
cell-index = <2>;
spacemit,csiphy = <&csiphy2>;
reg = <0x0 0xd4206000 0x0 0x3ff>;
reg-names = "ccic-regs";
interrupt-parent = <&intc>;
interrupts = <83>;
interrupt-names = "ipe-irq";
clocks = <&ccu CLK_CSI>, <&ccu CLK_CCIC_4X>,
<&ccu CLK_ISP_BUS>;
clock-names = "csi_func", "ccic_func",
"isp_axi";
resets = <&reset RESET_ISP_AHB>, <&reset RESET_CSI>,
<&reset RESET_CCIC_4X>, <&reset RESET_ISP_CI>;
reset-names = "isp_ahb_reset", "csi_reset",
"ccic_4x_reset", "isp_ci_reset";
interconnects = <&dram_range3>;
interconnect-names = "dma-mem";
status = "okay";
};
isp: isp@C0230000 {
compatible = "spacemit,k1xisp";
reg = <0x0 0xC0230000 0x0 0x12700>;
reg-names = "isp";
interrupt-parent = <&intc>;
interrupts = <79>, <85>;
interrupt-names = "feisp-irq", "feisp-dma-irq";
clocks = <&ccu CLK_ISP>,
<&ccu CLK_ISP_BUS>,
<&ccu CLK_DPU_MCLK>;
clock-names = "isp_func", "isp_axi", "dpu_mclk";
resets = <&reset RESET_ISP_AHB>, <&reset RESET_ISP>,
<&reset RESET_ISP_CI>, <&reset RESET_LCD_MCLK>;
reset-names = "isp_ahb_reset", "isp_reset",
"isp_ci_reset", "lcd_mclk_reset";
interconnects = <&dram_range3>;
interconnect-names = "dma-mem";
status = "okay";
};
vi: vi@C0230000 {
compatible = "spacemit,k1xvi";
reg = <0x0 0xc0230000 0x0 0x14000>;
reg-names = "vi";
interrupt-parent = <&intc>;
interrupts = <79>, <85>;
interrupt-names = "feisp-irq", "feisp-dma-irq";
clocks = <&ccu CLK_ISP>, <&ccu CLK_ISP_BUS>,
<&ccu CLK_DPU_MCLK>;
clock-names = "isp_func", "isp_axi",
"dpu_mclk";
resets = <&reset RESET_ISP_AHB>, <&reset RESET_ISP>,
<&reset RESET_ISP_CI>, <&reset RESET_LCD_MCLK>;
reset-names = "isp_ahb_reset", "isp_reset",
"isp_ci_reset", "lcd_mclk_reset";
interconnects = <&dram_range3>;
interconnect-names = "dma-mem";
status = "okay";
};
cpp: cpp@C02f0000 {
compatible = "spacemit,k1xcpp";
reg = <0x0 0xC02f0000 0x0 0x7fff>;
reg-names = "cpp";
interrupt-parent = <&intc>;
interrupts = <84>;
interrupt-names = "cpp";
clocks = <&ccu CLK_ISP_CPP>, <&ccu CLK_ISP_BUS>,
<&ccu CLK_DPU_MCLK>;
clock-names = "cpp_func", "isp_axi",
"dpu_mclk";
resets = <&reset RESET_ISP_AHB>, <&reset RESET_ISP_CPP>,
<&reset RESET_ISP_CI>, <&reset RESET_LCD_MCLK>;
reset-names = "isp_ahb_reset", "isp_cpp_reset",
"isp_ci_reset", "lcd_mclk_reset";
interconnects = <&dram_range3>;
interconnect-names = "dma-mem";
status = "okay";
};
}; /* soc */

View File

@@ -1,73 +0,0 @@
// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (C) 2023 SPACEMIT Micro Limited
*/
#include <dt-bindings/gpio/gpio.h>
#include "k1-x_pinctrl.dtsi"
&soc {
/* imx315 */
backsensor: cam_sensor@0 {
cell-index = <0>;
twsi-index = <0>;
dphy-index = <0>;
compatible = "spacemit,cam-sensor";
clocks = <&ccu CLK_CAMM0>;
clock-names = "cam_mclk0";
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_camera0>;
//pwdn-gpios = <&gpio 113 GPIO_ACTIVE_HIGH>;
//reset-gpios = <&gpio 111 GPIO_ACTIVE_HIGH>;
//dphy-entries = <5>;
//dphy-settings = <0x00000001 0xa2848888 0x00001500 0x000000ff 0x1001>;
/*
afvdd28-supply = <&ldo_12>;
avdd28-supply = <&ldo_10>;
dvdd12-supply = <&ldo_20>;
iovdd18-supply = <&ldo_11>;
cam-supply-names = "afvdd28", "avdd28", "dvdd12", "iovdd18";
*/
interconnects = <&dram_range1>;
interconnect-names = "dma-mem";
status = "okay";
};
/* gc2375h */
backsensor_aux: cam_sensor@1 {
cell-index = <1>;
twsi-index = <1>;
dphy-index = <2>;
compatible = "spacemit,cam-sensor";
clocks = <&ccu CLK_CAMM1>;
clock-names = "cam_mclk1";
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_camera1>;
//dphy-entries = <5>;
//dphy-settings = <0x00000001 0xa2848888 0x00001500 0x000000ff 0x1001>;
//pwdn-gpios = <&gpio 114 GPIO_ACTIVE_HIGH>;
//reset-gpios = <&gpio 112 GPIO_ACTIVE_HIGH>;
interconnects = <&dram_range1>;
interconnect-names = "dma-mem";
status = "okay";
};
/* S5K5E3 */
frontsensor: cam_sensor@2 {
cell-index = <2>;
twsi-index = <1>;
dphy-index = <2>;
compatible = "spacemit,cam-sensor";
clocks = <&ccu CLK_CAMM2>;
clock-names = "cam_mclk2";
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_camera2>;
//dphy-entries = <5>;
//dphy-settings = <0x00000001 0xa2848888 0x00001500 0x000000ff 0x1001>;
//pwdn-gpios = <&gpio 122 GPIO_ACTIVE_HIGH>;
//reset-gpios = <&gpio 121 GPIO_ACTIVE_HIGH>;
interconnects = <&dram_range1>;
interconnect-names = "dma-mem";
status = "okay";
};
};

View File

@@ -1,52 +0,0 @@
// SPDX-License-Identifier: (GPL-2.0 OR MIT)
/* Copyright (c) 2024 Spacemit, Inc */
&efuse {
status = "okay";
efuse_bank7: efuse_bank@7 {
compatible = "spacemit,k1-efuse";
#address-cells = <1>;
#size-cells = <1>;
reg = <0x190 0x20>;
resets = <&reset RESET_AES>;
reset-names = "aes_reset";
clocks = <&ccu CLK_AES>;
clock-names = "aes_core";
status = "okay";
soc_die_id: bank7@11,3 {
reg = <0x11 3>;
bits = <3 16>;
};
soc_ver_id: bank7@1f,6 {
reg = <0x1F 1>;
bits = <6 2>;
};
soc_pack_id: bank7@16,6 {
reg = <0x16 2>;
bits = <6 9>;
};
soc_svt_dro: bank7@15,5 {
reg = <0x15 2>;
bits = <5 9>;
};
soc_chip_id: bank7@17,7 {
reg = <0x17 8>;
bits = <7 55>;
};
};
};
&socinfo {
nvmem-cells = <&soc_die_id>, <&soc_ver_id>, <&soc_pack_id>,
<&soc_svt_dro>, <&soc_chip_id>;
nvmem-cell-names = "soc_die_id", "soc_ver_id", "soc_pack_id",
"soc_svt_dro", "soc_chip_id";
status = "okay";
};

View File

@@ -1,62 +0,0 @@
// SPDX-License-Identifier: (GPL-2.0 OR MIT)
/* Copyright (c) 2023 Spacemit, Inc */
&soc {
display-subsystem-hdmi {
compatible = "spacemit,saturn-hdmi";
reg = <0 0xc0440000 0 0x2A000>;
ports = <&dpu_online2_hdmi>;
interconnects = <&dram_range1>;
interconnect-names = "dma-mem";
};
dpu_online2_hdmi: port@c0440000 {
compatible = "spacemit,dpu-online2";
interrupt-parent = <&intc>;
interrupts = <139>, <138>;
interrupt-names = "ONLINE_IRQ", "OFFLINE_IRQ";
interconnects = <&dram_range1>;
interconnect-names = "dma-mem";
clocks = <&ccu CLK_HDMI>;
clock-names = "hmclk";
resets = <&reset RESET_HDMI>;
reset-names= "hdmi_reset";
power-domains = <&power K1X_PMU_HDMI_PWR_DOMAIN>;
pipeline-id = <ONLINE2>;
ip = "spacemit-saturn";
type = <HDMI>;
clk,pm-runtime,no-sleep;
status = "disabled";
dpu_online2_hdmi_out: endpoint@0 {
remote-endpoint = <&hdmi_in>;
};
dpu_offline0_hdmi_out: endpoint@1 {
/* remote-endpoint = <&wb0_in>; */
};
};
hdmi: hdmi@C0400500 {
compatible = "spacemit,hdmi";
reg = <0 0xC0400500 0 0x200>;
interrupt-parent = <&intc>;
interrupts = <136>;
clocks = <&ccu CLK_HDMI>;
clock-names = "hmclk";
resets = <&reset RESET_HDMI>;
reset-names= "hdmi_reset";
power-domains = <&power K1X_PMU_HDMI_PWR_DOMAIN>;
clk,pm-runtime,no-sleep;
status = "disabled";
port {
#address-cells = <1>;
#size-cells = <0>;
hdmi_in: endpoint@0 {
reg = <0>;
remote-endpoint = <&dpu_online2_hdmi_out>;
};
};
};
};

View File

@@ -1,116 +0,0 @@
// SPDX-License-Identifier: (GPL-2.0 OR MIT)
/* Copyright (c) 2023 Spacemit, Inc */
&soc {
display-subsystem-dsi {
compatible = "spacemit,saturn-le";
reg = <0 0xC0340000 0 0x2A000>;
ports = <&dpu_online2_dsi>;
interconnects = <&dram_range1>;
interconnect-names = "dma-mem";
};
dpu_online2_dsi: port@c0340000 {
compatible = "spacemit,dpu-online2";
interrupt-parent = <&intc>;
interrupts = <90>, <89>;
interrupt-names = "ONLINE_IRQ", "OFFLINE_IRQ";
interconnects = <&dram_range1>;
interconnect-names = "dma-mem";
clocks = <&ccu CLK_DPU_PXCLK>,
<&ccu CLK_DPU_MCLK>,
<&ccu CLK_DPU_HCLK>,
<&ccu CLK_DPU_ESC>,
<&ccu CLK_DPU_BIT>;
clock-names = "pxclk", "mclk", "hclk", "escclk", "bitclk";
resets = <&reset RESET_MIPI>,
<&reset RESET_LCD_MCLK>,
<&reset RESET_LCD>,
<&reset RESET_DSI_ESC>;
reset-names= "dsi_reset", "mclk_reset", "lcd_reset","esc_reset";
power-domains = <&power K1X_PMU_LCD_PWR_DOMAIN>;
pipeline-id = <ONLINE2>;
ip = "spacemit-saturn";
spacemit-dpu-min-mclk = <40960000>;
type = <DSI>;
clk,pm-runtime,no-sleep;
status = "disabled";
dpu_online2_dsi_out: endpoint@0 {
remote-endpoint = <&dsi2_in>;
};
dpu_offline0_dsi_out: endpoint@1 {
remote-endpoint = <&wb0_in>;
};
};
dsi2: dsi2@d421a800 {
compatible = "spacemit,dsi2-host";
#address-cells = <1>;
#size-cells = <0>;
reg = <0 0xD421A800 0 0x200>;
interrupt-parent = <&intc>;
interrupts = <95>;
ip = "synopsys-dhost";
dev-id = <2>;
status = "disabled";
ports {
#address-cells = <1>;
#size-cells = <0>;
port@0 {
reg = <0>;
#address-cells = <1>;
#size-cells = <0>;
dsi2_out: endpoint@0 {
reg = <0>;
remote-endpoint = <&dphy2_in>;
};
};
port@1 {
reg = <1>;
dsi2_in: endpoint {
remote-endpoint = <&dpu_online2_dsi_out>;
};
};
};
};
dphy2: dphy2@d421a800 {
compatible = "spacemit,dsi2-phy";
#address-cells = <1>;
#size-cells = <0>;
reg = <0 0xD421A800 0 0x200>;
ip = "spacemit-dphy";
dev-id = <2>;
status = "okay";
port@1 {
reg = <1>;
dphy2_in: endpoint {
remote-endpoint = <&dsi2_out>;
};
};
};
wb0 {
compatible = "spacemit,wb0";
dev-id = <2>;
status = "okay";
ports {
#address-cells = <1>;
#size-cells = <0>;
port@0 {
reg = <0>;
wb0_in: endpoint {
remote-endpoint = <&dpu_offline0_dsi_out>;
};
};
};
};
};

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -1,110 +0,0 @@
// SPDX-License-Identifier: (GPL-2.0 OR MIT)
/* Copyright (c) 2024 Spacemit, Inc */
&cpus {
clst_core_opp_table0: opp_table0 {
compatible = "operating-points-v2";
opp-shared;
clocks = <&ccu CLK_CPU_C0_ACE>, <&ccu CLK_CPU_C1_ACE>, <&ccu CLK_CPU_C0_TCM>,
<&ccu CLK_CCI550>, <&ccu CLK_PLL3>;
clock-names = "ace0","ace1","tcm","cci","pll3";
cci-hz = /bits/ 64 <614000000>;
opp1600000000 {
opp-hz = /bits/ 64 <1600000000>, /bits/ 64 <1600000000>;
tcm-hz = /bits/ 64 <800000000>;
ace-hz = /bits/ 64 <800000000>;
opp-microvolt = <1050000>;
clock-latency-ns = <200000>;
};
opp1228800000 {
opp-hz = /bits/ 64 <1228800000>, /bits/ 64 <1228800000>;
tcm-hz = /bits/ 64 <614400000>;
ace-hz = /bits/ 64 <614400000>;
opp-microvolt = <950000>;
clock-latency-ns = <200000>;
};
opp1000000000 {
opp-hz = /bits/ 64 <1000000000>, /bits/ 64 <1000000000>;
tcm-hz = /bits/ 64 <500000000>;
ace-hz = /bits/ 64 <500000000>;
opp-microvolt = <950000>;
clock-latency-ns = <200000>;
};
opp819000000 {
opp-hz = /bits/ 64 <819000000>, /bits/ 64 <819000000>;
opp-microvolt = <950000>;
tcm-hz = /bits/ 64 <409500000>;
ace-hz = /bits/ 64 <409500000>;
clock-latency-ns = <200000>;
};
opp614400000 {
opp-hz = /bits/ 64 <614400000>, /bits/ 64 <614400000>;
tcm-hz = /bits/ 64 <307200000>;
ace-hz = /bits/ 64 <307200000>;
opp-microvolt = <950000>;
clock-latency-ns = <200000>;
};
};
};
&cpu_0 {
clst-supply = <&dcdc_1>;
clocks = <&ccu CLK_CPU_C0_CORE>, <&ccu CLK_CPU_C1_CORE>;
clock-names = "cls0", "cls1";
operating-points-v2 = <&clst_core_opp_table0>;
};
&cpu_1 {
clst-supply = <&dcdc_1>;
clocks = <&ccu CLK_CPU_C0_CORE>, <&ccu CLK_CPU_C1_CORE>;
clock-names = "cls0", "cls1";
operating-points-v2 = <&clst_core_opp_table0>;
};
&cpu_2 {
clst-supply = <&dcdc_1>;
clocks = <&ccu CLK_CPU_C0_CORE>, <&ccu CLK_CPU_C1_CORE>;
clock-names = "cls0", "cls1";
operating-points-v2 = <&clst_core_opp_table0>;
};
&cpu_3 {
clst-supply = <&dcdc_1>;
clocks = <&ccu CLK_CPU_C0_CORE>, <&ccu CLK_CPU_C1_CORE>;
clock-names = "cls0", "cls1";
operating-points-v2 = <&clst_core_opp_table0>;
};
&cpu_4 {
clst-supply = <&dcdc_1>;
clocks = <&ccu CLK_CPU_C0_CORE>, <&ccu CLK_CPU_C1_CORE>;
clock-names = "cls0", "cls1";
operating-points-v2 = <&clst_core_opp_table0>;
};
&cpu_5 {
clst-supply = <&dcdc_1>;
clocks = <&ccu CLK_CPU_C0_CORE>, <&ccu CLK_CPU_C1_CORE>;
clock-names = "cls0", "cls1";
operating-points-v2 = <&clst_core_opp_table0>;
};
&cpu_6 {
clst-supply = <&dcdc_1>;
clocks = <&ccu CLK_CPU_C0_CORE>, <&ccu CLK_CPU_C1_CORE>;
clock-names = "cls0", "cls1";
operating-points-v2 = <&clst_core_opp_table0>;
};
&cpu_7 {
clst-supply = <&dcdc_1>;
clocks = <&ccu CLK_CPU_C0_CORE>, <&ccu CLK_CPU_C1_CORE>;
clock-names = "cls0", "cls1";
operating-points-v2 = <&clst_core_opp_table0>;
};

File diff suppressed because it is too large Load Diff

View File

@@ -1,157 +0,0 @@
// SPDX-License-Identifier: GPL-2.0
/ { lcds: lcds {
lcd_gx09inx101_mipi: lcd_gx09inx101_mipi {
dsi-work-mode = <1>; /* video burst mode*/
dsi-lane-number = <4>;
dsi-color-format = "rgb888";
width-mm = <142>;
height-mm = <228>;
use-dcs-write;
/*mipi info*/
height = <1920>;
width = <1200>;
hfp = <80>;
hbp = <40>;
hsync = <10>;
vfp = <20>;
vbp = <16>;
vsync = <4>;
fps = <60>;
work-mode = <0>;
rgb-mode = <3>;
lane-number = <4>;
phy-bit-clock = <1000000000>;
phy-esc-clock = <76800000>;
split-enable = <0>;
eotp-enable = <0>;
burst-mode = <2>;
esd-check-enable = <0>;
/* DSI_CMD, DSI_MODE, timeout, len, cmd */
initial-command = [
39 01 00 02 B0 01
39 01 00 02 C3 4F
39 01 00 02 C4 40
39 01 00 02 C5 40
39 01 00 02 C6 40
39 01 00 02 C7 40
39 01 00 02 C8 4D
39 01 00 02 C9 52
39 01 00 02 CA 51
39 01 00 02 CD 5D
39 01 00 02 CE 5B
39 01 00 02 CF 4B
39 01 00 02 D0 49
39 01 00 02 D1 47
39 01 00 02 D2 45
39 01 00 02 D3 41
39 01 00 02 D7 50
39 01 00 02 D8 40
39 01 00 02 D9 40
39 01 00 02 DA 40
39 01 00 02 DB 40
39 01 00 02 DC 4E
39 01 00 02 DD 52
39 01 00 02 DE 51
39 01 00 02 E1 5E
39 01 00 02 E2 5C
39 01 00 02 E3 4C
39 01 00 02 E4 4A
39 01 00 02 E5 48
39 01 00 02 E6 46
39 01 00 02 E7 42
39 01 00 02 B0 03
39 01 00 02 BE 03
39 01 00 02 CC 44
39 01 00 02 C8 07
39 01 00 02 C9 05
39 01 00 02 CA 42
39 01 00 02 CD 3E
39 01 00 02 CF 60
39 01 00 02 D2 04
39 01 00 02 D3 04
39 01 00 02 D4 01
39 01 00 02 D5 00
39 01 00 02 D6 03
39 01 00 02 D7 04
39 01 00 02 D9 01
39 01 00 02 DB 01
39 01 00 02 E4 F0
39 01 00 02 E5 0A
39 01 00 02 B0 00
39 01 00 02 BD 50
39 01 00 02 C2 08
39 01 00 02 C4 10
39 01 00 02 CC 00
// 39 01 00 02 B2 41 // BIST pattern
39 01 00 02 B0 02
39 01 00 02 C0 00
39 01 00 02 C1 0A
39 01 00 02 C2 20
39 01 00 02 C3 24
39 01 00 02 C4 23
39 01 00 02 C5 29
39 01 00 02 C6 23
39 01 00 02 C7 1C
39 01 00 02 C8 19
39 01 00 02 C9 17
39 01 00 02 CA 17
39 01 00 02 CB 18
39 01 00 02 CC 1A
39 01 00 02 CD 1E
39 01 00 02 CE 20
39 01 00 02 CF 23
39 01 00 02 D0 07
39 01 00 02 D1 00
39 01 00 02 D2 00
39 01 00 02 D3 0A
39 01 00 02 D4 13
39 01 00 02 D5 1C
39 01 00 02 D6 1A
39 01 00 02 D7 13
39 01 00 02 D8 17
39 01 00 02 D9 1C
39 01 00 02 DA 19
39 01 00 02 DB 17
39 01 00 02 DC 17
39 01 00 02 DD 18
39 01 00 02 DE 1A
39 01 00 02 DF 1E
39 01 00 02 E0 20
39 01 00 02 E1 23
39 01 00 02 E2 07
39 01 F0 01 11
39 01 28 01 29
];
sleep-in-command = [
39 01 78 01 28
39 01 78 01 10
];
sleep-out-command = [
39 01 96 01 11
39 01 32 01 29
];
read-id-command = [
37 01 00 01 05
14 01 00 05 fb fc fd fe ff
];
display-timings {
timing0 {
clock-frequency = <143000000>;
hactive = <1200>;
hfront-porch = <80>;
hback-porch = <40>;
hsync-len = <10>;
vactive = <1920>;
vfront-porch = <20>;
vback-porch = <16>;
vsync-len = <4>;
vsync-active = <1>;
hsync-active = <1>;
};
};
};
};};

View File

@@ -1,234 +0,0 @@
// SPDX-License-Identifier: (GPL-2.0 OR MIT)
/* Copyright (c) 2023 Spacemit, Inc */
&cpus {
clst_core_opp_table0: opp_table0 {
compatible = "operating-points-v2";
opp-shared;
clocks = <&ccu CLK_CPU_C0_ACE>, <&ccu CLK_CPU_C1_ACE>, <&ccu CLK_CPU_C0_TCM>,
<&ccu CLK_CCI550>, <&ccu CLK_PLL3>;
clock-names = "ace0","ace1","tcm","cci","pll3";
cci-hz = /bits/ 64 <614000000>;
opp1800000000 {
opp-hz = /bits/ 64 <1800000000>, /bits/ 64 <1800000000>;
tcm-hz = /bits/ 64 <900000000>;
ace-hz = /bits/ 64 <900000000>;
opp-microvolt = <1160000>;
clock-latency-ns = <200000>;
};
opp1600000000 {
opp-hz = /bits/ 64 <1600000000>, /bits/ 64 <1600000000>;
tcm-hz = /bits/ 64 <800000000>;
ace-hz = /bits/ 64 <800000000>;
opp-microvolt = <1050000>;
clock-latency-ns = <200000>;
};
opp1228800000 {
opp-hz = /bits/ 64 <1228800000>, /bits/ 64 <1228800000>;
tcm-hz = /bits/ 64 <614400000>;
ace-hz = /bits/ 64 <614400000>;
opp-microvolt = <950000>;
clock-latency-ns = <200000>;
};
opp1000000000 {
opp-hz = /bits/ 64 <1000000000>, /bits/ 64 <1000000000>;
tcm-hz = /bits/ 64 <500000000>;
ace-hz = /bits/ 64 <500000000>;
opp-microvolt = <950000>;
clock-latency-ns = <200000>;
};
opp819000000 {
opp-hz = /bits/ 64 <819000000>, /bits/ 64 <819000000>;
opp-microvolt = <950000>;
tcm-hz = /bits/ 64 <409500000>;
ace-hz = /bits/ 64 <409500000>;
clock-latency-ns = <200000>;
};
opp614400000 {
opp-hz = /bits/ 64 <614400000>, /bits/ 64 <614400000>;
tcm-hz = /bits/ 64 <307200000>;
ace-hz = /bits/ 64 <307200000>;
opp-microvolt = <950000>;
clock-latency-ns = <200000>;
};
};
clst_core_opp_table1: opp_table1 {
compatible = "operating-points-v2";
opp-shared;
clocks = <&ccu CLK_CPU_C0_ACE>, <&ccu CLK_CPU_C1_ACE>, <&ccu CLK_CPU_C0_TCM>,
<&ccu CLK_CCI550>, <&ccu CLK_PLL3>;
clock-names = "ace0","ace1","tcm","cci","pll3";
cci-hz = /bits/ 64 <614000000>;
opp1800000000 {
opp-hz = /bits/ 64 <1800000000>, /bits/ 64 <1800000000>;
tcm-hz = /bits/ 64 <900000000>;
ace-hz = /bits/ 64 <900000000>;
opp-microvolt = <1100000>;
clock-latency-ns = <200000>;
};
opp1600000000 {
opp-hz = /bits/ 64 <1600000000>, /bits/ 64 <1600000000>;
tcm-hz = /bits/ 64 <800000000>;
ace-hz = /bits/ 64 <800000000>;
opp-microvolt = <1050000>;
clock-latency-ns = <200000>;
};
opp1228800000 {
opp-hz = /bits/ 64 <1228800000>, /bits/ 64 <1228800000>;
tcm-hz = /bits/ 64 <614400000>;
ace-hz = /bits/ 64 <614400000>;
opp-microvolt = <950000>;
clock-latency-ns = <200000>;
};
opp1000000000 {
opp-hz = /bits/ 64 <1000000000>, /bits/ 64 <1000000000>;
tcm-hz = /bits/ 64 <500000000>;
ace-hz = /bits/ 64 <500000000>;
opp-microvolt = <950000>;
clock-latency-ns = <200000>;
};
opp819000000 {
opp-hz = /bits/ 64 <819000000>, /bits/ 64 <819000000>;
opp-microvolt = <950000>;
tcm-hz = /bits/ 64 <409500000>;
ace-hz = /bits/ 64 <409500000>;
clock-latency-ns = <200000>;
};
opp614400000 {
opp-hz = /bits/ 64 <614400000>, /bits/ 64 <614400000>;
tcm-hz = /bits/ 64 <307200000>;
ace-hz = /bits/ 64 <307200000>;
opp-microvolt = <950000>;
clock-latency-ns = <200000>;
};
};
clst_core_opp_table2: opp_table2 {
compatible = "operating-points-v2";
opp-shared;
clocks = <&ccu CLK_CPU_C0_ACE>, <&ccu CLK_CPU_C1_ACE>, <&ccu CLK_CPU_C0_TCM>,
<&ccu CLK_CCI550>, <&ccu CLK_PLL3>;
clock-names = "ace0","ace1","tcm","cci","pll3";
cci-hz = /bits/ 64 <614000000>;
opp1800000000 {
opp-hz = /bits/ 64 <1800000000>, /bits/ 64 <1800000000>;
tcm-hz = /bits/ 64 <900000000>;
ace-hz = /bits/ 64 <900000000>;
opp-microvolt = <1050000>;
clock-latency-ns = <200000>;
};
opp1600000000 {
opp-hz = /bits/ 64 <1600000000>, /bits/ 64 <1600000000>;
tcm-hz = /bits/ 64 <800000000>;
ace-hz = /bits/ 64 <800000000>;
opp-microvolt = <1050000>;
clock-latency-ns = <200000>;
};
opp1228800000 {
opp-hz = /bits/ 64 <1228800000>, /bits/ 64 <1228800000>;
tcm-hz = /bits/ 64 <614400000>;
ace-hz = /bits/ 64 <614400000>;
opp-microvolt = <950000>;
clock-latency-ns = <200000>;
};
opp1000000000 {
opp-hz = /bits/ 64 <1000000000>, /bits/ 64 <1000000000>;
tcm-hz = /bits/ 64 <500000000>;
ace-hz = /bits/ 64 <500000000>;
opp-microvolt = <950000>;
clock-latency-ns = <200000>;
};
opp819000000 {
opp-hz = /bits/ 64 <819000000>, /bits/ 64 <819000000>;
opp-microvolt = <950000>;
tcm-hz = /bits/ 64 <409500000>;
ace-hz = /bits/ 64 <409500000>;
clock-latency-ns = <200000>;
};
opp614400000 {
opp-hz = /bits/ 64 <614400000>, /bits/ 64 <614400000>;
tcm-hz = /bits/ 64 <307200000>;
ace-hz = /bits/ 64 <307200000>;
opp-microvolt = <950000>;
clock-latency-ns = <200000>;
};
};
};
&cpu_0 {
clst-supply = <&dcdc_1>;
clocks = <&ccu CLK_CPU_C0_CORE>, <&ccu CLK_CPU_C1_CORE>;
clock-names = "cls0", "cls1";
operating-points-v2 = <&clst_core_opp_table0>, <&clst_core_opp_table1>, <&clst_core_opp_table2>;
};
&cpu_1 {
clst-supply = <&dcdc_1>;
clocks = <&ccu CLK_CPU_C0_CORE>, <&ccu CLK_CPU_C1_CORE>;
clock-names = "cls0", "cls1";
operating-points-v2 = <&clst_core_opp_table0>, <&clst_core_opp_table1>, <&clst_core_opp_table2>;
};
&cpu_2 {
clst-supply = <&dcdc_1>;
clocks = <&ccu CLK_CPU_C0_CORE>, <&ccu CLK_CPU_C1_CORE>;
clock-names = "cls0", "cls1";
operating-points-v2 = <&clst_core_opp_table0>, <&clst_core_opp_table1>, <&clst_core_opp_table2>;
};
&cpu_3 {
clst-supply = <&dcdc_1>;
clocks = <&ccu CLK_CPU_C0_CORE>, <&ccu CLK_CPU_C1_CORE>;
clock-names = "cls0", "cls1";
operating-points-v2 = <&clst_core_opp_table0>, <&clst_core_opp_table1>, <&clst_core_opp_table2>;
};
&cpu_4 {
clst-supply = <&dcdc_1>;
clocks = <&ccu CLK_CPU_C0_CORE>, <&ccu CLK_CPU_C1_CORE>;
clock-names = "cls0", "cls1";
operating-points-v2 = <&clst_core_opp_table0>, <&clst_core_opp_table1>, <&clst_core_opp_table2>;
};
&cpu_5 {
clst-supply = <&dcdc_1>;
clocks = <&ccu CLK_CPU_C0_CORE>, <&ccu CLK_CPU_C1_CORE>;
clock-names = "cls0", "cls1";
operating-points-v2 = <&clst_core_opp_table0>, <&clst_core_opp_table1>, <&clst_core_opp_table2>;
};
&cpu_6 {
clst-supply = <&dcdc_1>;
clocks = <&ccu CLK_CPU_C0_CORE>, <&ccu CLK_CPU_C1_CORE>;
clock-names = "cls0", "cls1";
operating-points-v2 = <&clst_core_opp_table0>, <&clst_core_opp_table1>, <&clst_core_opp_table2>;
};
&cpu_7 {
clst-supply = <&dcdc_1>;
clocks = <&ccu CLK_CPU_C0_CORE>, <&ccu CLK_CPU_C1_CORE>;
clock-names = "cls0", "cls1";
operating-points-v2 = <&clst_core_opp_table0>, <&clst_core_opp_table1>, <&clst_core_opp_table2>;
};

View File

@@ -1,76 +0,0 @@
/ {
sram {
compatible = "mmio-sram";
/* 256k */
reg = <0x0 0x2f902000 0x0 0x3e000>;
#address-cells = <1>;
#size-cells = <1>;
ranges = <0x0 0x0 0x2f902000 0x3e000>;
/* channel 0*/
cpu_scp_lpri0: scp-sram@2f900000 {
compatible = "arm,scmi-shmem";
reg = <0x0 0x80>;
};
/* channel 1*/
cpu_scp_lpri1: scp-sram@2f900080 {
compatible = "arm,scmi-shmem";
reg = <0x80 0x80>;
};
/* channel 2*/
cpu_scp_lpri2: scp-sram@2f900100 {
compatible = "arm,scmi-shmem";
reg = <0x100 0x80>;
};
/* channel 3*/
cpu_scp_lpri3: scp-sram@2f900180 {
compatible = "arm,scmi-shmem";
reg = <0x180 0x80>;
};
};
firmware {
scmi {
compatible = "arm,scmi";
mbox-names = "tx", "rx";
mboxes = <&mailbox 0 &mailbox 2>;
shmem = <&cpu_scp_lpri0 &cpu_scp_lpri0>;
#address-cells = <1>;
#size-cells = <0>;
scmi_vold: protocol@23 {
reg = <0x17>;
regulators {
#address-cells = <1>;
#size-cells = <0>;
regulator_devlittle: regulator@0 {
reg = <0x0>;
regulator-min-microvolt = <820000>;
regulator-max-microvolt = <1000000>;
};
regulator_devgpu: regulator@1 {
reg = <0x1>;
regulator-min-microvolt = <820000>;
regulator-max-microvolt = <900000>;
};
};
};
scmi_devpd: protocol@11 {
reg = <0x11>;
#power-domain-cells = <1>;
};
scmi_dvfs: protocol@13 {
reg = <0x13>;
#clock-cells = <1>;
};
};
};
};

View File

@@ -0,0 +1,56 @@
From 7648741002eeb851ceb394864253445b77ea3d25 Mon Sep 17 00:00:00 2001
From: Catalin Marinas <catalin.marinas@arm.com>
Date: Wed, 10 Apr 2024 08:25:37 -0400
Subject: [PATCH] arm64: swiotlb: Reduce the default size if no ZONE_DMA
bouncing needed
With CONFIG_DMA_BOUNCE_UNALIGNED_KMALLOC enabled, the arm64 kernel still
allocates the default SWIOTLB buffer (64MB) even if ZONE_DMA is disabled
or all the RAM fits into this zone. However, this potentially wastes a
non-negligible amount of memory on platforms with little RAM.
Reduce the SWIOTLB size to 1MB per 1GB of RAM if only needed for
kmalloc() buffer bouncing.
Signed-off-by: Catalin Marinas <catalin.marinas@arm.com>
Suggested-by: Ross Burton <ross.burton@arm.com>
Cc: Ross Burton <ross.burton@arm.com>
Cc: Will Deacon <will@kernel.org>
Reviewed-by: Robin Murphy <robin.murphy@arm.com>
---
arch/arm64/mm/init.c | 11 ++++++++++-
1 file changed, 10 insertions(+), 1 deletion(-)
diff --git a/arch/arm64/mm/init.c b/arch/arm64/mm/init.c
index 8a0f8604348b..8deec68028ac 100644
--- a/arch/arm64/mm/init.c
+++ b/arch/arm64/mm/init.c
@@ -16,6 +16,7 @@
#include <linux/nodemask.h>
#include <linux/initrd.h>
#include <linux/gfp.h>
+#include <linux/math.h>
#include <linux/memblock.h>
#include <linux/sort.h>
#include <linux/of.h>
@@ -493,8 +494,16 @@ void __init mem_init(void)
{
bool swiotlb = max_pfn > PFN_DOWN(arm64_dma_phys_limit);
- if (IS_ENABLED(CONFIG_DMA_BOUNCE_UNALIGNED_KMALLOC))
+ if (IS_ENABLED(CONFIG_DMA_BOUNCE_UNALIGNED_KMALLOC) && !swiotlb) {
+ /*
+ * If no bouncing needed for ZONE_DMA, reduce the swiotlb
+ * buffer for kmalloc() bouncing to 1MB per 1GB of RAM.
+ */
+ unsigned long size =
+ DIV_ROUND_UP(memblock_phys_mem_size(), 1024);
+ swiotlb_adjust_size(min(swiotlb_size_or_default(), size));
swiotlb = true;
+ }
swiotlb_init(swiotlb, SWIOTLB_VERBOSE);
--
2.39.2

View File

@@ -0,0 +1,51 @@
From b531d7b85ef42801a078d19965048385cfb379cd Mon Sep 17 00:00:00 2001
From: Patrick Yavitz <pyavitz@armbian.com>
Date: Thu, 15 Aug 2024 04:38:42 -0400
Subject: [PATCH] Add board BananaPi F3
Signed-off-by: Patrick Yavitz <pyavitz@armbian.com>
---
arch/riscv/boot/dts/spacemit/Makefile | 1 +
.../boot/dts/spacemit/k1-bananapi-f3.dts | 21 +++++++++++++++++++
2 files changed, 22 insertions(+)
create mode 100644 arch/riscv/boot/dts/spacemit/k1-bananapi-f3.dts
diff --git a/arch/riscv/boot/dts/spacemit/Makefile b/arch/riscv/boot/dts/spacemit/Makefile
index fb2fdbd4d..e4d644b68 100644
--- a/arch/riscv/boot/dts/spacemit/Makefile
+++ b/arch/riscv/boot/dts/spacemit/Makefile
@@ -1,3 +1,4 @@
+dtb-$(CONFIG_SOC_SPACEMIT_K1X) += k1-bananapi-f3.dtb
dtb-$(CONFIG_SOC_SPACEMIT_K1X) += k1-x_evb.dtb k1-x_deb2.dtb k1-x_deb1.dtb k1-x_hs450.dtb \
k1-x_kx312.dtb k1-x_MINI-PC.dtb k1-x_MUSE-N1.dtb k1-x_mingo.dtb \
k1-x_MUSE-Pi.dtb k1-x_milkv-jupiter.dtb m1-x_milkv-jupiter.dtb \
diff --git a/arch/riscv/boot/dts/spacemit/k1-bananapi-f3.dts b/arch/riscv/boot/dts/spacemit/k1-bananapi-f3.dts
new file mode 100644
index 000000000..ba29585ca
--- /dev/null
+++ b/arch/riscv/boot/dts/spacemit/k1-bananapi-f3.dts
@@ -0,0 +1,21 @@
+// SPDX-License-Identifier: (GPL-2.0 OR MIT)
+/* Copyright (c) 2024 Spacemit, Inc */
+
+/dts-v1/;
+
+#include "k1-x_deb1.dts"
+
+/ {
+ model = "BananaPi BPI-F3";
+};
+
+&uart2 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_uart2>;
+ status = "disabled";
+
+ bluetooth {
+ compatible = "realtek,rtl8852bs-bt";
+ device-wake-gpios = <&gpio 64 GPIO_ACTIVE_HIGH>;
+ };
+};
--
2.39.2

View File

@@ -0,0 +1,26 @@
From 4e85858c9a2217f93b34fd767488de2123f99fea Mon Sep 17 00:00:00 2001
From: Patrick Yavitz <pyavitz@xxxxx.com>
Date: Wed, 26 Jun 2024 06:01:30 -0400
Subject: [PATCH] Bluetooth: hci_h5: Add support for RTL8852BS
Signed-off-by: Patrick Yavitz <pyavitz@xxxxx.com>
---
drivers/bluetooth/hci_h5.c | 2 ++
1 file changed, 2 insertions(+)
diff --git a/drivers/bluetooth/hci_h5.c b/drivers/bluetooth/hci_h5.c
index e90670955df2..a05ab0c37e81 100644
--- a/drivers/bluetooth/hci_h5.c
+++ b/drivers/bluetooth/hci_h5.c
@@ -1106,6 +1106,8 @@ static const struct of_device_id rtl_bluetooth_of_match[] = {
.data = (const void *)&h5_data_rtl8723bs },
{ .compatible = "realtek,rtl8723ds-bt",
.data = (const void *)&h5_data_rtl8723bs },
+ { .compatible = "realtek,rtl8852bs-bt",
+ .data = (const void *)&h5_data_rtl8723bs },
#endif
{ },
};
--
2.39.2

View File

@@ -0,0 +1,40 @@
From d77e410afa4ee896a00335f268f37b59c6f44ea1 Mon Sep 17 00:00:00 2001
From: Patrick Yavitz <pyavitz@armbian.com>
Date: Sat, 17 Aug 2024 11:49:20 -0400
Subject: [PATCH] rtl8852bs: Turn off DEBUG and remove RTW_WARN_LM
Signed-off-by: Patrick Yavitz <pyavitz@armbian.com>
---
drivers/net/wireless/realtek/rtl8852bs/Makefile | 2 +-
drivers/net/wireless/realtek/rtl8852bs/core/rtw_xmit.c | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/drivers/net/wireless/realtek/rtl8852bs/Makefile b/drivers/net/wireless/realtek/rtl8852bs/Makefile
index 2af36254f..181d9320b 100644
--- a/drivers/net/wireless/realtek/rtl8852bs/Makefile
+++ b/drivers/net/wireless/realtek/rtl8852bs/Makefile
@@ -138,7 +138,7 @@ EXTRA_CFLAGS += -DCONFIG_RTW_ANDROID=$(CONFIG_RTW_ANDROID)
endif
########################## Debug ###########################
-CONFIG_RTW_DEBUG = y
+CONFIG_RTW_DEBUG = n
# default log level is _DRV_INFO_ = 4,
# please refer to "How_to_set_driver_debug_log_level.doc" to set the available level.
CONFIG_RTW_LOG_LEVEL = 2
diff --git a/drivers/net/wireless/realtek/rtl8852bs/core/rtw_xmit.c b/drivers/net/wireless/realtek/rtl8852bs/core/rtw_xmit.c
index f50926762..5310587f4 100644
--- a/drivers/net/wireless/realtek/rtl8852bs/core/rtw_xmit.c
+++ b/drivers/net/wireless/realtek/rtl8852bs/core/rtw_xmit.c
@@ -6677,7 +6677,7 @@ static void fill_txreq_list_skb(_adapter *padapter,
if (skb_total_frag_nr(head_skb) > NUM_PKT_LIST_PER_TXREQ - 2) {
rtw_skb_linearize(head_skb);
- RTW_WARN_LMT("skb total frag nr over %d\n", NUM_PKT_LIST_PER_TXREQ - 2);
+ //RTW_WARN_LMT("skb total frag nr over %d\n", NUM_PKT_LIST_PER_TXREQ - 2);
}
_fill_txreq_list_skb(padapter, txreq, pkt_list, head_skb, &req_sz, &offset);
--
2.39.2

View File

@@ -0,0 +1,25 @@
From 5d858cd89700b69bdf37661052a6c07f5ca040e8 Mon Sep 17 00:00:00 2001
From: Patrick Yavitz <pyavitz@gmail.com>
Date: Wed, 18 Dec 2024 10:28:24 -0500
Subject: [PATCH] Do not build Focaltech touch
Signed-off-by: Patrick Yavitz <pyavitz@gmail.com>
---
drivers/input/touchscreen/focaltech_touch/Kconfig | 1 -
1 file changed, 1 deletion(-)
diff --git a/drivers/input/touchscreen/focaltech_touch/Kconfig b/drivers/input/touchscreen/focaltech_touch/Kconfig
index 9d34d7437..0d97331f5 100755
--- a/drivers/input/touchscreen/focaltech_touch/Kconfig
+++ b/drivers/input/touchscreen/focaltech_touch/Kconfig
@@ -4,7 +4,6 @@
config TOUCHSCREEN_FTS
tristate "Focaltech Touchscreen"
- default m
help
Say Y here if you have Focaltech touch panel.
If unsure, say N.
--
2.39.5

View File

@@ -1,10 +1,9 @@
From faa72a12de6759e8bd14736bba16e5ac778bf96f Mon Sep 17 00:00:00 2001 From 1caeec5d9b700d2408c44df4e4ce7ac2a90412ab Mon Sep 17 00:00:00 2001
From: Banana Pi -BPI <lionwang@sinovoip.com.cn> From: Banana Pi -BPI <lionwang@sinovoip.com.cn>
Date: Thu, 11 Jul 2024 07:33:58 -0400 Date: Mon, 4 Nov 2024 09:59:05 -0500
Subject: [PATCH 1/4] MBR support Subject: [PATCH] MBR support
Signed-off-by: Banana Pi -BPI <lionwang@sinovoip.com.cn> Signed-off-by: Banana Pi -BPI <lionwang@sinovoip.com.cn>
Signed-off-by: Patrick Yavitz <pyavitz@armbian.com>
--- ---
board/spacemit/k1-x/k1x.c | 10 +++++++++- board/spacemit/k1-x/k1x.c | 10 +++++++++-
common/spl/spl_mmc.c | 22 ++++++++++++++++++++-- common/spl/spl_mmc.c | 22 ++++++++++++++++++++--
@@ -12,10 +11,10 @@ Signed-off-by: Patrick Yavitz <pyavitz@armbian.com>
3 files changed, 30 insertions(+), 3 deletions(-) 3 files changed, 30 insertions(+), 3 deletions(-)
diff --git a/board/spacemit/k1-x/k1x.c b/board/spacemit/k1-x/k1x.c diff --git a/board/spacemit/k1-x/k1x.c b/board/spacemit/k1-x/k1x.c
index b6f06fbb..70141121 100644 index f47d9475..460eea4f 100644
--- a/board/spacemit/k1-x/k1x.c --- a/board/spacemit/k1-x/k1x.c
+++ b/board/spacemit/k1-x/k1x.c +++ b/board/spacemit/k1-x/k1x.c
@@ -312,6 +312,7 @@ void _load_env_from_blk(struct blk_desc *dev_desc, const char *dev_name, int dev @@ -440,6 +440,7 @@ void _load_env_from_blk(struct blk_desc *dev_desc, const char *dev_name, int dev
char cmd[128]; char cmd[128];
struct disk_partition info; struct disk_partition info;
@@ -23,7 +22,7 @@ index b6f06fbb..70141121 100644
for (part = 1; part <= MAX_SEARCH_PARTITIONS; part++) { for (part = 1; part <= MAX_SEARCH_PARTITIONS; part++) {
err = part_get_info(dev_desc, part, &info); err = part_get_info(dev_desc, part, &info);
if (err) if (err)
@@ -321,8 +322,13 @@ void _load_env_from_blk(struct blk_desc *dev_desc, const char *dev_name, int dev @@ -449,8 +450,13 @@ void _load_env_from_blk(struct blk_desc *dev_desc, const char *dev_name, int dev
break; break;
} }
} }
@@ -38,7 +37,7 @@ index b6f06fbb..70141121 100644
env_set("bootfs_part", simple_itoa(part)); env_set("bootfs_part", simple_itoa(part));
env_set("bootfs_devname", dev_name); env_set("bootfs_devname", dev_name);
@@ -332,12 +338,14 @@ void _load_env_from_blk(struct blk_desc *dev_desc, const char *dev_name, int dev @@ -460,12 +466,14 @@ void _load_env_from_blk(struct blk_desc *dev_desc, const char *dev_name, int dev
sprintf(cmd, "load %s %d:%d 0x%x env_%s.txt", dev_name, sprintf(cmd, "load %s %d:%d 0x%x env_%s.txt", dev_name,
dev, part, CONFIG_SPL_LOAD_FIT_ADDRESS, CONFIG_SYS_CONFIG_NAME); dev, part, CONFIG_SPL_LOAD_FIT_ADDRESS, CONFIG_SYS_CONFIG_NAME);
pr_debug("cmd:%s\n", cmd); pr_debug("cmd:%s\n", cmd);
@@ -54,7 +53,7 @@ index b6f06fbb..70141121 100644
pr_info("load env_%s.txt from bootfs successful\n", CONFIG_SYS_CONFIG_NAME); pr_info("load env_%s.txt from bootfs successful\n", CONFIG_SYS_CONFIG_NAME);
} }
diff --git a/common/spl/spl_mmc.c b/common/spl/spl_mmc.c diff --git a/common/spl/spl_mmc.c b/common/spl/spl_mmc.c
index acf2b278..3109c93d 100644 index acf2b278..581958bb 100644
--- a/common/spl/spl_mmc.c --- a/common/spl/spl_mmc.c
+++ b/common/spl/spl_mmc.c +++ b/common/spl/spl_mmc.c
@@ -91,6 +91,7 @@ int mmc_load_image_raw_sector(struct spl_image_info *spl_image, @@ -91,6 +91,7 @@ int mmc_load_image_raw_sector(struct spl_image_info *spl_image,
@@ -104,7 +103,7 @@ index acf2b278..3109c93d 100644
#endif #endif
} }
diff --git a/configs/k1_defconfig b/configs/k1_defconfig diff --git a/configs/k1_defconfig b/configs/k1_defconfig
index 568400e5..66a6729a 100644 index b23d595b..197d54cb 100644
--- a/configs/k1_defconfig --- a/configs/k1_defconfig
+++ b/configs/k1_defconfig +++ b/configs/k1_defconfig
@@ -23,6 +23,7 @@ CONFIG_ARCH_RV64I=y @@ -23,6 +23,7 @@ CONFIG_ARCH_RV64I=y
@@ -116,5 +115,5 @@ index 568400e5..66a6729a 100644
CONFIG_HAS_CUSTOM_SYS_INIT_SP_ADDR=y CONFIG_HAS_CUSTOM_SYS_INIT_SP_ADDR=y
CONFIG_CUSTOM_SYS_INIT_SP_ADDR=0x1000000 CONFIG_CUSTOM_SYS_INIT_SP_ADDR=0x1000000
-- --
2.35.3 2.39.5

View File

@@ -1,16 +1,15 @@
From 1377ac604cc13156c4af4e7cdc5d3acafcbd2db5 Mon Sep 17 00:00:00 2001 From e646c31222ba2175e7ded14507f852a1a2202e8e Mon Sep 17 00:00:00 2001
From: Banana Pi -BPI <lionwang@sinovoip.com.cn> From: Banana Pi -BPI <lionwang@sinovoip.com.cn>
Date: Thu, 11 Jul 2024 07:37:18 -0400 Date: Thu, 11 Jul 2024 07:37:18 -0400
Subject: [PATCH 2/4] change AUTOBOOT_STOP_STR to Space KEY Subject: [PATCH] change AUTOBOOT_STOP_STR to Space KEY
Signed-off-by: Banana Pi -BPI <lionwang@sinovoip.com.cn> Signed-off-by: Banana Pi -BPI <lionwang@sinovoip.com.cn>
Signed-off-by: Patrick Yavitz <pyavitz@armbian.com>
--- ---
configs/k1_defconfig | 7 +++++-- configs/k1_defconfig | 7 +++++--
1 file changed, 5 insertions(+), 2 deletions(-) 1 file changed, 5 insertions(+), 2 deletions(-)
diff --git a/configs/k1_defconfig b/configs/k1_defconfig diff --git a/configs/k1_defconfig b/configs/k1_defconfig
index 66a6729a..7ae44243 100644 index a3adf4b091..4ee8f69e47 100644
--- a/configs/k1_defconfig --- a/configs/k1_defconfig
+++ b/configs/k1_defconfig +++ b/configs/k1_defconfig
@@ -35,9 +35,12 @@ CONFIG_SPL_LOAD_FIT_ADDRESS=0x11000000 @@ -35,9 +35,12 @@ CONFIG_SPL_LOAD_FIT_ADDRESS=0x11000000
@@ -29,5 +28,5 @@ index 66a6729a..7ae44243 100644
CONFIG_BOOTCOMMAND="bootm 0x11000000" CONFIG_BOOTCOMMAND="bootm 0x11000000"
CONFIG_LOGLEVEL=7 CONFIG_LOGLEVEL=7
-- --
2.35.3 2.39.2

View File

@@ -1,23 +1,25 @@
From eec3cefda7f6f5b50b7fce2f07736f79c855d93a Mon Sep 17 00:00:00 2001 From 55d1b972a09de27995c29fe4eb8e3b9ade3a9ba9 Mon Sep 17 00:00:00 2001
From: Patrick Yavitz <pyavitz@armbian.com> From: Patrick Yavitz <pyavitz@gmail.com>
Date: Thu, 11 Jul 2024 07:43:37 -0400 Date: Wed, 25 Dec 2024 18:35:46 -0500
Subject: [PATCH 3/4] Syslinux and script support Subject: [PATCH] Add syslinux and script support
Signed-off-by: Patrick Yavitz <pyavitz@armbian.com> Signed-off-by: Patrick Yavitz <pyavitz@gmail.com>
--- ---
board/spacemit/k1-x/k1-x.env | 185 ++++------------------------------- board/spacemit/k1-x/k1-x.env | 246 ++++-------------------------------
board/spacemit/k1-x/k1x.c | 20 ++-- 1 file changed, 22 insertions(+), 224 deletions(-)
configs/k1_defconfig | 3 +
include/configs/k1-x.h | 23 ++---
4 files changed, 43 insertions(+), 188 deletions(-)
diff --git a/board/spacemit/k1-x/k1-x.env b/board/spacemit/k1-x/k1-x.env diff --git a/board/spacemit/k1-x/k1-x.env b/board/spacemit/k1-x/k1-x.env
index bdb32b35..acb1ef7a 100644 index bb18f40e..acb1ef7a 100644
--- a/board/spacemit/k1-x/k1-x.env --- a/board/spacemit/k1-x/k1-x.env
+++ b/board/spacemit/k1-x/k1-x.env +++ b/board/spacemit/k1-x/k1-x.env
@@ -8,169 +8,24 @@ loglevel=8 @@ -4,230 +4,28 @@ console=ttyS0,115200
init=/init
bootdelay=0
baudrate=115200
+loglevel=8
stderr=serial stderr=serial
stdin=serial,usbkbd -stdin=serial,usbkbd,usbkbd1
+stdin=serial,usbkbd
stdout=serial stdout=serial
-workqueue.default_affinity_scope=system -workqueue.default_affinity_scope=system
- -
@@ -56,11 +58,12 @@ index bdb32b35..acb1ef7a 100644
-//ethaddr=fe:fe:fe:22:22:01 -//ethaddr=fe:fe:fe:22:22:01
-//eth1addr=fe:fe:fe:22:22:02 -//eth1addr=fe:fe:fe:22:22:02
- -
-ipaddr=10.0.92.100 -ipaddr=
-netmask=255.255.255.0 -netmask=255.255.255.0
-serverip=10.0.92.134 -serverip=10.0.92.148
-gatewayip=10.0.92.1 -gatewayip=10.0.92.1
-net_data_path=net_flash_file/net_flash_file/ -net_data_path=net_flash_file/net_flash_file/
-mac_mapping_file=/home/it/nfs/bianbu/mac_mapping.txt
- -
-preboot= -preboot=
-ramdisk_size=- -ramdisk_size=-
@@ -70,14 +73,24 @@ index bdb32b35..acb1ef7a 100644
-dtb_dir= -dtb_dir=
-dtb_name=k1-x_evb.dtb -dtb_name=k1-x_evb.dtb
-splashfile=bianbu.bmp -splashfile=bianbu.bmp
-grub_file=EFI/BOOT/BOOTRISCV64.EFI
-mdio_intf= -mdio_intf=
-phyaddr0=1 -phyaddr0=1
-phy_link_time=10000 -phy_link_time=10000
-netdev=eth0 -netdev=eth0
- -
-uboot_status=IN_UBOOT
-
-// EFI system partition
-esp_name=ESP
-esp_index=5
-usb_start=true
-
-get_esp_index=env set esp_index ${bootfs_part}; \
- part number ${bootfs_devname} ${boot_devnum} ${esp_name} esp_index;
-
-// Common boot args -// Common boot args
-set_bootargs=setenv bootargs earlycon=${earlycon} earlyprintk quiet splash console=${console} loglevel=${loglevel} clk_ignore_unused swiotlb=65536 rdinit=${init} product_name=${product_name} -commonargs=setenv bootargs earlyprintk quiet splash plymouth.ignore-serial-consoles plymouth.prefer-fbcon clk_ignore_unused swiotlb=65536 workqueue.default_affinity_scope=${workqueue.default_affinity_scope}
-commonargs=run set_bootargs; setenv bootargs "${bootargs}" plymouth.ignore-serial-consoles plymouth.prefer-fbcon workqueue.default_affinity_scope=${workqueue.default_affinity_scope}
- -
-//detect product_name from env and select dtb file to load -//detect product_name from env and select dtb file to load
-dtb_env=if test -n "${product_name}"; then \ -dtb_env=if test -n "${product_name}"; then \
@@ -123,18 +136,42 @@ index bdb32b35..acb1ef7a 100644
- setenv dtb_addr ""; \ - setenv dtb_addr ""; \
- fi; - fi;
- -
-load_grub=echo "Loading grub..."; \
- load ${bootfs_devname} ${boot_devnum}:${esp_index} ${kernel_addr_r} ${grub_file};
-
-# bootm command for fit image, booti command for PE or compress PE image
-start_kernel=fdt addr ${kernel_addr_r}; \
- if fdt list /; then \
- bootm ${kernel_addr_r} ${ramdisk_combo} ${dtb_addr}; \
- else \
- booti ${kernel_addr_r} ${ramdisk_combo} ${dtb_addr}; \
- fi;
-
-boot_kernel=run detect_dtb; \
- run loadknl; \
- run loaddtb; \
- run loadramdisk; \
- run start_kernel;
-
-boot_grub=env set -e -bs product_name "${product_name}"; \
- env set -e -bs bootargs "${bootargs}"; \
- run usb_start;
- run load_grub; \
- bootefi ${kernel_addr_r};
-
-// Nor+ssd boot combo -// Nor+ssd boot combo
-set_nor_args=setenv bootargs "${bootargs}" mtdparts=${mtdparts} root=${blk_root} rootfstype=ext4 -set_nor_args=setenv bootargs "${bootargs}" mtdparts=${mtdparts} root=${blk_root} rootfstype=ext4
-nor_boot=echo "Try to boot from ${bootfs_devname}${boot_devnum} ..."; \ -nor_boot=echo "Try to boot from ${bootfs_devname}${boot_devnum} ..."; \
- run commonargs; \ - run commonargs; \
- run set_nor_root; \ - run set_nor_root; \
- run set_nor_args; \ - run set_nor_args; \
- run detect_dtb; \ - run get_esp_index; \
- run loadknl; \ - if test -e ${bootfs_devname} ${boot_devnum}:${esp_index} ${grub_file}; then \
- run loaddtb; \ - run boot_grub; \
- run loadramdisk; \ - else \
- bootm ${kernel_addr_r} ${ramdisk_combo} ${dtb_addr}; \ - run boot_kernel; \
- echo "########### boot kernel failed by default config, check your boot config #############" - fi; \
- echo "########### boot failed by default config, check your boot config #############"
- -
-//############################################################################## -//##############################################################################
-// eMMC/SDCard boot -// eMMC/SDCard boot
@@ -142,15 +179,36 @@ index bdb32b35..acb1ef7a 100644
-set_mmc_args=setenv bootargs "${bootargs}" root=${blk_root} rootwait rootfstype=${mmc_rootfstype}; -set_mmc_args=setenv bootargs "${bootargs}" root=${blk_root} rootwait rootfstype=${mmc_rootfstype};
- -
-mmc_boot=echo "Try to boot from ${bootfs_devname}${boot_devnum} ..."; \ -mmc_boot=echo "Try to boot from ${bootfs_devname}${boot_devnum} ..."; \
- run commonargs; \ - run commonargs; \
- run set_mmc_root; \ - run set_mmc_root; \
- run set_mmc_args; \ - run set_mmc_args; \
- run detect_dtb; \ - run get_esp_index; \
- run loadknl; \ - if test -e ${bootfs_devname} ${boot_devnum}:${esp_index} ${grub_file}; then \
- run loaddtb; \ - run boot_grub; \
- run loadramdisk; \ - else \
- bootm ${kernel_addr_r} ${ramdisk_combo} ${dtb_addr}; \ - run boot_kernel; \
- echo "########### boot kernel failed by default config, check your boot config #############" - fi; \
- echo "########### boot failed by default config, check your boot config #############"
-
-nfs_boot=echo "Try to boot from NFS ..."; \
- run commonargs; \
- setenv bootargs "${bootargs}" root=/dev/nfs nfsroot=${serverip}:${rootfs_path} bootfs=${serverip}:${bootfs_path} ip=${ipaddr}:${serverip}:${gatewayip}:${netmask}::${netdev}:off noipath; \
- echo "bootargs: ${bootargs}"; \
- run detect_dtb; \
- echo "Loading kernel from NFS..."; \
- nfs ${kernel_addr_r} ${serverip}:${bootfs_path}/${knl_name}; \
- echo "Loading dtb from NFS..."; \
- nfs ${dtb_addr} ${serverip}:${bootfs_path}/${dtb_name}; \
- if test -n "${ramdisk_name}"; then \
- echo "Loading ramdisk from NFS..."; \
- nfs ${ramdisk_addr} ${serverip}:${bootfs_path}/${ramdisk_name}; \
- setenv ramdisk_size ${filesize}; \
- setenv ramdisk_combo ${ramdisk_addr}:${ramdisk_size}; \
- else \
- setenv ramdisk_combo -; \
- fi; \
- run start_kernel; \
- echo "########### boot kernel failed from NFS, check your boot config #############"
- -
-// Variable "boot_device" is set during board_late_init() -// Variable "boot_device" is set during board_late_init()
-autoboot=if test ${boot_device} = nand; then \ -autoboot=if test ${boot_device} = nand; then \
@@ -159,6 +217,8 @@ index bdb32b35..acb1ef7a 100644
- run nor_boot; \ - run nor_boot; \
- elif test ${boot_device} = mmc; then \ - elif test ${boot_device} = mmc; then \
- run mmc_boot; \ - run mmc_boot; \
- elif test ${boot_device} = nfs; then \
- run nfs_boot; \
- fi; - fi;
- -
-bootcmd=run autoboot; echo "run autoboot" -bootcmd=run autoboot; echo "run autoboot"
@@ -205,11 +265,26 @@ index bdb32b35..acb1ef7a 100644
+ fi; + fi;
+ +
+bootcmd=echo "Loading ..."; run autoboot +bootcmd=echo "Loading ..."; run autoboot
--
2.39.5
From 9bb50320cc81251c93a21a94fb73cf0a2feb693e Mon Sep 17 00:00:00 2001
From: Patrick Yavitz <pyavitz@gmail.com>
Date: Mon, 4 Nov 2024 10:09:19 -0500
Subject: [PATCH] Add syslinux and script support
Signed-off-by: Patrick Yavitz <pyavitz@gmail.com>
---
board/spacemit/k1-x/k1x.c | 20 ++++++++++----------
configs/k1_defconfig | 3 +++
include/configs/k1-x.h | 23 ++++++++++-------------
3 files changed, 23 insertions(+), 23 deletions(-)
diff --git a/board/spacemit/k1-x/k1x.c b/board/spacemit/k1-x/k1x.c diff --git a/board/spacemit/k1-x/k1x.c b/board/spacemit/k1-x/k1x.c
index 70141121..ada5f1fc 100644 index 460eea4f..7f59b332 100644
--- a/board/spacemit/k1-x/k1x.c --- a/board/spacemit/k1-x/k1x.c
+++ b/board/spacemit/k1-x/k1x.c +++ b/board/spacemit/k1-x/k1x.c
@@ -330,8 +330,8 @@ void _load_env_from_blk(struct blk_desc *dev_desc, const char *dev_name, int dev @@ -458,8 +458,8 @@ void _load_env_from_blk(struct blk_desc *dev_desc, const char *dev_name, int dev
#endif #endif
} }
@@ -220,7 +295,7 @@ index 70141121..ada5f1fc 100644
/*load env.txt and import to uboot*/ /*load env.txt and import to uboot*/
memset((void *)CONFIG_SPL_LOAD_FIT_ADDRESS, 0, CONFIG_ENV_SIZE); memset((void *)CONFIG_SPL_LOAD_FIT_ADDRESS, 0, CONFIG_ENV_SIZE);
@@ -510,7 +510,7 @@ void setenv_boot_mode(void) @@ -662,7 +662,7 @@ void setenv_boot_mode(void)
u32 boot_mode = get_boot_mode(); u32 boot_mode = get_boot_mode();
switch (boot_mode) { switch (boot_mode) {
case BOOT_MODE_NAND: case BOOT_MODE_NAND:
@@ -229,7 +304,7 @@ index 70141121..ada5f1fc 100644
break; break;
case BOOT_MODE_NOR: case BOOT_MODE_NOR:
char *blk_name; char *blk_name;
@@ -521,23 +521,23 @@ void setenv_boot_mode(void) @@ -673,23 +673,23 @@ void setenv_boot_mode(void)
return; return;
} }
@@ -261,7 +336,7 @@ index 70141121..ada5f1fc 100644
} }
} }
diff --git a/configs/k1_defconfig b/configs/k1_defconfig diff --git a/configs/k1_defconfig b/configs/k1_defconfig
index 7ae44243..5af667bf 100644 index 8db91b1e..63ac72b5 100644
--- a/configs/k1_defconfig --- a/configs/k1_defconfig
+++ b/configs/k1_defconfig +++ b/configs/k1_defconfig
@@ -43,6 +43,8 @@ CONFIG_AUTOBOOT_STOP_STR=" " @@ -43,6 +43,8 @@ CONFIG_AUTOBOOT_STOP_STR=" "
@@ -273,13 +348,13 @@ index 7ae44243..5af667bf 100644
CONFIG_LOGLEVEL=7 CONFIG_LOGLEVEL=7
CONFIG_SPL_LOGLEVEL=1 CONFIG_SPL_LOGLEVEL=1
# CONFIG_SYS_DEVICE_NULLDEV is not set # CONFIG_SYS_DEVICE_NULLDEV is not set
@@ -279,3 +281,4 @@ CONFIG_PRINT_TIMESTAMP=y @@ -288,3 +290,4 @@ CONFIG_PRINT_TIMESTAMP=y
# CONFIG_SPL_SHA1 is not set
# CONFIG_SPL_SHA256 is not set # CONFIG_SPL_SHA256 is not set
CONFIG_ZSTD=y CONFIG_ZSTD=y
# CONFIG_HEXDUMP is not set
+CONFIG_OF_LIBFDT_OVERLAY=y +CONFIG_OF_LIBFDT_OVERLAY=y
diff --git a/include/configs/k1-x.h b/include/configs/k1-x.h diff --git a/include/configs/k1-x.h b/include/configs/k1-x.h
index f1f4be78..34ad156e 100644 index 8d27fe9d..c7f42bbc 100644
--- a/include/configs/k1-x.h --- a/include/configs/k1-x.h
+++ b/include/configs/k1-x.h +++ b/include/configs/k1-x.h
@@ -84,11 +84,6 @@ @@ -84,11 +84,6 @@
@@ -306,7 +381,7 @@ index f1f4be78..34ad156e 100644
#include <config_distro_bootcmd.h> #include <config_distro_bootcmd.h>
#define BOOTENV_DEV_QEMU(devtypeu, devtypel, instance) \ #define BOOTENV_DEV_QEMU(devtypeu, devtypel, instance) \
@@ -167,11 +167,6 @@ struct boot_storage_op @@ -167,16 +167,13 @@ struct boot_storage_op
/*if env not use for spl, please define to board/spacemit/k1-x/k1-x.env */ /*if env not use for spl, please define to board/spacemit/k1-x/k1-x.env */
#define CONFIG_EXTRA_ENV_SETTINGS \ #define CONFIG_EXTRA_ENV_SETTINGS \
"stdout_flash=serial,vidconsole\0" \ "stdout_flash=serial,vidconsole\0" \
@@ -317,11 +392,6 @@ index f1f4be78..34ad156e 100644
- "dtb_addr=" __stringify(DTB_LOAD_ADDR) "\0" \ - "dtb_addr=" __stringify(DTB_LOAD_ADDR) "\0" \
"scriptaddr=0x2c100000\0" \ "scriptaddr=0x2c100000\0" \
"pxefile_addr_r=0x0c200000\0" \ "pxefile_addr_r=0x0c200000\0" \
"ipaddr=192.168.1.15\0" \
@@ -179,9 +174,11 @@ struct boot_storage_op
"serverip=10.0.92.134\0" \
"gatewayip=192.168.1.1\0" \
"net_data_path=spacemit_flash_file/net_flash_file/\0" \
- "splashimage=" __stringify(CONFIG_FASTBOOT_BUF_ADDR) "\0" \ - "splashimage=" __stringify(CONFIG_FASTBOOT_BUF_ADDR) "\0" \
- "splashpos=m,m\0" \ - "splashpos=m,m\0" \
- "splashfile=bianbu.bmp\0" \ - "splashfile=bianbu.bmp\0" \
@@ -334,5 +404,5 @@ index f1f4be78..34ad156e 100644
-- --
2.35.3 2.39.5

View File

@@ -1,7 +1,7 @@
From 0027fcd7dedbc6920c6222e5887df60651b22b2b Mon Sep 17 00:00:00 2001 From 60013790aa6b8ba65fdb7546f715314d00591f81 Mon Sep 17 00:00:00 2001
From: Tejas Bhumkar <tejas.arvind.bhumkar@amd.com> From: Tejas Bhumkar <tejas.arvind.bhumkar@amd.com>
Date: Fri, 7 Jun 2024 06:32:58 -0400 Date: Fri, 7 Jun 2024 06:32:58 -0400
Subject: [PATCH 4/4] efi_loader : Suppress error print message Subject: [PATCH] efi_loader : Suppress error print message
Currently, on certain Xilinx platforms, an issue has been Currently, on certain Xilinx platforms, an issue has been
identified, manifesting as follows: identified, manifesting as follows:
@@ -38,7 +38,7 @@ Signed-off-by: Tejas Bhumkar <tejas.arvind.bhumkar@amd.com>
1 file changed, 1 insertion(+), 1 deletion(-) 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/lib/efi_loader/efi_memory.c b/lib/efi_loader/efi_memory.c diff --git a/lib/efi_loader/efi_memory.c b/lib/efi_loader/efi_memory.c
index 15c42be7..a4840ead 100644 index e048a545e4..7fea2f79c8 100644
--- a/lib/efi_loader/efi_memory.c --- a/lib/efi_loader/efi_memory.c
+++ b/lib/efi_loader/efi_memory.c +++ b/lib/efi_loader/efi_memory.c
@@ -660,7 +660,7 @@ efi_status_t efi_free_pool(void *buffer) @@ -660,7 +660,7 @@ efi_status_t efi_free_pool(void *buffer)
@@ -51,5 +51,5 @@ index 15c42be7..a4840ead 100644
} }
/* Avoid double free */ /* Avoid double free */
-- --
2.35.3 2.39.2