mirror of
https://github.com/armbian/build
synced 2025-09-24 19:47:06 +07:00
BananaPi BPI-F3: Update u-boot and linux patching
Signed-off-by: Patrick Yavitz <pyavitz@gmail.com>
This commit is contained in:
committed by
c0rnelius
parent
7b6fcab372
commit
df9ddaf44e
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
@@ -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
@@ -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
|
||||
|
||||
@@ -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
File diff suppressed because it is too large
Load Diff
@@ -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
|
||||
|
||||
@@ -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", µvol);
|
||||
+ 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(®ulator_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(®ulator_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
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
File diff suppressed because it is too large
Load Diff
@@ -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
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -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
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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, ¶m);
|
||||
+
|
||||
+ 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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
File diff suppressed because it is too large
Load Diff
@@ -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
|
||||
|
||||
@@ -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
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
@@ -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
|
||||
|
||||
@@ -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
@@ -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
|
||||
|
||||
@@ -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>;
|
||||
};
|
||||
};
|
||||
@@ -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>;
|
||||
};
|
||||
};
|
||||
};
|
||||
@@ -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 */
|
||||
@@ -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";
|
||||
};
|
||||
};
|
||||
@@ -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";
|
||||
};
|
||||
|
||||
@@ -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>;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
@@ -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
@@ -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
@@ -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>;
|
||||
};
|
||||
};
|
||||
};
|
||||
};};
|
||||
@@ -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>;
|
||||
};
|
||||
@@ -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>;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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>
|
||||
Date: Thu, 11 Jul 2024 07:33:58 -0400
|
||||
Subject: [PATCH 1/4] MBR support
|
||||
Date: Mon, 4 Nov 2024 09:59:05 -0500
|
||||
Subject: [PATCH] MBR support
|
||||
|
||||
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 +++++++++-
|
||||
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(-)
|
||||
|
||||
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
|
||||
+++ 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];
|
||||
struct disk_partition info;
|
||||
|
||||
@@ -23,7 +22,7 @@ index b6f06fbb..70141121 100644
|
||||
for (part = 1; part <= MAX_SEARCH_PARTITIONS; part++) {
|
||||
err = part_get_info(dev_desc, part, &info);
|
||||
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;
|
||||
}
|
||||
}
|
||||
@@ -38,7 +37,7 @@ index b6f06fbb..70141121 100644
|
||||
|
||||
env_set("bootfs_part", simple_itoa(part));
|
||||
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,
|
||||
dev, part, CONFIG_SPL_LOAD_FIT_ADDRESS, CONFIG_SYS_CONFIG_NAME);
|
||||
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);
|
||||
}
|
||||
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
|
||||
+++ b/common/spl/spl_mmc.c
|
||||
@@ -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
|
||||
}
|
||||
diff --git a/configs/k1_defconfig b/configs/k1_defconfig
|
||||
index 568400e5..66a6729a 100644
|
||||
index b23d595b..197d54cb 100644
|
||||
--- a/configs/k1_defconfig
|
||||
+++ b/configs/k1_defconfig
|
||||
@@ -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_CUSTOM_SYS_INIT_SP_ADDR=0x1000000
|
||||
--
|
||||
2.35.3
|
||||
2.39.5
|
||||
|
||||
@@ -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>
|
||||
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: Patrick Yavitz <pyavitz@armbian.com>
|
||||
---
|
||||
configs/k1_defconfig | 7 +++++--
|
||||
1 file changed, 5 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/configs/k1_defconfig b/configs/k1_defconfig
|
||||
index 66a6729a..7ae44243 100644
|
||||
index a3adf4b091..4ee8f69e47 100644
|
||||
--- a/configs/k1_defconfig
|
||||
+++ b/configs/k1_defconfig
|
||||
@@ -35,9 +35,12 @@ CONFIG_SPL_LOAD_FIT_ADDRESS=0x11000000
|
||||
@@ -29,5 +28,5 @@ index 66a6729a..7ae44243 100644
|
||||
CONFIG_BOOTCOMMAND="bootm 0x11000000"
|
||||
CONFIG_LOGLEVEL=7
|
||||
--
|
||||
2.35.3
|
||||
2.39.2
|
||||
|
||||
@@ -1,23 +1,25 @@
|
||||
From eec3cefda7f6f5b50b7fce2f07736f79c855d93a Mon Sep 17 00:00:00 2001
|
||||
From: Patrick Yavitz <pyavitz@armbian.com>
|
||||
Date: Thu, 11 Jul 2024 07:43:37 -0400
|
||||
Subject: [PATCH 3/4] Syslinux and script support
|
||||
From 55d1b972a09de27995c29fe4eb8e3b9ade3a9ba9 Mon Sep 17 00:00:00 2001
|
||||
From: Patrick Yavitz <pyavitz@gmail.com>
|
||||
Date: Wed, 25 Dec 2024 18:35:46 -0500
|
||||
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/k1x.c | 20 ++--
|
||||
configs/k1_defconfig | 3 +
|
||||
include/configs/k1-x.h | 23 ++---
|
||||
4 files changed, 43 insertions(+), 188 deletions(-)
|
||||
board/spacemit/k1-x/k1-x.env | 246 ++++-------------------------------
|
||||
1 file changed, 22 insertions(+), 224 deletions(-)
|
||||
|
||||
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
|
||||
+++ 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
|
||||
stdin=serial,usbkbd
|
||||
-stdin=serial,usbkbd,usbkbd1
|
||||
+stdin=serial,usbkbd
|
||||
stdout=serial
|
||||
-workqueue.default_affinity_scope=system
|
||||
-
|
||||
@@ -56,11 +58,12 @@ index bdb32b35..acb1ef7a 100644
|
||||
-//ethaddr=fe:fe:fe:22:22:01
|
||||
-//eth1addr=fe:fe:fe:22:22:02
|
||||
-
|
||||
-ipaddr=10.0.92.100
|
||||
-ipaddr=
|
||||
-netmask=255.255.255.0
|
||||
-serverip=10.0.92.134
|
||||
-serverip=10.0.92.148
|
||||
-gatewayip=10.0.92.1
|
||||
-net_data_path=net_flash_file/net_flash_file/
|
||||
-mac_mapping_file=/home/it/nfs/bianbu/mac_mapping.txt
|
||||
-
|
||||
-preboot=
|
||||
-ramdisk_size=-
|
||||
@@ -70,14 +73,24 @@ index bdb32b35..acb1ef7a 100644
|
||||
-dtb_dir=
|
||||
-dtb_name=k1-x_evb.dtb
|
||||
-splashfile=bianbu.bmp
|
||||
-grub_file=EFI/BOOT/BOOTRISCV64.EFI
|
||||
-mdio_intf=
|
||||
-phyaddr0=1
|
||||
-phy_link_time=10000
|
||||
-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
|
||||
-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=run set_bootargs; setenv bootargs "${bootargs}" plymouth.ignore-serial-consoles plymouth.prefer-fbcon workqueue.default_affinity_scope=${workqueue.default_affinity_scope}
|
||||
-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}
|
||||
-
|
||||
-//detect product_name from env and select dtb file to load
|
||||
-dtb_env=if test -n "${product_name}"; then \
|
||||
@@ -123,18 +136,42 @@ index bdb32b35..acb1ef7a 100644
|
||||
- setenv dtb_addr ""; \
|
||||
- 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
|
||||
-set_nor_args=setenv bootargs "${bootargs}" mtdparts=${mtdparts} root=${blk_root} rootfstype=ext4
|
||||
-nor_boot=echo "Try to boot from ${bootfs_devname}${boot_devnum} ..."; \
|
||||
- run commonargs; \
|
||||
- run set_nor_root; \
|
||||
- run set_nor_args; \
|
||||
- run detect_dtb; \
|
||||
- run loadknl; \
|
||||
- run loaddtb; \
|
||||
- run loadramdisk; \
|
||||
- bootm ${kernel_addr_r} ${ramdisk_combo} ${dtb_addr}; \
|
||||
- echo "########### boot kernel failed by default config, check your boot config #############"
|
||||
- run commonargs; \
|
||||
- run set_nor_root; \
|
||||
- run set_nor_args; \
|
||||
- run get_esp_index; \
|
||||
- if test -e ${bootfs_devname} ${boot_devnum}:${esp_index} ${grub_file}; then \
|
||||
- run boot_grub; \
|
||||
- else \
|
||||
- run boot_kernel; \
|
||||
- fi; \
|
||||
- echo "########### boot failed by default config, check your boot config #############"
|
||||
-
|
||||
-//##############################################################################
|
||||
-// eMMC/SDCard boot
|
||||
@@ -142,15 +179,36 @@ index bdb32b35..acb1ef7a 100644
|
||||
-set_mmc_args=setenv bootargs "${bootargs}" root=${blk_root} rootwait rootfstype=${mmc_rootfstype};
|
||||
-
|
||||
-mmc_boot=echo "Try to boot from ${bootfs_devname}${boot_devnum} ..."; \
|
||||
- run commonargs; \
|
||||
- run set_mmc_root; \
|
||||
- run set_mmc_args; \
|
||||
- run detect_dtb; \
|
||||
- run loadknl; \
|
||||
- run loaddtb; \
|
||||
- run loadramdisk; \
|
||||
- bootm ${kernel_addr_r} ${ramdisk_combo} ${dtb_addr}; \
|
||||
- echo "########### boot kernel failed by default config, check your boot config #############"
|
||||
- run commonargs; \
|
||||
- run set_mmc_root; \
|
||||
- run set_mmc_args; \
|
||||
- run get_esp_index; \
|
||||
- if test -e ${bootfs_devname} ${boot_devnum}:${esp_index} ${grub_file}; then \
|
||||
- run boot_grub; \
|
||||
- else \
|
||||
- run boot_kernel; \
|
||||
- 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()
|
||||
-autoboot=if test ${boot_device} = nand; then \
|
||||
@@ -159,6 +217,8 @@ index bdb32b35..acb1ef7a 100644
|
||||
- run nor_boot; \
|
||||
- elif test ${boot_device} = mmc; then \
|
||||
- run mmc_boot; \
|
||||
- elif test ${boot_device} = nfs; then \
|
||||
- run nfs_boot; \
|
||||
- fi;
|
||||
-
|
||||
-bootcmd=run autoboot; echo "run autoboot"
|
||||
@@ -205,11 +265,26 @@ index bdb32b35..acb1ef7a 100644
|
||||
+ fi;
|
||||
+
|
||||
+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
|
||||
index 70141121..ada5f1fc 100644
|
||||
index 460eea4f..7f59b332 100644
|
||||
--- a/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
|
||||
}
|
||||
|
||||
@@ -220,7 +295,7 @@ index 70141121..ada5f1fc 100644
|
||||
|
||||
/*load env.txt and import to uboot*/
|
||||
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();
|
||||
switch (boot_mode) {
|
||||
case BOOT_MODE_NAND:
|
||||
@@ -229,7 +304,7 @@ index 70141121..ada5f1fc 100644
|
||||
break;
|
||||
case BOOT_MODE_NOR:
|
||||
char *blk_name;
|
||||
@@ -521,23 +521,23 @@ void setenv_boot_mode(void)
|
||||
@@ -673,23 +673,23 @@ void setenv_boot_mode(void)
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -261,7 +336,7 @@ index 70141121..ada5f1fc 100644
|
||||
}
|
||||
}
|
||||
diff --git a/configs/k1_defconfig b/configs/k1_defconfig
|
||||
index 7ae44243..5af667bf 100644
|
||||
index 8db91b1e..63ac72b5 100644
|
||||
--- a/configs/k1_defconfig
|
||||
+++ b/configs/k1_defconfig
|
||||
@@ -43,6 +43,8 @@ CONFIG_AUTOBOOT_STOP_STR=" "
|
||||
@@ -273,13 +348,13 @@ index 7ae44243..5af667bf 100644
|
||||
CONFIG_LOGLEVEL=7
|
||||
CONFIG_SPL_LOGLEVEL=1
|
||||
# CONFIG_SYS_DEVICE_NULLDEV is not set
|
||||
@@ -279,3 +281,4 @@ CONFIG_PRINT_TIMESTAMP=y
|
||||
# CONFIG_SPL_SHA1 is not set
|
||||
@@ -288,3 +290,4 @@ CONFIG_PRINT_TIMESTAMP=y
|
||||
# CONFIG_SPL_SHA256 is not set
|
||||
CONFIG_ZSTD=y
|
||||
# CONFIG_HEXDUMP is not set
|
||||
+CONFIG_OF_LIBFDT_OVERLAY=y
|
||||
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
|
||||
+++ b/include/configs/k1-x.h
|
||||
@@ -84,11 +84,6 @@
|
||||
@@ -306,7 +381,7 @@ index f1f4be78..34ad156e 100644
|
||||
#include <config_distro_bootcmd.h>
|
||||
|
||||
#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 */
|
||||
#define CONFIG_EXTRA_ENV_SETTINGS \
|
||||
"stdout_flash=serial,vidconsole\0" \
|
||||
@@ -317,11 +392,6 @@ index f1f4be78..34ad156e 100644
|
||||
- "dtb_addr=" __stringify(DTB_LOAD_ADDR) "\0" \
|
||||
"scriptaddr=0x2c100000\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" \
|
||||
- "splashpos=m,m\0" \
|
||||
- "splashfile=bianbu.bmp\0" \
|
||||
@@ -334,5 +404,5 @@ index f1f4be78..34ad156e 100644
|
||||
|
||||
|
||||
--
|
||||
2.35.3
|
||||
2.39.5
|
||||
|
||||
@@ -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>
|
||||
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
|
||||
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(-)
|
||||
|
||||
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
|
||||
+++ b/lib/efi_loader/efi_memory.c
|
||||
@@ -660,7 +660,7 @@ efi_status_t efi_free_pool(void *buffer)
|
||||
@@ -51,5 +51,5 @@ index 15c42be7..a4840ead 100644
|
||||
}
|
||||
/* Avoid double free */
|
||||
--
|
||||
2.35.3
|
||||
2.39.2
|
||||
|
||||
Reference in New Issue
Block a user