* [PATCH 2/4] arm64: mm: Provide prot param in trans_pgd_idmap_page()'s prototype
From: Pingfan Liu @ 2024-03-28 11:56 UTC (permalink / raw)
To: linux-arm-kernel
Cc: Pingfan Liu, Catalin Marinas, Will Deacon, Ard Biesheuvel,
Kees Cook, Mark Rutland, Pasha Tatashin
In-Reply-To: <20240328115656.24090-1-piliu@redhat.com>
Since relocate_kernel code will build stack at the rear of the page,
it requires 'wx' on the page. Adapting the prototype of
trans_pgd_idmap_page() to make it doable.
The trans_pgd_idmap_page() can be enhanced further to support multiple
pages. But since the change has met the requirement, it is not
necessary to enhance for the time being.
Signed-off-by: Pingfan Liu <piliu@redhat.com>
Cc: Catalin Marinas <catalin.marinas@arm.com>
Cc: Will Deacon <will@kernel.org>
Cc: Ard Biesheuvel <ardb@kernel.org>
Cc: Kees Cook <keescook@chromium.org>
Cc: Mark Rutland <mark.rutland@arm.com>
Cc: Pasha Tatashin <pasha.tatashin@soleen.com>
To: linux-arm-kernel@lists.infradead.org
---
arch/arm64/include/asm/trans_pgd.h | 2 +-
arch/arm64/kernel/hibernate.c | 3 ++-
arch/arm64/kernel/machine_kexec.c | 4 ++--
arch/arm64/mm/trans_pgd.c | 4 ++--
4 files changed, 7 insertions(+), 6 deletions(-)
diff --git a/arch/arm64/include/asm/trans_pgd.h b/arch/arm64/include/asm/trans_pgd.h
index 033d400a4ea4..c55a8a5670a8 100644
--- a/arch/arm64/include/asm/trans_pgd.h
+++ b/arch/arm64/include/asm/trans_pgd.h
@@ -31,7 +31,7 @@ int trans_pgd_create_copy(struct trans_pgd_info *info, pgd_t **trans_pgd,
unsigned long start, unsigned long end);
int trans_pgd_idmap_page(struct trans_pgd_info *info, phys_addr_t *trans_ttbr0,
- unsigned long *t0sz, void *page);
+ unsigned long *t0sz, void *page, pgprot_t prot);
int trans_pgd_copy_el2_vectors(struct trans_pgd_info *info,
phys_addr_t *el2_vectors);
diff --git a/arch/arm64/kernel/hibernate.c b/arch/arm64/kernel/hibernate.c
index 02870beb271e..0c5ce99b7acf 100644
--- a/arch/arm64/kernel/hibernate.c
+++ b/arch/arm64/kernel/hibernate.c
@@ -203,7 +203,8 @@ static int create_safe_exec_page(void *src_start, size_t length,
memcpy(page, src_start, length);
caches_clean_inval_pou((unsigned long)page, (unsigned long)page + length);
- rc = trans_pgd_idmap_page(&trans_info, &trans_ttbr0, &t0sz, page);
+ rc = trans_pgd_idmap_page(&trans_info, &trans_ttbr0, &t0sz, page,
+ PAGE_KERNEL_ROX);
if (rc)
return rc;
diff --git a/arch/arm64/kernel/machine_kexec.c b/arch/arm64/kernel/machine_kexec.c
index b38aae5b488d..de4e9e0ad682 100644
--- a/arch/arm64/kernel/machine_kexec.c
+++ b/arch/arm64/kernel/machine_kexec.c
@@ -141,8 +141,8 @@ int machine_kexec_post_load(struct kimage *kimage)
reloc_size = __relocate_new_kernel_end - __relocate_new_kernel_start;
memcpy(reloc_code, __relocate_new_kernel_start, reloc_size);
kimage->arch.kern_reloc = __pa(reloc_code);
- rc = trans_pgd_idmap_page(&info, &kimage->arch.ttbr0,
- &kimage->arch.t0sz, reloc_code);
+ rc = trans_pgd_idmap_page(&info, &kimage->arch.ttbr0, &kimage->arch.t0sz,
+ reloc_code, PAGE_KERNEL_EXEC);
if (rc)
return rc;
kimage->arch.phys_offset = virt_to_phys(kimage) - (long)kimage;
diff --git a/arch/arm64/mm/trans_pgd.c b/arch/arm64/mm/trans_pgd.c
index 7b14df3c6477..4dfe6a9f9a8b 100644
--- a/arch/arm64/mm/trans_pgd.c
+++ b/arch/arm64/mm/trans_pgd.c
@@ -230,7 +230,7 @@ int trans_pgd_create_copy(struct trans_pgd_info *info, pgd_t **dst_pgdp,
* maximum T0SZ for this page.
*/
int trans_pgd_idmap_page(struct trans_pgd_info *info, phys_addr_t *trans_ttbr0,
- unsigned long *t0sz, void *page)
+ unsigned long *t0sz, void *page, pgprot_t prot)
{
phys_addr_t dst_addr = virt_to_phys(page);
unsigned long pfn = __phys_to_pfn(dst_addr);
@@ -240,7 +240,7 @@ int trans_pgd_idmap_page(struct trans_pgd_info *info, phys_addr_t *trans_ttbr0,
int this_level, index, level_lsb, level_msb;
dst_addr &= PAGE_MASK;
- prev_level_entry = pte_val(pfn_pte(pfn, PAGE_KERNEL_ROX));
+ prev_level_entry = pte_val(pfn_pte(pfn, prot));
for (this_level = 3; this_level >= 0; this_level--) {
levels[this_level] = trans_alloc(info);
--
2.41.0
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply related
* [PATCH 1/4] arm64: relocate: Let __relocate_new_kernel_start align on SZ_4K
From: Pingfan Liu @ 2024-03-28 11:56 UTC (permalink / raw)
To: linux-arm-kernel
Cc: Pingfan Liu, Catalin Marinas, Will Deacon, Ard Biesheuvel,
Kees Cook, Mark Rutland, Pasha Tatashin
In-Reply-To: <20240328115656.24090-1-piliu@redhat.com>
For upcoming C implement, let this section align on SZ_4K, so that
it makes potential instruction pairs 'adrp, add' work.
Signed-off-by: Pingfan Liu <piliu@redhat.com>
Cc: Catalin Marinas <catalin.marinas@arm.com>
Cc: Will Deacon <will@kernel.org>
Cc: Ard Biesheuvel <ardb@kernel.org>
Cc: Kees Cook <keescook@chromium.org>
Cc: Mark Rutland <mark.rutland@arm.com>
Cc: Pasha Tatashin <pasha.tatashin@soleen.com>
To: linux-arm-kernel@lists.infradead.org
---
arch/arm64/kernel/vmlinux.lds.S | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/arch/arm64/kernel/vmlinux.lds.S b/arch/arm64/kernel/vmlinux.lds.S
index 3cd7e76cc562..51eb382ab3a4 100644
--- a/arch/arm64/kernel/vmlinux.lds.S
+++ b/arch/arm64/kernel/vmlinux.lds.S
@@ -103,7 +103,7 @@ jiffies = jiffies_64;
#ifdef CONFIG_KEXEC_CORE
#define KEXEC_TEXT \
- ALIGN_FUNCTION(); \
+ . = ALIGN(SZ_4K); \
__relocate_new_kernel_start = .; \
*(.kexec_relocate.text) \
__relocate_new_kernel_end = .;
--
2.41.0
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply related
* [PATCH 3/4] arm64: kexec: Introduce d_size to carry cacheline size information
From: Pingfan Liu @ 2024-03-28 11:56 UTC (permalink / raw)
To: linux-arm-kernel
Cc: Pingfan Liu, Catalin Marinas, Will Deacon, Ard Biesheuvel,
Kees Cook, Mark Rutland, Pasha Tatashin
In-Reply-To: <20240328115656.24090-1-piliu@redhat.com>
Introducing kimage_arch.d_size to carry the data cacheline size
information, so that the relocate_kernel C routine can be implemented
simpler. The cache size info will be used in the next patch
Signed-off-by: Pingfan Liu <piliu@redhat.com>
Cc: Catalin Marinas <catalin.marinas@arm.com>
Cc: Will Deacon <will@kernel.org>
Cc: Ard Biesheuvel <ardb@kernel.org>
Cc: Kees Cook <keescook@chromium.org>
Cc: Mark Rutland <mark.rutland@arm.com>
Cc: Pasha Tatashin <pasha.tatashin@soleen.com>
To: linux-arm-kernel@lists.infradead.org
---
arch/arm64/include/asm/kexec.h | 1 +
arch/arm64/kernel/machine_kexec.c | 3 +++
2 files changed, 4 insertions(+)
diff --git a/arch/arm64/include/asm/kexec.h b/arch/arm64/include/asm/kexec.h
index 9ac9572a3bbe..882d00786f92 100644
--- a/arch/arm64/include/asm/kexec.h
+++ b/arch/arm64/include/asm/kexec.h
@@ -116,6 +116,7 @@ struct kimage_arch {
phys_addr_t zero_page;
unsigned long phys_offset;
unsigned long t0sz;
+ unsigned long d_size;
};
#ifdef CONFIG_KEXEC_FILE
diff --git a/arch/arm64/kernel/machine_kexec.c b/arch/arm64/kernel/machine_kexec.c
index de4e9e0ad682..b4ae24dcac8c 100644
--- a/arch/arm64/kernel/machine_kexec.c
+++ b/arch/arm64/kernel/machine_kexec.c
@@ -146,6 +146,9 @@ int machine_kexec_post_load(struct kimage *kimage)
if (rc)
return rc;
kimage->arch.phys_offset = virt_to_phys(kimage) - (long)kimage;
+ kimage->arch.d_size = 4 << cpuid_feature_extract_unsigned_field(
+ arm64_ftr_reg_ctrel0.sys_val,
+ CTR_EL0_DminLine_SHIFT);
/* Flush the reloc_code in preparation for its execution. */
dcache_clean_inval_poc((unsigned long)reloc_code,
--
2.41.0
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply related
* [PATCH 4/4] arm64: kexec: Change relocate_kernel to C code
From: Pingfan Liu @ 2024-03-28 11:56 UTC (permalink / raw)
To: linux-arm-kernel
Cc: Pingfan Liu, Catalin Marinas, Will Deacon, Ard Biesheuvel,
Kees Cook, Mark Rutland, Pasha Tatashin
In-Reply-To: <20240328115656.24090-1-piliu@redhat.com>
The kexec_relocate.o is a self-contained section, and it should be PIE.
Beside that, C function call requires stack, which is built on the idmap
of the rear of kimage->control_code_page.
Signed-off-by: Pingfan Liu <piliu@redhat.com>
Cc: Catalin Marinas <catalin.marinas@arm.com>
Cc: Will Deacon <will@kernel.org>
Cc: Ard Biesheuvel <ardb@kernel.org>
Cc: Kees Cook <keescook@chromium.org>
Cc: Mark Rutland <mark.rutland@arm.com>
Cc: Pasha Tatashin <pasha.tatashin@soleen.com>
To: linux-arm-kernel@lists.infradead.org
---
arch/arm64/kernel/Makefile | 1 +
arch/arm64/kernel/asm-offsets.c | 10 --
arch/arm64/kernel/machine_kexec.c | 9 +-
arch/arm64/kernel/relocate_kernel.S | 100 --------------
arch/arm64/kernel/relocate_kernel.c | 197 ++++++++++++++++++++++++++++
arch/arm64/kernel/vmlinux.lds.S | 1 +
6 files changed, 206 insertions(+), 112 deletions(-)
delete mode 100644 arch/arm64/kernel/relocate_kernel.S
create mode 100644 arch/arm64/kernel/relocate_kernel.c
diff --git a/arch/arm64/kernel/Makefile b/arch/arm64/kernel/Makefile
index 467cb7117273..5fc539c6d094 100644
--- a/arch/arm64/kernel/Makefile
+++ b/arch/arm64/kernel/Makefile
@@ -13,6 +13,7 @@ CFLAGS_REMOVE_return_address.o = $(CC_FLAGS_FTRACE)
# checks due to randomize_kstack_offset.
CFLAGS_REMOVE_syscall.o = -fstack-protector -fstack-protector-strong
CFLAGS_syscall.o += -fno-stack-protector
+CFLAGS_relocate_kernel.o += -fPIE
# When KASAN is enabled, a stack trace is recorded for every alloc/free, which
# can significantly impact performance. Avoid instrumenting the stack trace
diff --git a/arch/arm64/kernel/asm-offsets.c b/arch/arm64/kernel/asm-offsets.c
index 5a7dbbe0ce63..ce3f3bed76a4 100644
--- a/arch/arm64/kernel/asm-offsets.c
+++ b/arch/arm64/kernel/asm-offsets.c
@@ -186,16 +186,6 @@ int main(void)
#endif
BLANK();
#endif
-#ifdef CONFIG_KEXEC_CORE
- DEFINE(KIMAGE_ARCH_DTB_MEM, offsetof(struct kimage, arch.dtb_mem));
- DEFINE(KIMAGE_ARCH_EL2_VECTORS, offsetof(struct kimage, arch.el2_vectors));
- DEFINE(KIMAGE_ARCH_ZERO_PAGE, offsetof(struct kimage, arch.zero_page));
- DEFINE(KIMAGE_ARCH_PHYS_OFFSET, offsetof(struct kimage, arch.phys_offset));
- DEFINE(KIMAGE_ARCH_TTBR1, offsetof(struct kimage, arch.ttbr1));
- DEFINE(KIMAGE_HEAD, offsetof(struct kimage, head));
- DEFINE(KIMAGE_START, offsetof(struct kimage, start));
- BLANK();
-#endif
#ifdef CONFIG_FUNCTION_TRACER
DEFINE(FTRACE_OPS_FUNC, offsetof(struct ftrace_ops, func));
#endif
diff --git a/arch/arm64/kernel/machine_kexec.c b/arch/arm64/kernel/machine_kexec.c
index b4ae24dcac8c..31d96655664b 100644
--- a/arch/arm64/kernel/machine_kexec.c
+++ b/arch/arm64/kernel/machine_kexec.c
@@ -198,13 +198,18 @@ void machine_kexec(struct kimage *kimage)
restart(is_hyp_nvhe(), kimage->start, kimage->arch.dtb_mem,
0, 0);
} else {
- void (*kernel_reloc)(struct kimage *kimage);
+ void (*kernel_reloc)(struct kimage *kimage, unsigned long sp);
+ u64 new_sp = (u64)(page_to_pfn(kimage->control_code_page) << PAGE_SHIFT)
+ + KEXEC_CONTROL_PAGE_SIZE;
if (is_hyp_nvhe())
__hyp_set_vectors(kimage->arch.el2_vectors);
cpu_install_ttbr0(kimage->arch.ttbr0, kimage->arch.t0sz);
kernel_reloc = (void *)kimage->arch.kern_reloc;
- kernel_reloc(kimage);
+ pr_info("jump to relocation at: 0x%llx, with sp:0x%llx\n",
+ (u64)kernel_reloc, new_sp);
+ /* new_sp is accessible through idmap */
+ kernel_reloc(kimage, new_sp);
}
BUG(); /* Should never get here. */
diff --git a/arch/arm64/kernel/relocate_kernel.S b/arch/arm64/kernel/relocate_kernel.S
deleted file mode 100644
index 413f899e4ac6..000000000000
--- a/arch/arm64/kernel/relocate_kernel.S
+++ /dev/null
@@ -1,100 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0-only */
-/*
- * kexec for arm64
- *
- * Copyright (C) Linaro.
- * Copyright (C) Huawei Futurewei Technologies.
- * Copyright (C) 2021, Microsoft Corporation.
- * Pasha Tatashin <pasha.tatashin@soleen.com>
- */
-
-#include <linux/kexec.h>
-#include <linux/linkage.h>
-
-#include <asm/assembler.h>
-#include <asm/kexec.h>
-#include <asm/page.h>
-#include <asm/sysreg.h>
-#include <asm/virt.h>
-
-.macro turn_off_mmu tmp1, tmp2
- mov_q \tmp1, INIT_SCTLR_EL1_MMU_OFF
- pre_disable_mmu_workaround
- msr sctlr_el1, \tmp1
- isb
-.endm
-
-.section ".kexec_relocate.text", "ax"
-/*
- * arm64_relocate_new_kernel - Put a 2nd stage image in place and boot it.
- *
- * The memory that the old kernel occupies may be overwritten when copying the
- * new image to its final location. To assure that the
- * arm64_relocate_new_kernel routine which does that copy is not overwritten,
- * all code and data needed by arm64_relocate_new_kernel must be between the
- * symbols arm64_relocate_new_kernel and arm64_relocate_new_kernel_end. The
- * machine_kexec() routine will copy arm64_relocate_new_kernel to the kexec
- * safe memory that has been set up to be preserved during the copy operation.
- */
-SYM_CODE_START(arm64_relocate_new_kernel)
- /*
- * The kimage structure isn't allocated specially and may be clobbered
- * during relocation. We must load any values we need from it prior to
- * any relocation occurring.
- */
- ldr x28, [x0, #KIMAGE_START]
- ldr x27, [x0, #KIMAGE_ARCH_EL2_VECTORS]
- ldr x26, [x0, #KIMAGE_ARCH_DTB_MEM]
-
- /* Setup the list loop variables. */
- ldr x18, [x0, #KIMAGE_ARCH_ZERO_PAGE] /* x18 = zero page for BBM */
- ldr x17, [x0, #KIMAGE_ARCH_TTBR1] /* x17 = linear map copy */
- ldr x16, [x0, #KIMAGE_HEAD] /* x16 = kimage_head */
- ldr x22, [x0, #KIMAGE_ARCH_PHYS_OFFSET] /* x22 phys_offset */
- raw_dcache_line_size x15, x1 /* x15 = dcache line size */
- break_before_make_ttbr_switch x18, x17, x1, x2 /* set linear map */
-.Lloop:
- and x12, x16, PAGE_MASK /* x12 = addr */
- sub x12, x12, x22 /* Convert x12 to virt */
- /* Test the entry flags. */
-.Ltest_source:
- tbz x16, IND_SOURCE_BIT, .Ltest_indirection
-
- /* Invalidate dest page to PoC. */
- mov x19, x13
- copy_page x13, x12, x1, x2, x3, x4, x5, x6, x7, x8
- add x1, x19, #PAGE_SIZE
- dcache_by_myline_op civac, sy, x19, x1, x15, x20
- b .Lnext
-.Ltest_indirection:
- tbz x16, IND_INDIRECTION_BIT, .Ltest_destination
- mov x14, x12 /* ptr = addr */
- b .Lnext
-.Ltest_destination:
- tbz x16, IND_DESTINATION_BIT, .Lnext
- mov x13, x12 /* dest = addr */
-.Lnext:
- ldr x16, [x14], #8 /* entry = *ptr++ */
- tbz x16, IND_DONE_BIT, .Lloop /* while (!(entry & DONE)) */
- /* wait for writes from copy_page to finish */
- dsb nsh
- ic iallu
- dsb nsh
- isb
- turn_off_mmu x12, x13
-
- /* Start new image. */
- cbz x27, .Lel1
- mov x1, x28 /* kernel entry point */
- mov x2, x26 /* dtb address */
- mov x3, xzr
- mov x4, xzr
- mov x0, #HVC_SOFT_RESTART
- hvc #0 /* Jumps from el2 */
-.Lel1:
- mov x0, x26 /* dtb address */
- mov x1, xzr
- mov x2, xzr
- mov x3, xzr
- br x28 /* Jumps from el1 */
-SYM_CODE_END(arm64_relocate_new_kernel)
diff --git a/arch/arm64/kernel/relocate_kernel.c b/arch/arm64/kernel/relocate_kernel.c
new file mode 100644
index 000000000000..348515a0f497
--- /dev/null
+++ b/arch/arm64/kernel/relocate_kernel.c
@@ -0,0 +1,197 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * kexec for arm64
+ *
+ * Copyright (C) Linaro.
+ * Copyright (C) Huawei Futurewei Technologies.
+ * Copyright (C) 2021, Microsoft Corporation.
+ * Pasha Tatashin <pasha.tatashin@soleen.com>
+ * Copyright (C) 2024, Red Hat, Inc.
+ */
+
+#include <linux/kconfig.h>
+#include <linux/kexec.h>
+#include <linux/compiler_types.h>
+
+#include <asm/pgtable-hwdef.h>
+#include <asm/cpufeature.h>
+#include <asm/kexec.h>
+#include <asm/page.h>
+#include <asm/sysreg.h>
+#include <asm/virt.h>
+
+#define __kexec_section __noinstr_section(".kexec_relocate.text")
+#define __kexec_entry_section __noinstr_section(".kexec_relocate.entry.text")
+
+static u64 __kexec_section offset_ttbr1(u64 ttbr)
+{
+#ifdef CONFIG_ARM64_VA_BITS_52
+ u64 tmp;
+
+ tmp = read_sysreg_s(SYS_ID_AA64MMFR2_EL1);
+ tmp &= (0xf << ID_AA64MMFR2_EL1_VARange_SHIFT);
+ if (!tmp)
+ ttbr |= TTBR1_BADDR_4852_OFFSET;
+#endif
+ return ttbr;
+}
+
+void __kexec_section make_ttbr1_switch(phys_addr_t zero_page,
+ phys_addr_t pgtable)
+{
+ unsigned long zero_ttbr;
+ unsigned long pgtable_ttbr;
+
+ zero_ttbr = phys_to_ttbr(zero_page);
+ pgtable_ttbr = phys_to_ttbr(pgtable);
+ pgtable_ttbr = offset_ttbr1(pgtable_ttbr);
+
+ write_sysreg(zero_ttbr, ttbr1_el1);
+ isb();
+ __tlbi(vmalle1);
+ dsb(nsh);
+
+ write_sysreg(pgtable_ttbr, ttbr1_el1);
+ isb();
+}
+
+static void __kexec_section sync(void)
+{
+ dsb(nsh);
+ asm volatile("ic iallu");
+ dsb(nsh);
+ isb();
+}
+
+static void __kexec_section turn_mmu_off(void)
+{
+ u64 tmp = INIT_SCTLR_EL1_MMU_OFF;
+
+ /* pre_disable_mmu_workaround */
+#ifdef CONFIG_QCOM_FALKOR_ERRATUM_E1041
+ isb();
+#endif
+ write_sysreg(tmp, sctlr_el1);
+ isb();
+}
+
+/* The parameter lays out according to the hvc call */
+static void __kexec_section hvc_call(unsigned long vector, unsigned long entry,
+ unsigned long dtb, unsigned long x3, unsigned long x4)
+{
+ asm volatile("hvc #0");
+}
+
+typedef void (*kernel_entry)(u64 dtb, u64 x1, u64 x2, u64 x3);
+
+static __always_inline void relocate_copy_page(void *dst, void *src)
+{
+ int i = PAGE_SIZE >> 3;
+ unsigned long *s, *d;
+
+ s = (unsigned long *)src;
+ d = (unsigned long *)dst;
+ for (int j = 0; j < i; j++, d++, s++)
+ *d = *s;
+}
+
+/* Borrowed from clean_dcache_range_nopatch() in arch/arm64/kernel/alternative.c */
+static __always_inline void clean_dcache_range(u64 d_size, u64 start, u64 end)
+{
+ u64 cur;
+
+ cur = start & ~(d_size - 1);
+ do {
+ /*
+ * We must clean+invalidate to the PoC in order to avoid
+ * Cortex-A53 errata 826319, 827319, 824069 and 819472
+ * (this corresponds to ARM64_WORKAROUND_CLEAN_CACHE)
+ */
+ asm volatile("dc civac, %0" : : "r" (cur) : "memory");
+ } while (cur += d_size, cur < end);
+}
+
+void __kexec_section __arm64_relocate_new_kernel(struct kimage *kimage)
+{
+ phys_addr_t dtb, el2_vectors, zero_page, ttbr1;
+ u64 start, phys_offset, ctr_el0, d_size;
+ kimage_entry_t *ptr, entry;
+ char *src, *dst;
+
+ zero_page = kimage->arch.zero_page;
+ ttbr1 = kimage->arch.ttbr1;
+ start = kimage->start;
+ dtb = kimage->arch.dtb_mem;
+ el2_vectors = kimage->arch.el2_vectors;
+ phys_offset = kimage->arch.phys_offset;
+ d_size = kimage->arch.d_size;
+
+ make_ttbr1_switch(zero_page, ttbr1);
+
+ /* kimage->head is fetched once */
+ for (ptr = &kimage->head; (entry = *ptr) && !(entry & IND_DONE);
+ ptr = (entry & IND_INDIRECTION) ?
+ (void *)((entry & PAGE_MASK) - phys_offset) : ptr + 1) {
+
+ if (entry & IND_INDIRECTION)
+ continue;
+ else if (entry & IND_DESTINATION)
+ dst = (char *)((entry & PAGE_MASK) - phys_offset);
+ else if (entry & IND_SOURCE) {
+ src = (char *)((entry & PAGE_MASK) - phys_offset);
+ relocate_copy_page(dst, src);
+ /* Force all cache line in page to PoC */
+ clean_dcache_range(d_size, (u64)dst, (u64)dst + PAGE_SIZE);
+ dst += PAGE_SIZE;
+ }
+
+ }
+ /* wait for writes from copy_page to finish */
+ sync();
+ turn_mmu_off();
+
+ if (!el2_vectors) {
+ kernel_entry entry = (kernel_entry)start;
+
+ entry(dtb, 0, 0, 0);
+ } else {
+ /* Jumps from el2 */
+ hvc_call(HVC_SOFT_RESTART, start, dtb, 0, 0);
+ }
+
+}
+
+extern void __arm64_relocate_new_kernel(struct kimage *image);
+
+/*
+ * arm64_relocate_new_kernel - Put a 2nd stage image in place and boot it.
+ *
+ * The memory that the old kernel occupies may be overwritten when copying the
+ * new image to its final location. To assure that the
+ * arm64_relocate_new_kernel routine which does that copy is not overwritten,
+ * all code and data needed by arm64_relocate_new_kernel must be between the
+ * symbols arm64_relocate_new_kernel and arm64_relocate_new_kernel_end. The
+ * machine_kexec() routine will copy arm64_relocate_new_kernel to the kexec
+ * safe memory that has been set up to be preserved during the copy operation.
+ *
+ * Come here through ttbr0, and ttbr1 still takes effect.
+ */
+void __kexec_entry_section arm64_relocate_new_kernel(
+ struct kimage *kimage, unsigned long new_sp)
+{
+ /*
+ * From now on, no local variable so the new sp can be safely prepared.
+ * The new stack should be on the control page which is safe during copying
+ */
+ asm volatile(
+ "mov sp, %0;"
+ "mov x0, %1;"
+ "adrp x2, __arm64_relocate_new_kernel;"
+ "add x2, x2, #:lo12:__arm64_relocate_new_kernel;"
+ "br x2;"
+ :
+ : "r" (new_sp), "r" (kimage)
+ :
+ );
+ /* never return */
+}
diff --git a/arch/arm64/kernel/vmlinux.lds.S b/arch/arm64/kernel/vmlinux.lds.S
index 51eb382ab3a4..b6781667783c 100644
--- a/arch/arm64/kernel/vmlinux.lds.S
+++ b/arch/arm64/kernel/vmlinux.lds.S
@@ -105,6 +105,7 @@ jiffies = jiffies_64;
#define KEXEC_TEXT \
. = ALIGN(SZ_4K); \
__relocate_new_kernel_start = .; \
+ *(.kexec_relocate.entry.text) \
*(.kexec_relocate.text) \
__relocate_new_kernel_end = .;
#else
--
2.41.0
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply related
* [PATCH v3 1/2] dt-bindings: arm: sunxi: Add PocketBook 614 Plus
From: Denis Burkov @ 2024-03-28 12:29 UTC (permalink / raw)
To: Rob Herring, Krzysztof Kozlowski, Conor Dooley, Chen-Yu Tsai,
Jernej Skrabec, Samuel Holland, Maxime Ripard, devicetree,
linux-arm-kernel, linux-sunxi, linux-kernel
Cc: Denis Burkov, Rob Herring
Add a new board name.
Signed-off-by: Denis Burkov <hitechshell@mail.ru>
Acked-by: Rob Herring <robh@kernel.org>
---
Documentation/devicetree/bindings/arm/sunxi.yaml | 5 +++++
1 file changed, 5 insertions(+)
diff --git a/Documentation/devicetree/bindings/arm/sunxi.yaml b/Documentation/devicetree/bindings/arm/sunxi.yaml
index 09d835db6db5..43491e7f8a5e 100644
--- a/Documentation/devicetree/bindings/arm/sunxi.yaml
+++ b/Documentation/devicetree/bindings/arm/sunxi.yaml
@@ -774,6 +774,11 @@ properties:
- const: pocketbook,touch-lux-3
- const: allwinner,sun5i-a13
+ - description: PocketBook 614 Plus
+ items:
+ - const: pocketbook,614-plus
+ - const: allwinner,sun5i-a13
+
- description: Point of View Protab2-IPS9
items:
- const: pov,protab2-ips9
--
2.43.2
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply related
* [PATCH v3 2/2] ARM: dts: sun5i: Add PocketBook 614 Plus support
From: Denis Burkov @ 2024-03-28 12:29 UTC (permalink / raw)
To: Rob Herring, Krzysztof Kozlowski, Conor Dooley, Chen-Yu Tsai,
Jernej Skrabec, Samuel Holland, Maxime Ripard, devicetree,
linux-arm-kernel, linux-sunxi, linux-kernel
Cc: Denis Burkov
In-Reply-To: <20240328122922.13796-1-hitechshell@mail.ru>
What works:
- Serial console
- mmc0, mmc2 (both microSD card slots on the board)
- All buttons (gpio and lradc based)
- Power LED
- PMIC
- RTC
- USB OTG/gadgets mode
Signed-off-by: Denis Burkov <hitechshell@mail.ru>
---
arch/arm/boot/dts/allwinner/Makefile | 1 +
.../sun5i-a13-pocketbook-614-plus.dts | 218 ++++++++++++++++++
2 files changed, 219 insertions(+)
create mode 100644 arch/arm/boot/dts/allwinner/sun5i-a13-pocketbook-614-plus.dts
diff --git a/arch/arm/boot/dts/allwinner/Makefile b/arch/arm/boot/dts/allwinner/Makefile
index 5fbb44ddacd0..6209243ad975 100644
--- a/arch/arm/boot/dts/allwinner/Makefile
+++ b/arch/arm/boot/dts/allwinner/Makefile
@@ -61,6 +61,7 @@ dtb-$(CONFIG_MACH_SUN5I) += \
sun5i-a13-olinuxino.dtb \
sun5i-a13-olinuxino-micro.dtb \
sun5i-a13-pocketbook-touch-lux-3.dtb \
+ sun5i-a13-pocketbook-614-plus.dtb \
sun5i-a13-q8-tablet.dtb \
sun5i-a13-utoo-p66.dtb \
sun5i-gr8-chip-pro.dtb \
diff --git a/arch/arm/boot/dts/allwinner/sun5i-a13-pocketbook-614-plus.dts b/arch/arm/boot/dts/allwinner/sun5i-a13-pocketbook-614-plus.dts
new file mode 100644
index 000000000000..ab8d138dc11d
--- /dev/null
+++ b/arch/arm/boot/dts/allwinner/sun5i-a13-pocketbook-614-plus.dts
@@ -0,0 +1,218 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright 2024 Denis Burkov <hitechshell@mail.ru>
+ */
+
+/dts-v1/;
+#include "sun5i-a13.dtsi"
+#include "sunxi-common-regulators.dtsi"
+
+#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/input/input.h>
+#include <dt-bindings/interrupt-controller/irq.h>
+#include <dt-bindings/leds/common.h>
+
+/ {
+ model = "PocketBook 614 Plus";
+ compatible = "pocketbook,614-plus", "allwinner,sun5i-a13";
+
+ aliases {
+ serial0 = &uart1;
+ };
+
+ chosen {
+ stdout-path = "serial0:115200n8";
+ };
+
+ leds {
+ compatible = "gpio-leds";
+
+ led-0 {
+ color = <LED_COLOR_ID_WHITE>;
+ function = LED_FUNCTION_POWER;
+ linux,default-trigger = "default-on";
+ gpios = <&pio 4 8 GPIO_ACTIVE_LOW>; /* PE8 */
+ };
+ };
+
+ gpio-keys {
+ compatible = "gpio-keys";
+
+ key-0 {
+ label = "Right";
+ linux,code = <KEY_NEXT>;
+ gpios = <&pio 6 9 GPIO_ACTIVE_LOW>; /* PG9 */
+ };
+
+ key-1 {
+ label = "Left";
+ linux,code = <KEY_PREVIOUS>;
+ gpios = <&pio 6 10 GPIO_ACTIVE_LOW>; /* PG10 */
+ };
+ };
+
+ reg_3v3_mmc0: regulator-mmc0 {
+ compatible = "regulator-fixed";
+ regulator-name = "vdd-mmc0";
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ gpio = <&pio 4 4 GPIO_ACTIVE_LOW>; /* PE4 */
+ vin-supply = <®_vcc3v3>;
+ };
+};
+
+&cpu0 {
+ cpu-supply = <®_dcdc2>;
+};
+
+&ehci0 {
+ status = "okay";
+};
+
+&i2c0 {
+ status = "okay";
+
+ axp209: pmic@34 {
+ compatible = "x-powers,axp209";
+ reg = <0x34>;
+ interrupts = <0>;
+ };
+};
+
+#include "axp209.dtsi"
+
+&i2c1 {
+ status = "okay";
+
+ pcf8563: rtc@51 {
+ compatible = "nxp,pcf8563";
+ reg = <0x51>;
+ #clock-cells = <0>;
+ };
+};
+
+&lradc {
+ vref-supply = <®_ldo2>;
+ status = "okay";
+
+ button-300 {
+ label = "Down";
+ linux,code = <KEY_DOWN>;
+ channel = <0>;
+ voltage = <300000>;
+ };
+
+ button-700 {
+ label = "Up";
+ linux,code = <KEY_UP>;
+ channel = <0>;
+ voltage = <700000>;
+ };
+
+ button-1000 {
+ label = "Left";
+ linux,code = <KEY_LEFT>;
+ channel = <0>;
+ voltage = <1000000>;
+ };
+
+ button-1200 {
+ label = "Menu";
+ linux,code = <KEY_MENU>;
+ channel = <0>;
+ voltage = <1200000>;
+ };
+
+ button-1500 {
+ label = "Right";
+ linux,code = <KEY_RIGHT>;
+ channel = <0>;
+ voltage = <1500000>;
+ };
+};
+
+&mmc0 {
+ vmmc-supply = <®_3v3_mmc0>;
+ bus-width = <4>;
+ cd-gpios = <&pio 6 0 GPIO_ACTIVE_LOW>; /* PG0 */
+ status = "okay";
+};
+
+&mmc2 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&mmc2_4bit_pc_pins>;
+ vmmc-supply = <®_vcc3v3>;
+ bus-width = <4>;
+ non-removable;
+ status = "okay";
+};
+
+&ohci0 {
+ status = "okay";
+};
+
+&otg_sram {
+ status = "okay";
+};
+
+®_dcdc2 {
+ regulator-always-on;
+ regulator-min-microvolt = <1000000>;
+ regulator-max-microvolt = <1500000>;
+ regulator-name = "vdd-cpu";
+};
+
+®_dcdc3 {
+ regulator-always-on;
+ regulator-min-microvolt = <1000000>;
+ regulator-max-microvolt = <1400000>;
+ regulator-name = "vdd-int-dll";
+};
+
+®_ldo1 {
+ regulator-name = "vdd-rtc";
+};
+
+®_ldo2 {
+ regulator-always-on;
+ regulator-min-microvolt = <3000000>;
+ regulator-max-microvolt = <3000000>;
+ regulator-name = "avcc";
+};
+
+®_usb0_vbus {
+ status = "okay";
+ gpio = <&pio 6 12 GPIO_ACTIVE_HIGH>; /* PG12 */
+};
+
+®_usb1_vbus {
+ gpio = <&pio 6 11 GPIO_ACTIVE_HIGH>; /* PG11 */
+ status = "okay";
+};
+
+&uart1 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&uart1_pg_pins>;
+ status = "okay";
+};
+
+&usb_otg {
+ dr_mode = "otg";
+ status = "okay";
+};
+
+&usb_power_supply {
+ status = "okay";
+};
+
+&battery_power_supply {
+ status = "okay";
+};
+
+&usbphy {
+ usb0_id_det-gpios = <&pio 6 2 GPIO_ACTIVE_HIGH>; /* PG2 */
+ usb0_vbus_det-gpios = <&axp_gpio 1 GPIO_ACTIVE_HIGH>;
+ usb0_vbus-supply = <®_usb0_vbus>;
+ usb1_vbus-supply = <®_usb1_vbus>;
+ status = "okay";
+};
--
2.43.2
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply related
* [PATCH v3 1/3] clk: samsung: introduce nMUX for MUX clks that can reparented
From: Tudor Ambarus @ 2024-03-28 12:34 UTC (permalink / raw)
To: peter.griffin, krzysztof.kozlowski
Cc: alim.akhtar, linux-arm-kernel, linux-samsung-soc, linux-kernel,
andre.draszik, willmcvicker, kernel-team, s.nawrocki, cw00.choi,
mturquette, sboyd, semen.protsenko, linux-clk, jaewon02.kim,
Tudor Ambarus
In-Reply-To: <20240328123440.1387823-1-tudor.ambarus@linaro.org>
All samsung MUX clocks that are defined with MUX() set the
CLK_SET_RATE_NO_REPARENT flag in __MUX(), which prevents MUXes to be
reparented during clk_set_rate().
Introduce nMUX() for MUX clocks that can be reparented on clock rate
change. "nMUX" comes from "n-to-1 selector", hopefully emphasising that
the selector can change on clock rate changes. Ideally MUX/MUX_F()
should change to not have the CLK_SET_RATE_NO_REPARENT flag set by
default, and all their users to be updated to add the flag back
(like in the case of DIV and GATE). But this is a very intrusive change
and because for now only GS101 allows MUX reparenting on clock rate
change, stick with nMUX().
One user of nMUX() will be GS101. GS101 defines MUX clocks that
are dedicated for each instance of an IP (see MUX USI). The reparenting
of these MUX clocks will not affect other instances of the same IP or
different IPs altogether.
Signed-off-by: Tudor Ambarus <tudor.ambarus@linaro.org>
---
drivers/clk/samsung/clk.h | 11 +++++++++--
1 file changed, 9 insertions(+), 2 deletions(-)
diff --git a/drivers/clk/samsung/clk.h b/drivers/clk/samsung/clk.h
index a70bd7cce39f..fb06caa71f0a 100644
--- a/drivers/clk/samsung/clk.h
+++ b/drivers/clk/samsung/clk.h
@@ -133,7 +133,7 @@ struct samsung_mux_clock {
.name = cname, \
.parent_names = pnames, \
.num_parents = ARRAY_SIZE(pnames), \
- .flags = (f) | CLK_SET_RATE_NO_REPARENT, \
+ .flags = f, \
.offset = o, \
.shift = s, \
.width = w, \
@@ -141,9 +141,16 @@ struct samsung_mux_clock {
}
#define MUX(_id, cname, pnames, o, s, w) \
- __MUX(_id, cname, pnames, o, s, w, 0, 0)
+ __MUX(_id, cname, pnames, o, s, w, CLK_SET_RATE_NO_REPARENT, 0)
#define MUX_F(_id, cname, pnames, o, s, w, f, mf) \
+ __MUX(_id, cname, pnames, o, s, w, (f) | CLK_SET_RATE_NO_REPARENT, mf)
+
+/* Used by MUX clocks where reparenting on clock rate change is allowed. */
+#define nMUX(_id, cname, pnames, o, s, w) \
+ __MUX(_id, cname, pnames, o, s, w, 0, 0)
+
+#define nMUX_F(_id, cname, pnames, o, s, w, f, mf) \
__MUX(_id, cname, pnames, o, s, w, f, mf)
/**
--
2.44.0.396.g6e790dbe36-goog
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply related
* [PATCH v3 0/3] clk: samsung: introduce nMUX to reparent MUX clocks
From: Tudor Ambarus @ 2024-03-28 12:34 UTC (permalink / raw)
To: peter.griffin, krzysztof.kozlowski
Cc: alim.akhtar, linux-arm-kernel, linux-samsung-soc, linux-kernel,
andre.draszik, willmcvicker, kernel-team, s.nawrocki, cw00.choi,
mturquette, sboyd, semen.protsenko, linux-clk, jaewon02.kim,
Tudor Ambarus
v3:
- update first patch:
- remove __nMUX() as it duplicated __MUX() with an exception on flags.
- update commit message
- update comment and say that nMUX() shall be used where MUX reparenting
on clock rate chage is allowed
- collect R-b, A-b tags
v2:
- reword commit messages
- drop exynos850 patch on Sam's request
v1: https://lore.kernel.org/linux-samsung-soc/20240229122021.1901785-1-tudor.ambarus@linaro.org/
All samsung MUX clocks that are defined with MUX() set the
CLK_SET_RATE_NO_REPARENT flag in __MUX(), which prevents MUXes to be
reparented during clk_set_rate().
Introduce nMUX() for MUX clocks that can be reparented. nMUX is used
in GS101 to reparent the USI MUX to OSCCLK on low SPI clock rates.
Each instance of the USI IP in GS101 has its own MUX_USI clock, thus
the reparenting of a MUX_USI clock corresponds to a single instance
of the USI IP. We allow the reparenting of the MUX_USIx clocks to
OSCCLK. The datasheet mentions OSCCLK just in the low-power mode
context, but the downstream driver reparents too the MUX_USI clocks
to OSCCLK. Follow the downstream driver and do the same.
Tested with USI6 and USI13 SPI.
Find discussion on MUX reparenting to OSCCLK at:
https://lore.kernel.org/linux-samsung-soc/d508dfc1-bc28-4470-92aa-cf71915966f4@linaro.org/
Tudor Ambarus (3):
clk: samsung: introduce nMUX for MUX clks that can reparented
clk: samsung: gs101: propagate PERIC1 USI SPI clock rate
clk: samsung: gs101: propagate PERIC0 USI SPI clock rate
drivers/clk/samsung/clk-gs101.c | 225 +++++++++++++++++---------------
drivers/clk/samsung/clk.h | 11 +-
2 files changed, 129 insertions(+), 107 deletions(-)
--
2.44.0.396.g6e790dbe36-goog
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply
* [PATCH v3 2/3] clk: samsung: gs101: propagate PERIC1 USI SPI clock rate
From: Tudor Ambarus @ 2024-03-28 12:34 UTC (permalink / raw)
To: peter.griffin, krzysztof.kozlowski
Cc: alim.akhtar, linux-arm-kernel, linux-samsung-soc, linux-kernel,
andre.draszik, willmcvicker, kernel-team, s.nawrocki, cw00.choi,
mturquette, sboyd, semen.protsenko, linux-clk, jaewon02.kim,
Tudor Ambarus
In-Reply-To: <20240328123440.1387823-1-tudor.ambarus@linaro.org>
When SPI transfer is being prepared, the spi-s3c64xx driver will call
clk_set_rate() to change the rate of SPI source clock (IPCLK). But IPCLK
is a gate (leaf) clock, so it must propagate the rate change up the
clock tree, so that corresponding MUX/DIV clocks can actually change
their values. Add CLK_SET_RATE_PARENT flag to corresponding clocks for
all USI instances in GS101 PERIC1: USI{0, 9, 10, 11, 12, 13}. This change
involves the following clocks:
PERIC1 USI*:
Clock Div range MUX Selection
-------------------------------------------------------------------
gout_peric1_peric1_top0_ipclk_* - -
dout_peric1_usi*_usi /1..16 -
mout_peric1_usi*_usi_user - {24.5 MHz, 400 MHz}
With input clock of 400 MHz this scheme provides the following IPCLK
rate range, for each USI block:
PERIC1 USI*: 1.5 MHz ... 400 MHz
Accounting for internal /4 divider in SPI blocks, and because the max
SPI frequency is limited at 50 MHz, it gives us next SPI SCK rates:
PERIC1 USI_SPI*: 384 KHz ... 49.9 MHz
Which shall be fine for the applications of the SPI bus.
Note that with this we allow the reparenting of the MUX_USIx clocks to
OSCCLK. Each instance of the USI IP has its own MUX_USI clock, thus the
reparenting of a MUX_USI clock corresponds to a single instance of the
USI IP. The datasheet mentions OSCCLK just in the low-power mode
context, but the downstream driver reparents too the MUX_USI clocks to
OSCCLK. Follow the downstream driver and do the same.
Fixes: 63b4bd1259d9 ("clk: samsung: gs101: add support for cmu_peric1")
Reviewed-by: Peter Griffin <peter.griffin@linaro.org>
Acked-by: André Draszik <andre.draszik@linaro.org>
Signed-off-by: Tudor Ambarus <tudor.ambarus@linaro.org>
---
drivers/clk/samsung/clk-gs101.c | 90 ++++++++++++++++++---------------
1 file changed, 48 insertions(+), 42 deletions(-)
diff --git a/drivers/clk/samsung/clk-gs101.c b/drivers/clk/samsung/clk-gs101.c
index d065e343a85d..ddf2d57eed68 100644
--- a/drivers/clk/samsung/clk-gs101.c
+++ b/drivers/clk/samsung/clk-gs101.c
@@ -3230,47 +3230,53 @@ static const struct samsung_mux_clock peric1_mux_clks[] __initconst = {
MUX(CLK_MOUT_PERIC1_I3C_USER,
"mout_peric1_i3c_user", mout_peric1_nonbususer_p,
PLL_CON0_MUX_CLKCMU_PERIC1_I3C_USER, 4, 1),
- MUX(CLK_MOUT_PERIC1_USI0_USI_USER,
- "mout_peric1_usi0_usi_user", mout_peric1_nonbususer_p,
- PLL_CON0_MUX_CLKCMU_PERIC1_USI0_USI_USER, 4, 1),
- MUX(CLK_MOUT_PERIC1_USI10_USI_USER,
- "mout_peric1_usi10_usi_user", mout_peric1_nonbususer_p,
- PLL_CON0_MUX_CLKCMU_PERIC1_USI10_USI_USER, 4, 1),
- MUX(CLK_MOUT_PERIC1_USI11_USI_USER,
- "mout_peric1_usi11_usi_user", mout_peric1_nonbususer_p,
- PLL_CON0_MUX_CLKCMU_PERIC1_USI11_USI_USER, 4, 1),
- MUX(CLK_MOUT_PERIC1_USI12_USI_USER,
- "mout_peric1_usi12_usi_user", mout_peric1_nonbususer_p,
- PLL_CON0_MUX_CLKCMU_PERIC1_USI12_USI_USER, 4, 1),
- MUX(CLK_MOUT_PERIC1_USI13_USI_USER,
- "mout_peric1_usi13_usi_user", mout_peric1_nonbususer_p,
- PLL_CON0_MUX_CLKCMU_PERIC1_USI13_USI_USER, 4, 1),
- MUX(CLK_MOUT_PERIC1_USI9_USI_USER,
- "mout_peric1_usi9_usi_user", mout_peric1_nonbususer_p,
- PLL_CON0_MUX_CLKCMU_PERIC1_USI9_USI_USER, 4, 1),
+ nMUX(CLK_MOUT_PERIC1_USI0_USI_USER,
+ "mout_peric1_usi0_usi_user", mout_peric1_nonbususer_p,
+ PLL_CON0_MUX_CLKCMU_PERIC1_USI0_USI_USER, 4, 1),
+ nMUX(CLK_MOUT_PERIC1_USI10_USI_USER,
+ "mout_peric1_usi10_usi_user", mout_peric1_nonbususer_p,
+ PLL_CON0_MUX_CLKCMU_PERIC1_USI10_USI_USER, 4, 1),
+ nMUX(CLK_MOUT_PERIC1_USI11_USI_USER,
+ "mout_peric1_usi11_usi_user", mout_peric1_nonbususer_p,
+ PLL_CON0_MUX_CLKCMU_PERIC1_USI11_USI_USER, 4, 1),
+ nMUX(CLK_MOUT_PERIC1_USI12_USI_USER,
+ "mout_peric1_usi12_usi_user", mout_peric1_nonbususer_p,
+ PLL_CON0_MUX_CLKCMU_PERIC1_USI12_USI_USER, 4, 1),
+ nMUX(CLK_MOUT_PERIC1_USI13_USI_USER,
+ "mout_peric1_usi13_usi_user", mout_peric1_nonbususer_p,
+ PLL_CON0_MUX_CLKCMU_PERIC1_USI13_USI_USER, 4, 1),
+ nMUX(CLK_MOUT_PERIC1_USI9_USI_USER,
+ "mout_peric1_usi9_usi_user", mout_peric1_nonbususer_p,
+ PLL_CON0_MUX_CLKCMU_PERIC1_USI9_USI_USER, 4, 1),
};
static const struct samsung_div_clock peric1_div_clks[] __initconst = {
DIV(CLK_DOUT_PERIC1_I3C, "dout_peric1_i3c", "mout_peric1_i3c_user",
CLK_CON_DIV_DIV_CLK_PERIC1_I3C, 0, 4),
- DIV(CLK_DOUT_PERIC1_USI0_USI,
- "dout_peric1_usi0_usi", "mout_peric1_usi0_usi_user",
- CLK_CON_DIV_DIV_CLK_PERIC1_USI0_USI, 0, 4),
- DIV(CLK_DOUT_PERIC1_USI10_USI,
- "dout_peric1_usi10_usi", "mout_peric1_usi10_usi_user",
- CLK_CON_DIV_DIV_CLK_PERIC1_USI10_USI, 0, 4),
- DIV(CLK_DOUT_PERIC1_USI11_USI,
- "dout_peric1_usi11_usi", "mout_peric1_usi11_usi_user",
- CLK_CON_DIV_DIV_CLK_PERIC1_USI11_USI, 0, 4),
- DIV(CLK_DOUT_PERIC1_USI12_USI,
- "dout_peric1_usi12_usi", "mout_peric1_usi12_usi_user",
- CLK_CON_DIV_DIV_CLK_PERIC1_USI12_USI, 0, 4),
- DIV(CLK_DOUT_PERIC1_USI13_USI,
- "dout_peric1_usi13_usi", "mout_peric1_usi13_usi_user",
- CLK_CON_DIV_DIV_CLK_PERIC1_USI13_USI, 0, 4),
- DIV(CLK_DOUT_PERIC1_USI9_USI,
- "dout_peric1_usi9_usi", "mout_peric1_usi9_usi_user",
- CLK_CON_DIV_DIV_CLK_PERIC1_USI9_USI, 0, 4),
+ DIV_F(CLK_DOUT_PERIC1_USI0_USI,
+ "dout_peric1_usi0_usi", "mout_peric1_usi0_usi_user",
+ CLK_CON_DIV_DIV_CLK_PERIC1_USI0_USI, 0, 4,
+ CLK_SET_RATE_PARENT, 0),
+ DIV_F(CLK_DOUT_PERIC1_USI10_USI,
+ "dout_peric1_usi10_usi", "mout_peric1_usi10_usi_user",
+ CLK_CON_DIV_DIV_CLK_PERIC1_USI10_USI, 0, 4,
+ CLK_SET_RATE_PARENT, 0),
+ DIV_F(CLK_DOUT_PERIC1_USI11_USI,
+ "dout_peric1_usi11_usi", "mout_peric1_usi11_usi_user",
+ CLK_CON_DIV_DIV_CLK_PERIC1_USI11_USI, 0, 4,
+ CLK_SET_RATE_PARENT, 0),
+ DIV_F(CLK_DOUT_PERIC1_USI12_USI,
+ "dout_peric1_usi12_usi", "mout_peric1_usi12_usi_user",
+ CLK_CON_DIV_DIV_CLK_PERIC1_USI12_USI, 0, 4,
+ CLK_SET_RATE_PARENT, 0),
+ DIV_F(CLK_DOUT_PERIC1_USI13_USI,
+ "dout_peric1_usi13_usi", "mout_peric1_usi13_usi_user",
+ CLK_CON_DIV_DIV_CLK_PERIC1_USI13_USI, 0, 4,
+ CLK_SET_RATE_PARENT, 0),
+ DIV_F(CLK_DOUT_PERIC1_USI9_USI,
+ "dout_peric1_usi9_usi", "mout_peric1_usi9_usi_user",
+ CLK_CON_DIV_DIV_CLK_PERIC1_USI9_USI, 0, 4,
+ CLK_SET_RATE_PARENT, 0),
};
static const struct samsung_gate_clock peric1_gate_clks[] __initconst = {
@@ -3305,27 +3311,27 @@ static const struct samsung_gate_clock peric1_gate_clks[] __initconst = {
GATE(CLK_GOUT_PERIC1_PERIC1_TOP0_IPCLK_1,
"gout_peric1_peric1_top0_ipclk_1", "dout_peric1_usi0_usi",
CLK_CON_GAT_GOUT_BLK_PERIC1_UID_PERIC1_TOP0_IPCLKPORT_IPCLK_1,
- 21, 0, 0),
+ 21, CLK_SET_RATE_PARENT, 0),
GATE(CLK_GOUT_PERIC1_PERIC1_TOP0_IPCLK_2,
"gout_peric1_peric1_top0_ipclk_2", "dout_peric1_usi9_usi",
CLK_CON_GAT_GOUT_BLK_PERIC1_UID_PERIC1_TOP0_IPCLKPORT_IPCLK_2,
- 21, 0, 0),
+ 21, CLK_SET_RATE_PARENT, 0),
GATE(CLK_GOUT_PERIC1_PERIC1_TOP0_IPCLK_3,
"gout_peric1_peric1_top0_ipclk_3", "dout_peric1_usi10_usi",
CLK_CON_GAT_GOUT_BLK_PERIC1_UID_PERIC1_TOP0_IPCLKPORT_IPCLK_3,
- 21, 0, 0),
+ 21, CLK_SET_RATE_PARENT, 0),
GATE(CLK_GOUT_PERIC1_PERIC1_TOP0_IPCLK_4,
"gout_peric1_peric1_top0_ipclk_4", "dout_peric1_usi11_usi",
CLK_CON_GAT_GOUT_BLK_PERIC1_UID_PERIC1_TOP0_IPCLKPORT_IPCLK_4,
- 21, 0, 0),
+ 21, CLK_SET_RATE_PARENT, 0),
GATE(CLK_GOUT_PERIC1_PERIC1_TOP0_IPCLK_5,
"gout_peric1_peric1_top0_ipclk_5", "dout_peric1_usi12_usi",
CLK_CON_GAT_GOUT_BLK_PERIC1_UID_PERIC1_TOP0_IPCLKPORT_IPCLK_5,
- 21, 0, 0),
+ 21, CLK_SET_RATE_PARENT, 0),
GATE(CLK_GOUT_PERIC1_PERIC1_TOP0_IPCLK_6,
"gout_peric1_peric1_top0_ipclk_6", "dout_peric1_usi13_usi",
CLK_CON_GAT_GOUT_BLK_PERIC1_UID_PERIC1_TOP0_IPCLKPORT_IPCLK_6,
- 21, 0, 0),
+ 21, CLK_SET_RATE_PARENT, 0),
GATE(CLK_GOUT_PERIC1_PERIC1_TOP0_IPCLK_8,
"gout_peric1_peric1_top0_ipclk_8", "dout_peric1_i3c",
CLK_CON_GAT_GOUT_BLK_PERIC1_UID_PERIC1_TOP0_IPCLKPORT_IPCLK_8,
--
2.44.0.396.g6e790dbe36-goog
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply related
* [PATCH v3 3/3] clk: samsung: gs101: propagate PERIC0 USI SPI clock rate
From: Tudor Ambarus @ 2024-03-28 12:34 UTC (permalink / raw)
To: peter.griffin, krzysztof.kozlowski
Cc: alim.akhtar, linux-arm-kernel, linux-samsung-soc, linux-kernel,
andre.draszik, willmcvicker, kernel-team, s.nawrocki, cw00.choi,
mturquette, sboyd, semen.protsenko, linux-clk, jaewon02.kim,
Tudor Ambarus
In-Reply-To: <20240328123440.1387823-1-tudor.ambarus@linaro.org>
When SPI transfer is being prepared, the spi-s3c64xx driver will call
clk_set_rate() to change the rate of SPI source clock (IPCLK). But IPCLK
is a gate (leaf) clock, so it must propagate the rate change up the
clock tree, so that corresponding MUX/DIV clocks can actually change
their values. Add CLK_SET_RATE_PARENT flag to corresponding clocks for
all USI instances in GS101 PERIC0: USI{1-8, 14}. This change involves the
following clocks:
PERIC0 USI*:
Clock Div range MUX Selection
-------------------------------------------------------------------
gout_peric0_peric0_top0_ipclk_* - -
dout_peric0_usi*_usi /1..16 -
mout_peric0_usi*_usi_user - {24.5 MHz, 400 MHz}
With input clock of 400 MHz this scheme provides the following IPCLK
rate range, for each USI block:
PERIC0 USI*: 1.5 MHz ... 400 MHz
Accounting for internal /4 divider in SPI blocks, and because the max
SPI frequency is limited at 50 MHz, it gives us next SPI SCK rates:
PERIC0 USI_SPI*: 384 KHz ... 49.9 MHz
Which shall be fine for the applications of the SPI bus.
Note that with this we allow the reparenting of the MUX_USIx clocks to
OSCCLK. Each instance of the USI IP has its own MUX_USI clock, thus the
reparenting of a MUX_USI clock corresponds to a single instance of the
USI IP. The datasheet mentions OSCCLK just in the low-power mode
context, but the downstream driver reparents too the MUX_USI clocks to
OSCCLK. Follow the downstream driver and do the same.
Fixes: 893f133a040b ("clk: samsung: gs101: add support for cmu_peric0")
Reviewed-by: Peter Griffin <peter.griffin@linaro.org>
Acked-by: André Draszik <andre.draszik@linaro.org>
Signed-off-by: Tudor Ambarus <tudor.ambarus@linaro.org>
---
drivers/clk/samsung/clk-gs101.c | 135 +++++++++++++++++---------------
1 file changed, 72 insertions(+), 63 deletions(-)
diff --git a/drivers/clk/samsung/clk-gs101.c b/drivers/clk/samsung/clk-gs101.c
index ddf2d57eed68..bd3c1b02715b 100644
--- a/drivers/clk/samsung/clk-gs101.c
+++ b/drivers/clk/samsung/clk-gs101.c
@@ -2763,33 +2763,33 @@ static const struct samsung_mux_clock peric0_mux_clks[] __initconst = {
MUX(CLK_MOUT_PERIC0_USI0_UART_USER,
"mout_peric0_usi0_uart_user", mout_peric0_usi0_uart_user_p,
PLL_CON0_MUX_CLKCMU_PERIC0_USI0_UART_USER, 4, 1),
- MUX(CLK_MOUT_PERIC0_USI14_USI_USER,
- "mout_peric0_usi14_usi_user", mout_peric0_usi_usi_user_p,
- PLL_CON0_MUX_CLKCMU_PERIC0_USI14_USI_USER, 4, 1),
- MUX(CLK_MOUT_PERIC0_USI1_USI_USER,
- "mout_peric0_usi1_usi_user", mout_peric0_usi_usi_user_p,
- PLL_CON0_MUX_CLKCMU_PERIC0_USI1_USI_USER, 4, 1),
- MUX(CLK_MOUT_PERIC0_USI2_USI_USER,
- "mout_peric0_usi2_usi_user", mout_peric0_usi_usi_user_p,
- PLL_CON0_MUX_CLKCMU_PERIC0_USI2_USI_USER, 4, 1),
- MUX(CLK_MOUT_PERIC0_USI3_USI_USER,
- "mout_peric0_usi3_usi_user", mout_peric0_usi_usi_user_p,
- PLL_CON0_MUX_CLKCMU_PERIC0_USI3_USI_USER, 4, 1),
- MUX(CLK_MOUT_PERIC0_USI4_USI_USER,
- "mout_peric0_usi4_usi_user", mout_peric0_usi_usi_user_p,
- PLL_CON0_MUX_CLKCMU_PERIC0_USI4_USI_USER, 4, 1),
- MUX(CLK_MOUT_PERIC0_USI5_USI_USER,
- "mout_peric0_usi5_usi_user", mout_peric0_usi_usi_user_p,
- PLL_CON0_MUX_CLKCMU_PERIC0_USI5_USI_USER, 4, 1),
- MUX(CLK_MOUT_PERIC0_USI6_USI_USER,
- "mout_peric0_usi6_usi_user", mout_peric0_usi_usi_user_p,
- PLL_CON0_MUX_CLKCMU_PERIC0_USI6_USI_USER, 4, 1),
- MUX(CLK_MOUT_PERIC0_USI7_USI_USER,
- "mout_peric0_usi7_usi_user", mout_peric0_usi_usi_user_p,
- PLL_CON0_MUX_CLKCMU_PERIC0_USI7_USI_USER, 4, 1),
- MUX(CLK_MOUT_PERIC0_USI8_USI_USER,
- "mout_peric0_usi8_usi_user", mout_peric0_usi_usi_user_p,
- PLL_CON0_MUX_CLKCMU_PERIC0_USI8_USI_USER, 4, 1),
+ nMUX(CLK_MOUT_PERIC0_USI14_USI_USER,
+ "mout_peric0_usi14_usi_user", mout_peric0_usi_usi_user_p,
+ PLL_CON0_MUX_CLKCMU_PERIC0_USI14_USI_USER, 4, 1),
+ nMUX(CLK_MOUT_PERIC0_USI1_USI_USER,
+ "mout_peric0_usi1_usi_user", mout_peric0_usi_usi_user_p,
+ PLL_CON0_MUX_CLKCMU_PERIC0_USI1_USI_USER, 4, 1),
+ nMUX(CLK_MOUT_PERIC0_USI2_USI_USER,
+ "mout_peric0_usi2_usi_user", mout_peric0_usi_usi_user_p,
+ PLL_CON0_MUX_CLKCMU_PERIC0_USI2_USI_USER, 4, 1),
+ nMUX(CLK_MOUT_PERIC0_USI3_USI_USER,
+ "mout_peric0_usi3_usi_user", mout_peric0_usi_usi_user_p,
+ PLL_CON0_MUX_CLKCMU_PERIC0_USI3_USI_USER, 4, 1),
+ nMUX(CLK_MOUT_PERIC0_USI4_USI_USER,
+ "mout_peric0_usi4_usi_user", mout_peric0_usi_usi_user_p,
+ PLL_CON0_MUX_CLKCMU_PERIC0_USI4_USI_USER, 4, 1),
+ nMUX(CLK_MOUT_PERIC0_USI5_USI_USER,
+ "mout_peric0_usi5_usi_user", mout_peric0_usi_usi_user_p,
+ PLL_CON0_MUX_CLKCMU_PERIC0_USI5_USI_USER, 4, 1),
+ nMUX(CLK_MOUT_PERIC0_USI6_USI_USER,
+ "mout_peric0_usi6_usi_user", mout_peric0_usi_usi_user_p,
+ PLL_CON0_MUX_CLKCMU_PERIC0_USI6_USI_USER, 4, 1),
+ nMUX(CLK_MOUT_PERIC0_USI7_USI_USER,
+ "mout_peric0_usi7_usi_user", mout_peric0_usi_usi_user_p,
+ PLL_CON0_MUX_CLKCMU_PERIC0_USI7_USI_USER, 4, 1),
+ nMUX(CLK_MOUT_PERIC0_USI8_USI_USER,
+ "mout_peric0_usi8_usi_user", mout_peric0_usi_usi_user_p,
+ PLL_CON0_MUX_CLKCMU_PERIC0_USI8_USI_USER, 4, 1),
};
static const struct samsung_div_clock peric0_div_clks[] __initconst = {
@@ -2798,33 +2798,42 @@ static const struct samsung_div_clock peric0_div_clks[] __initconst = {
DIV(CLK_DOUT_PERIC0_USI0_UART,
"dout_peric0_usi0_uart", "mout_peric0_usi0_uart_user",
CLK_CON_DIV_DIV_CLK_PERIC0_USI0_UART, 0, 4),
- DIV(CLK_DOUT_PERIC0_USI14_USI,
- "dout_peric0_usi14_usi", "mout_peric0_usi14_usi_user",
- CLK_CON_DIV_DIV_CLK_PERIC0_USI14_USI, 0, 4),
- DIV(CLK_DOUT_PERIC0_USI1_USI,
- "dout_peric0_usi1_usi", "mout_peric0_usi1_usi_user",
- CLK_CON_DIV_DIV_CLK_PERIC0_USI1_USI, 0, 4),
- DIV(CLK_DOUT_PERIC0_USI2_USI,
- "dout_peric0_usi2_usi", "mout_peric0_usi2_usi_user",
- CLK_CON_DIV_DIV_CLK_PERIC0_USI2_USI, 0, 4),
- DIV(CLK_DOUT_PERIC0_USI3_USI,
- "dout_peric0_usi3_usi", "mout_peric0_usi3_usi_user",
- CLK_CON_DIV_DIV_CLK_PERIC0_USI3_USI, 0, 4),
- DIV(CLK_DOUT_PERIC0_USI4_USI,
- "dout_peric0_usi4_usi", "mout_peric0_usi4_usi_user",
- CLK_CON_DIV_DIV_CLK_PERIC0_USI4_USI, 0, 4),
- DIV(CLK_DOUT_PERIC0_USI5_USI,
- "dout_peric0_usi5_usi", "mout_peric0_usi5_usi_user",
- CLK_CON_DIV_DIV_CLK_PERIC0_USI5_USI, 0, 4),
- DIV(CLK_DOUT_PERIC0_USI6_USI,
- "dout_peric0_usi6_usi", "mout_peric0_usi6_usi_user",
- CLK_CON_DIV_DIV_CLK_PERIC0_USI6_USI, 0, 4),
- DIV(CLK_DOUT_PERIC0_USI7_USI,
- "dout_peric0_usi7_usi", "mout_peric0_usi7_usi_user",
- CLK_CON_DIV_DIV_CLK_PERIC0_USI7_USI, 0, 4),
- DIV(CLK_DOUT_PERIC0_USI8_USI,
- "dout_peric0_usi8_usi", "mout_peric0_usi8_usi_user",
- CLK_CON_DIV_DIV_CLK_PERIC0_USI8_USI, 0, 4),
+ DIV_F(CLK_DOUT_PERIC0_USI14_USI,
+ "dout_peric0_usi14_usi", "mout_peric0_usi14_usi_user",
+ CLK_CON_DIV_DIV_CLK_PERIC0_USI14_USI, 0, 4,
+ CLK_SET_RATE_PARENT, 0),
+ DIV_F(CLK_DOUT_PERIC0_USI1_USI,
+ "dout_peric0_usi1_usi", "mout_peric0_usi1_usi_user",
+ CLK_CON_DIV_DIV_CLK_PERIC0_USI1_USI, 0, 4,
+ CLK_SET_RATE_PARENT, 0),
+ DIV_F(CLK_DOUT_PERIC0_USI2_USI,
+ "dout_peric0_usi2_usi", "mout_peric0_usi2_usi_user",
+ CLK_CON_DIV_DIV_CLK_PERIC0_USI2_USI, 0, 4,
+ CLK_SET_RATE_PARENT, 0),
+ DIV_F(CLK_DOUT_PERIC0_USI3_USI,
+ "dout_peric0_usi3_usi", "mout_peric0_usi3_usi_user",
+ CLK_CON_DIV_DIV_CLK_PERIC0_USI3_USI, 0, 4,
+ CLK_SET_RATE_PARENT, 0),
+ DIV_F(CLK_DOUT_PERIC0_USI4_USI,
+ "dout_peric0_usi4_usi", "mout_peric0_usi4_usi_user",
+ CLK_CON_DIV_DIV_CLK_PERIC0_USI4_USI, 0, 4,
+ CLK_SET_RATE_PARENT, 0),
+ DIV_F(CLK_DOUT_PERIC0_USI5_USI,
+ "dout_peric0_usi5_usi", "mout_peric0_usi5_usi_user",
+ CLK_CON_DIV_DIV_CLK_PERIC0_USI5_USI, 0, 4,
+ CLK_SET_RATE_PARENT, 0),
+ DIV_F(CLK_DOUT_PERIC0_USI6_USI,
+ "dout_peric0_usi6_usi", "mout_peric0_usi6_usi_user",
+ CLK_CON_DIV_DIV_CLK_PERIC0_USI6_USI, 0, 4,
+ CLK_SET_RATE_PARENT, 0),
+ DIV_F(CLK_DOUT_PERIC0_USI7_USI,
+ "dout_peric0_usi7_usi", "mout_peric0_usi7_usi_user",
+ CLK_CON_DIV_DIV_CLK_PERIC0_USI7_USI, 0, 4,
+ CLK_SET_RATE_PARENT, 0),
+ DIV_F(CLK_DOUT_PERIC0_USI8_USI,
+ "dout_peric0_usi8_usi", "mout_peric0_usi8_usi_user",
+ CLK_CON_DIV_DIV_CLK_PERIC0_USI8_USI, 0, 4,
+ CLK_SET_RATE_PARENT, 0),
};
static const struct samsung_gate_clock peric0_gate_clks[] __initconst = {
@@ -2857,11 +2866,11 @@ static const struct samsung_gate_clock peric0_gate_clks[] __initconst = {
GATE(CLK_GOUT_PERIC0_PERIC0_TOP0_IPCLK_0,
"gout_peric0_peric0_top0_ipclk_0", "dout_peric0_usi1_usi",
CLK_CON_GAT_GOUT_BLK_PERIC0_UID_PERIC0_TOP0_IPCLKPORT_IPCLK_0,
- 21, 0, 0),
+ 21, CLK_SET_RATE_PARENT, 0),
GATE(CLK_GOUT_PERIC0_PERIC0_TOP0_IPCLK_1,
"gout_peric0_peric0_top0_ipclk_1", "dout_peric0_usi2_usi",
CLK_CON_GAT_GOUT_BLK_PERIC0_UID_PERIC0_TOP0_IPCLKPORT_IPCLK_1,
- 21, 0, 0),
+ 21, CLK_SET_RATE_PARENT, 0),
GATE(CLK_GOUT_PERIC0_PERIC0_TOP0_IPCLK_10,
"gout_peric0_peric0_top0_ipclk_10", "dout_peric0_i3c",
CLK_CON_GAT_GOUT_BLK_PERIC0_UID_PERIC0_TOP0_IPCLKPORT_IPCLK_10,
@@ -2889,27 +2898,27 @@ static const struct samsung_gate_clock peric0_gate_clks[] __initconst = {
GATE(CLK_GOUT_PERIC0_PERIC0_TOP0_IPCLK_2,
"gout_peric0_peric0_top0_ipclk_2", "dout_peric0_usi3_usi",
CLK_CON_GAT_GOUT_BLK_PERIC0_UID_PERIC0_TOP0_IPCLKPORT_IPCLK_2,
- 21, 0, 0),
+ 21, CLK_SET_RATE_PARENT, 0),
GATE(CLK_GOUT_PERIC0_PERIC0_TOP0_IPCLK_3,
"gout_peric0_peric0_top0_ipclk_3", "dout_peric0_usi4_usi",
CLK_CON_GAT_GOUT_BLK_PERIC0_UID_PERIC0_TOP0_IPCLKPORT_IPCLK_3,
- 21, 0, 0),
+ 21, CLK_SET_RATE_PARENT, 0),
GATE(CLK_GOUT_PERIC0_PERIC0_TOP0_IPCLK_4,
"gout_peric0_peric0_top0_ipclk_4", "dout_peric0_usi5_usi",
CLK_CON_GAT_GOUT_BLK_PERIC0_UID_PERIC0_TOP0_IPCLKPORT_IPCLK_4,
- 21, 0, 0),
+ 21, CLK_SET_RATE_PARENT, 0),
GATE(CLK_GOUT_PERIC0_PERIC0_TOP0_IPCLK_5,
"gout_peric0_peric0_top0_ipclk_5", "dout_peric0_usi6_usi",
CLK_CON_GAT_GOUT_BLK_PERIC0_UID_PERIC0_TOP0_IPCLKPORT_IPCLK_5,
- 21, 0, 0),
+ 21, CLK_SET_RATE_PARENT, 0),
GATE(CLK_GOUT_PERIC0_PERIC0_TOP0_IPCLK_6,
"gout_peric0_peric0_top0_ipclk_6", "dout_peric0_usi7_usi",
CLK_CON_GAT_GOUT_BLK_PERIC0_UID_PERIC0_TOP0_IPCLKPORT_IPCLK_6,
- 21, 0, 0),
+ 21, CLK_SET_RATE_PARENT, 0),
GATE(CLK_GOUT_PERIC0_PERIC0_TOP0_IPCLK_7,
"gout_peric0_peric0_top0_ipclk_7", "dout_peric0_usi8_usi",
CLK_CON_GAT_GOUT_BLK_PERIC0_UID_PERIC0_TOP0_IPCLKPORT_IPCLK_7,
- 21, 0, 0),
+ 21, CLK_SET_RATE_PARENT, 0),
GATE(CLK_GOUT_PERIC0_PERIC0_TOP0_IPCLK_8,
"gout_peric0_peric0_top0_ipclk_8", "dout_peric0_i3c",
CLK_CON_GAT_GOUT_BLK_PERIC0_UID_PERIC0_TOP0_IPCLKPORT_IPCLK_8,
@@ -2990,7 +2999,7 @@ static const struct samsung_gate_clock peric0_gate_clks[] __initconst = {
GATE(CLK_GOUT_PERIC0_PERIC0_TOP1_IPCLK_2,
"gout_peric0_peric0_top1_ipclk_2", "dout_peric0_usi14_usi",
CLK_CON_GAT_GOUT_BLK_PERIC0_UID_PERIC0_TOP1_IPCLKPORT_IPCLK_2,
- 21, 0, 0),
+ 21, CLK_SET_RATE_PARENT, 0),
/* Disabling this clock makes the system hang. Mark the clock as critical. */
GATE(CLK_GOUT_PERIC0_PERIC0_TOP1_PCLK_0,
"gout_peric0_peric0_top1_pclk_0", "mout_peric0_bus_user",
--
2.44.0.396.g6e790dbe36-goog
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply related
* Re: [PATCH net-next v3 3/3] net: ti: icssg-prueth: Add support for ICSSG switch firmware
From: Andrew Lunn @ 2024-03-28 12:39 UTC (permalink / raw)
To: MD Danish Anwar
Cc: Diogo Ivo, Rob Herring, Dan Carpenter, Jan Kiszka, Simon Horman,
Wolfram Sang, Arnd Bergmann, Vignesh Raghavendra, Vladimir Oltean,
Roger Quadros, Paolo Abeni, Jakub Kicinski, Eric Dumazet,
David S. Miller, linux-arm-kernel, netdev, linux-kernel, srk,
r-gunasekaran
In-Reply-To: <c94815f8-798a-4167-8f69-359b9b28b7ce@ti.com>
On Thu, Mar 28, 2024 at 11:39:33AM +0530, MD Danish Anwar wrote:
> Hi Andrew,
>
> On 27/03/24 6:05 pm, Andrew Lunn wrote:
> > On Wed, Mar 27, 2024 at 05:10:54PM +0530, MD Danish Anwar wrote:
> >> Add support for ICSSG switch firmware using existing Dual EMAC driver
> >> with switchdev.
> >>
> >> Limitations:
> >> VLAN offloading is limited to 0-256 IDs.
> >> MDB/FDB static entries are limited to 511 entries and different FDBs can
> >> hash to same bucket and thus may not completely offloaded
> >>
> >> Switch mode requires loading of new firmware into ICSSG cores. This
> >> means interfaces have to taken down and then reconfigured to switch
> >> mode.
> >
> > Patch 0/3 does not say this. It just shows the interfaces being added
>
> I will modify the cover letter to state that.
>
> > to the bridge. There should not be any need to down the interfaces.
> >
>
> The interfaces needs to be turned down for switching between dual emac
> and switch mode.
>
> Dual Emac mode runs with ICSSG Dual Emac firmware where as Switch mode
> works with ICSSG Switch firmware. These firmware are running on the
> dedicated PRU RPROC cores (pru0, rtu0, txpru0). When switch mode is
> enabled, these pru cores need to be stopped and then Switch firmware is
> loaded on these cores and then the cores are started again.
>
> We stop the cores when interfaces are down and start the cores when
> interfaces are up.
>
> In short, Dual EMAC firmware runs on pru cores, we put down the
> interface, stop pru cores, load switch firmware on the cores, bring the
> interface up and start the pru cores and now Switch mode is enabled.
This is not the Linux model. Try it, add an interface to a software
bridge. It does not care if it is admin up or down.
You need to hide this difference in your driver.
> > I keep asking this, so it would be good to explain it in the commit
> > message. What configuration is preserved over a firmware reload, and
> > what is lost?
> >
> > Can i add VLAN in duel MAC mode and then swap into the switch firmware
> > and all the VLANs are preserved? Can i add fdb entries to a port in
> > dual MAC mode, and then swap into the swtich firmware and the FDB
> > table is preserved? What about STP port state? What about ... ?
> >
>
> When ports are brought up (firmware reload) we do a full cleaning of all
> the shared memories i.e. SMEM (shared RAM). [1]
>
> Vlan table and FDB table are stored in SMEM so all the configuration
> done to VLAN / FDB tables will be lost.
>
> We don't clear DRAM. DRAM is used for sending r30 commands [see
> emac_r30_cmd_init()], configure half duplex [see
> icssg_config_half_duplex()] and configure link speed [see
> icssg_config_set_speed()]. r30 commands are used to set port state (stp).
>
> Now when the interfaces are brought up (firmware reload) r30 command is
> reconfigured as a result any changes done to port state (stp) will be
> lost. But the duplex and speed settings will be preserved.
>
> To summarize,
> VLAN table / FDB table and port states are lost during a firmware reload.
So you also need to work around this in your driver. I think it is
possible to get the network stack to enumerate the configuration. Take
a look at the Mellanox driver. If i remember it does something like
this, but i don't remember the details.
Andrew
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply
* Re: [PATCH v2 1/3] arch: Select fbdev helpers with CONFIG_VIDEO
From: Helge Deller @ 2024-03-28 12:39 UTC (permalink / raw)
To: Thomas Zimmermann, arnd, javierm, sui.jingfeng
Cc: linux-arch, dri-devel, linux-fbdev, sparclinux, linux-sh,
linuxppc-dev, linux-parisc, linux-mips, linux-m68k, loongarch,
linux-arm-kernel, linux-snps-arc, linux-kernel,
James E.J. Bottomley, David S. Miller, Andreas Larsson,
Thomas Gleixner, Ingo Molnar, Borislav Petkov, Dave Hansen, x86,
H. Peter Anvin
In-Reply-To: <20240327204450.14914-2-tzimmermann@suse.de>
On 3/27/24 21:41, Thomas Zimmermann wrote:
> Various Kconfig options selected the per-architecture helpers for
> fbdev. But none of the contained code depends on fbdev. Standardize
> on CONFIG_VIDEO, which will allow to add more general helpers for
> video functionality.
>
> CONFIG_VIDEO protects each architecture's video/ directory.
Your patch in general looks good.
But is renaming the config option from CONFIG_FB_CORE to CONFIG_VIDEO
the best choice?
CONFIG_VIDEO might be mixed up with multimedia/video-streaming.
Why not e.g. CONFIG_GRAPHICS_CORE?
I'm fine with CONFIG_VIDEO as well, but if someone has a better idea
we maybe should go with that instead now?
Helge
> This
> allows for the use of more fine-grained control for each directory's
> files, such as the use of CONFIG_STI_CORE on parisc.
>
> v2:
> - sparc: rebased onto Makefile changes
>
> Signed-off-by: Thomas Zimmermann <tzimmermann@suse.de>
> Cc: "James E.J. Bottomley" <James.Bottomley@HansenPartnership.com>
> Cc: Helge Deller <deller@gmx.de>
> Cc: "David S. Miller" <davem@davemloft.net>
> Cc: Andreas Larsson <andreas@gaisler.com>
> Cc: Thomas Gleixner <tglx@linutronix.de>
> Cc: Ingo Molnar <mingo@redhat.com>
> Cc: Borislav Petkov <bp@alien8.de>
> Cc: Dave Hansen <dave.hansen@linux.intel.com>
> Cc: x86@kernel.org
> Cc: "H. Peter Anvin" <hpa@zytor.com>
> ---
> arch/parisc/Makefile | 2 +-
> arch/sparc/Makefile | 4 ++--
> arch/sparc/video/Makefile | 2 +-
> arch/x86/Makefile | 2 +-
> arch/x86/video/Makefile | 3 ++-
> 5 files changed, 7 insertions(+), 6 deletions(-)
>
> diff --git a/arch/parisc/Makefile b/arch/parisc/Makefile
> index 316f84f1d15c8..21b8166a68839 100644
> --- a/arch/parisc/Makefile
> +++ b/arch/parisc/Makefile
> @@ -119,7 +119,7 @@ export LIBGCC
>
> libs-y += arch/parisc/lib/ $(LIBGCC)
>
> -drivers-y += arch/parisc/video/
> +drivers-$(CONFIG_VIDEO) += arch/parisc/video/
>
> boot := arch/parisc/boot
>
> diff --git a/arch/sparc/Makefile b/arch/sparc/Makefile
> index 2a03daa68f285..757451c3ea1df 100644
> --- a/arch/sparc/Makefile
> +++ b/arch/sparc/Makefile
> @@ -59,8 +59,8 @@ endif
> libs-y += arch/sparc/prom/
> libs-y += arch/sparc/lib/
>
> -drivers-$(CONFIG_PM) += arch/sparc/power/
> -drivers-$(CONFIG_FB_CORE) += arch/sparc/video/
> +drivers-$(CONFIG_PM) += arch/sparc/power/
> +drivers-$(CONFIG_VIDEO) += arch/sparc/video/
>
> boot := arch/sparc/boot
>
> diff --git a/arch/sparc/video/Makefile b/arch/sparc/video/Makefile
> index d4d83f1702c61..9dd82880a027a 100644
> --- a/arch/sparc/video/Makefile
> +++ b/arch/sparc/video/Makefile
> @@ -1,3 +1,3 @@
> # SPDX-License-Identifier: GPL-2.0-only
>
> -obj-$(CONFIG_FB_CORE) += fbdev.o
> +obj-y += fbdev.o
> diff --git a/arch/x86/Makefile b/arch/x86/Makefile
> index 15a5f4f2ff0aa..c0ea612c62ebe 100644
> --- a/arch/x86/Makefile
> +++ b/arch/x86/Makefile
> @@ -265,7 +265,7 @@ drivers-$(CONFIG_PCI) += arch/x86/pci/
> # suspend and hibernation support
> drivers-$(CONFIG_PM) += arch/x86/power/
>
> -drivers-$(CONFIG_FB_CORE) += arch/x86/video/
> +drivers-$(CONFIG_VIDEO) += arch/x86/video/
>
> ####
> # boot loader support. Several targets are kept for legacy purposes
> diff --git a/arch/x86/video/Makefile b/arch/x86/video/Makefile
> index 5ebe48752ffc4..9dd82880a027a 100644
> --- a/arch/x86/video/Makefile
> +++ b/arch/x86/video/Makefile
> @@ -1,2 +1,3 @@
> # SPDX-License-Identifier: GPL-2.0-only
> -obj-$(CONFIG_FB_CORE) += fbdev.o
> +
> +obj-y += fbdev.o
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply
* [PATCH v5 02/11] mfd: tps6594: use volatile_table instead of volatile_reg
From: Bhargav Raviprakash @ 2024-03-28 12:40 UTC (permalink / raw)
To: linux-kernel
Cc: m.nirmaladevi, lee, robh+dt, krzysztof.kozlowski+dt, conor+dt,
jpanis, devicetree, arnd, gregkh, lgirdwood, broonie,
linus.walleij, linux-gpio, linux-arm-kernel, nm, vigneshr, kristo,
eblanc, Bhargav Raviprakash
In-Reply-To: <20240328124016.161959-1-bhargav.r@ltts.com>
In regmap_config use volatile_table instead of volatile_reg. This change
makes it easier to add support for TPS65224 PMIC.
Signed-off-by: Bhargav Raviprakash <bhargav.r@ltts.com>
Acked-by: Julien Panis <jpanis@baylibre.com>
---
drivers/mfd/tps6594-core.c | 16 ++++++++++------
drivers/mfd/tps6594-i2c.c | 2 +-
drivers/mfd/tps6594-spi.c | 2 +-
include/linux/mfd/tps6594.h | 4 +++-
4 files changed, 15 insertions(+), 9 deletions(-)
diff --git a/drivers/mfd/tps6594-core.c b/drivers/mfd/tps6594-core.c
index 783ee5990..089ab8cc8 100644
--- a/drivers/mfd/tps6594-core.c
+++ b/drivers/mfd/tps6594-core.c
@@ -319,12 +319,16 @@ static struct regmap_irq_chip tps6594_irq_chip = {
.handle_post_irq = tps6594_handle_post_irq,
};
-bool tps6594_is_volatile_reg(struct device *dev, unsigned int reg)
-{
- return (reg >= TPS6594_REG_INT_TOP && reg <= TPS6594_REG_STAT_READBACK_ERR) ||
- reg == TPS6594_REG_RTC_STATUS;
-}
-EXPORT_SYMBOL_GPL(tps6594_is_volatile_reg);
+static const struct regmap_range tps6594_volatile_ranges[] = {
+ regmap_reg_range(TPS6594_REG_INT_TOP, TPS6594_REG_STAT_READBACK_ERR),
+ regmap_reg_range(TPS6594_REG_RTC_STATUS, TPS6594_REG_RTC_STATUS),
+};
+
+const struct regmap_access_table tps6594_volatile_table = {
+ .yes_ranges = tps6594_volatile_ranges,
+ .n_yes_ranges = ARRAY_SIZE(tps6594_volatile_ranges),
+};
+EXPORT_SYMBOL_GPL(tps6594_volatile_table);
static int tps6594_check_crc_mode(struct tps6594 *tps, bool primary_pmic)
{
diff --git a/drivers/mfd/tps6594-i2c.c b/drivers/mfd/tps6594-i2c.c
index 899c88c0f..c125b474b 100644
--- a/drivers/mfd/tps6594-i2c.c
+++ b/drivers/mfd/tps6594-i2c.c
@@ -187,7 +187,7 @@ static const struct regmap_config tps6594_i2c_regmap_config = {
.reg_bits = 16,
.val_bits = 8,
.max_register = TPS6594_REG_DWD_FAIL_CNT_REG,
- .volatile_reg = tps6594_is_volatile_reg,
+ .volatile_table = &tps6594_volatile_table,
.read = tps6594_i2c_read,
.write = tps6594_i2c_write,
};
diff --git a/drivers/mfd/tps6594-spi.c b/drivers/mfd/tps6594-spi.c
index 24b72847e..5afb1736f 100644
--- a/drivers/mfd/tps6594-spi.c
+++ b/drivers/mfd/tps6594-spi.c
@@ -70,7 +70,7 @@ static const struct regmap_config tps6594_spi_regmap_config = {
.reg_bits = 16,
.val_bits = 8,
.max_register = TPS6594_REG_DWD_FAIL_CNT_REG,
- .volatile_reg = tps6594_is_volatile_reg,
+ .volatile_table = &tps6594_volatile_table,
.reg_read = tps6594_spi_reg_read,
.reg_write = tps6594_spi_reg_write,
.use_single_read = true,
diff --git a/include/linux/mfd/tps6594.h b/include/linux/mfd/tps6594.h
index e754c01ac..16543fd4d 100644
--- a/include/linux/mfd/tps6594.h
+++ b/include/linux/mfd/tps6594.h
@@ -1337,7 +1337,9 @@ struct tps6594 {
struct regmap_irq_chip_data *irq_data;
};
-bool tps6594_is_volatile_reg(struct device *dev, unsigned int reg);
+extern const struct regmap_access_table tps6594_volatile_table;
+extern const struct regmap_access_table tps65224_volatile_table;
+
int tps6594_device_init(struct tps6594 *tps, bool enable_crc);
#endif /* __LINUX_MFD_TPS6594_H */
--
2.25.1
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply related
* [PATCH v5 00/11] Add support for TI TPS65224 PMIC
From: Bhargav Raviprakash @ 2024-03-28 12:40 UTC (permalink / raw)
To: linux-kernel
Cc: m.nirmaladevi, lee, robh+dt, krzysztof.kozlowski+dt, conor+dt,
jpanis, devicetree, arnd, gregkh, lgirdwood, broonie,
linus.walleij, linux-gpio, linux-arm-kernel, nm, vigneshr, kristo,
eblanc, Bhargav Raviprakash
This series modifies the existing TPS6594 drivers to add support for the
TPS65224 PMIC device that is a derivative of TPS6594. TPS65224 has a
similar register map to TPS6594 with a few differences. SPI, I2C, ESM,
PFSM, Regulators and GPIO features overlap between the two devices.
TPS65224 is a Power Management IC (PMIC) which provides regulators and
other features like GPIOs, Watchdog, Error Signal Monitor (ESM) and
Pre-configurable Finite State Machine (PFSM). The SoC and the PMIC can
communicate through the I2C or SPI interfaces. The PMIC TPS65224
additionally has a 12-bit ADC.
Data Sheet for TPS65224: https://www.ti.com/product/TPS65224-Q1
Driver re-use is applied following the advice of the following series:
https://lore.kernel.org/lkml/2f467b0a-1d11-4ec7-8ca6-6c4ba66e5887@baylibre.com/
The features implemented in this series are:
- TPS65224 Register definitions
- Core (MFD I2C and SPI entry points)
- PFSM
- Regulators
- Pinctrl
TPS65224 Register definitions:
This patch adds macros for register field definitions of TPS65224
to the existing TPS6594 driver.
Core description:
I2C and SPI interface protocols are implemented, with and without
the bit-integrity error detection feature (CRC mode).
PFSM description:
Strictly speaking, PFSM is not hardware. It is a piece of code.
PMIC integrates a state machine which manages operational modes.
Depending on the current operational mode, some voltage domains
remain energized while others can be off.
PFSM driver can be used to trigger transitions between configured
states.
Regulators description:
4 BUCKs and 3 LDOs.
BUCK12 can be used in dual-phase mode.
Pinctrl description:
TPS65224 family has 6 GPIOs. Those GPIOs can also serve different
functions such as I2C or SPI interface or watchdog disable functions.
The driver provides both pinmuxing for the functions and GPIO capability.
This series was tested on linux-next tag: next-20240118
Test logs can be found here:
https://gist.github.com/LeonardMH/58ec135921fb1062ffd4a8b384831eb0
Changelog v4 -> v5:
- Regulator events changed to REGULATOR_EVENT_REGULATION_OUT for _UVOV
- Fixed pinctrl probe issues with TPS6593 PMIC
- Refactoring pinctrl driver: reduced no. of switch case statements and
using template structs for initializing tps6594_pinctrl.
Bhargav Raviprakash (8):
mfd: tps6594: use volatile_table instead of volatile_reg
mfd: tps6594: add regmap config in match data
dt-bindings: mfd: ti,tps6594: Add TI TPS65224 PMIC
mfd: tps6594-i2c: Add TI TPS65224 PMIC I2C
mfd: tps6594-spi: Add TI TPS65224 PMIC SPI
mfd: tps6594-core: Add TI TPS65224 PMIC core
misc: tps6594-pfsm: Add TI TPS65224 PMIC PFSM
arch: arm64: dts: ti: k3-am62p5-sk: Add TPS65224 PMIC support in AM62P
dts
Nirmala Devi Mal Nadar (3):
mfd: tps6594: Add register definitions for TI TPS65224 PMIC
regulator: tps6594-regulator: Add TI TPS65224 PMIC regulators
pinctrl: pinctrl-tps6594: Add TPS65224 PMIC pinctrl and GPIO
.../devicetree/bindings/mfd/ti,tps6594.yaml | 1 +
arch/arm64/boot/dts/ti/k3-am62p5-sk.dts | 95 +++++
drivers/mfd/tps6594-core.c | 253 ++++++++++--
drivers/mfd/tps6594-i2c.c | 41 +-
drivers/mfd/tps6594-spi.c | 43 ++-
drivers/misc/tps6594-pfsm.c | 48 ++-
drivers/pinctrl/pinctrl-tps6594.c | 275 ++++++++++---
drivers/regulator/Kconfig | 4 +-
drivers/regulator/tps6594-regulator.c | 238 ++++++++++--
include/linux/mfd/tps6594.h | 362 +++++++++++++++++-
10 files changed, 1215 insertions(+), 145 deletions(-)
base-commit: 2863b714f3ad0a9686f2de1b779228ad8c7a8052
--
2.25.1
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply
* [PATCH v5 03/11] mfd: tps6594: add regmap config in match data
From: Bhargav Raviprakash @ 2024-03-28 12:40 UTC (permalink / raw)
To: linux-kernel
Cc: m.nirmaladevi, lee, robh+dt, krzysztof.kozlowski+dt, conor+dt,
jpanis, devicetree, arnd, gregkh, lgirdwood, broonie,
linus.walleij, linux-gpio, linux-arm-kernel, nm, vigneshr, kristo,
eblanc, Bhargav Raviprakash
In-Reply-To: <20240328124016.161959-1-bhargav.r@ltts.com>
Introduces a new struct tps6594_match_data. This struct holds fields for
chip id and regmap config. Using this struct in of_device_id data field.
This helps in adding support for TPS65224 PMIC.
Signed-off-by: Bhargav Raviprakash <bhargav.r@ltts.com>
Acked-by: Julien Panis <jpanis@baylibre.com>
---
drivers/mfd/tps6594-i2c.c | 24 ++++++++++++++++--------
drivers/mfd/tps6594-spi.c | 24 ++++++++++++++++--------
include/linux/mfd/tps6594.h | 11 +++++++++++
3 files changed, 43 insertions(+), 16 deletions(-)
diff --git a/drivers/mfd/tps6594-i2c.c b/drivers/mfd/tps6594-i2c.c
index c125b474b..9e2ed48b7 100644
--- a/drivers/mfd/tps6594-i2c.c
+++ b/drivers/mfd/tps6594-i2c.c
@@ -192,10 +192,16 @@ static const struct regmap_config tps6594_i2c_regmap_config = {
.write = tps6594_i2c_write,
};
+static const struct tps6594_match_data match_data[] = {
+ [TPS6594] = {TPS6594, &tps6594_i2c_regmap_config},
+ [TPS6593] = {TPS6593, &tps6594_i2c_regmap_config},
+ [LP8764] = {LP8764, &tps6594_i2c_regmap_config},
+};
+
static const struct of_device_id tps6594_i2c_of_match_table[] = {
- { .compatible = "ti,tps6594-q1", .data = (void *)TPS6594, },
- { .compatible = "ti,tps6593-q1", .data = (void *)TPS6593, },
- { .compatible = "ti,lp8764-q1", .data = (void *)LP8764, },
+ { .compatible = "ti,tps6594-q1", .data = &match_data[TPS6594], },
+ { .compatible = "ti,tps6593-q1", .data = &match_data[TPS6593], },
+ { .compatible = "ti,lp8764-q1", .data = &match_data[LP8764], },
{}
};
MODULE_DEVICE_TABLE(of, tps6594_i2c_of_match_table);
@@ -205,6 +211,7 @@ static int tps6594_i2c_probe(struct i2c_client *client)
struct device *dev = &client->dev;
struct tps6594 *tps;
const struct of_device_id *match;
+ const struct tps6594_match_data *mdata;
tps = devm_kzalloc(dev, sizeof(*tps), GFP_KERNEL);
if (!tps)
@@ -216,14 +223,15 @@ static int tps6594_i2c_probe(struct i2c_client *client)
tps->reg = client->addr;
tps->irq = client->irq;
- tps->regmap = devm_regmap_init(dev, NULL, client, &tps6594_i2c_regmap_config);
- if (IS_ERR(tps->regmap))
- return dev_err_probe(dev, PTR_ERR(tps->regmap), "Failed to init regmap\n");
-
match = of_match_device(tps6594_i2c_of_match_table, dev);
if (!match)
return dev_err_probe(dev, -EINVAL, "Failed to find matching chip ID\n");
- tps->chip_id = (unsigned long)match->data;
+ mdata = (struct tps6594_match_data *)match->data;
+ tps->chip_id = mdata->chip_id;
+
+ tps->regmap = devm_regmap_init(dev, NULL, client, mdata->config);
+ if (IS_ERR(tps->regmap))
+ return dev_err_probe(dev, PTR_ERR(tps->regmap), "Failed to init regmap\n");
crc8_populate_msb(tps6594_i2c_crc_table, TPS6594_CRC8_POLYNOMIAL);
diff --git a/drivers/mfd/tps6594-spi.c b/drivers/mfd/tps6594-spi.c
index 5afb1736f..82a1c02e3 100644
--- a/drivers/mfd/tps6594-spi.c
+++ b/drivers/mfd/tps6594-spi.c
@@ -77,10 +77,16 @@ static const struct regmap_config tps6594_spi_regmap_config = {
.use_single_write = true,
};
+static const struct tps6594_match_data match_data[] = {
+ [TPS6594] = {TPS6594, &tps6594_spi_regmap_config},
+ [TPS6593] = {TPS6593, &tps6594_spi_regmap_config},
+ [LP8764] = {LP8764, &tps6594_spi_regmap_config},
+};
+
static const struct of_device_id tps6594_spi_of_match_table[] = {
- { .compatible = "ti,tps6594-q1", .data = (void *)TPS6594, },
- { .compatible = "ti,tps6593-q1", .data = (void *)TPS6593, },
- { .compatible = "ti,lp8764-q1", .data = (void *)LP8764, },
+ { .compatible = "ti,tps6594-q1", .data = &match_data[TPS6594], },
+ { .compatible = "ti,tps6593-q1", .data = &match_data[TPS6593], },
+ { .compatible = "ti,lp8764-q1", .data = &match_data[LP8764], },
{}
};
MODULE_DEVICE_TABLE(of, tps6594_spi_of_match_table);
@@ -90,6 +96,7 @@ static int tps6594_spi_probe(struct spi_device *spi)
struct device *dev = &spi->dev;
struct tps6594 *tps;
const struct of_device_id *match;
+ const struct tps6594_match_data *mdata;
tps = devm_kzalloc(dev, sizeof(*tps), GFP_KERNEL);
if (!tps)
@@ -101,14 +108,15 @@ static int tps6594_spi_probe(struct spi_device *spi)
tps->reg = spi_get_chipselect(spi, 0);
tps->irq = spi->irq;
- tps->regmap = devm_regmap_init(dev, NULL, spi, &tps6594_spi_regmap_config);
- if (IS_ERR(tps->regmap))
- return dev_err_probe(dev, PTR_ERR(tps->regmap), "Failed to init regmap\n");
-
match = of_match_device(tps6594_spi_of_match_table, dev);
if (!match)
return dev_err_probe(dev, -EINVAL, "Failed to find matching chip ID\n");
- tps->chip_id = (unsigned long)match->data;
+ mdata = (struct tps6594_match_data *)match->data;
+ tps->chip_id = mdata->chip_id;
+
+ tps->regmap = devm_regmap_init(dev, NULL, spi, mdata->config);
+ if (IS_ERR(tps->regmap))
+ return dev_err_probe(dev, PTR_ERR(tps->regmap), "Failed to init regmap\n");
crc8_populate_msb(tps6594_spi_crc_table, TPS6594_CRC8_POLYNOMIAL);
diff --git a/include/linux/mfd/tps6594.h b/include/linux/mfd/tps6594.h
index 16543fd4d..d781e0fe3 100644
--- a/include/linux/mfd/tps6594.h
+++ b/include/linux/mfd/tps6594.h
@@ -1337,6 +1337,17 @@ struct tps6594 {
struct regmap_irq_chip_data *irq_data;
};
+/**
+ * struct tps6594_match_data - of match data of PMIC
+ *
+ * @chip_id: chip ID of PMIC
+ * @config: regmap config of PMIC
+ */
+struct tps6594_match_data {
+ unsigned long chip_id;
+ const struct regmap_config *config;
+};
+
extern const struct regmap_access_table tps6594_volatile_table;
extern const struct regmap_access_table tps65224_volatile_table;
--
2.25.1
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply related
* [PATCH v5 04/11] dt-bindings: mfd: ti,tps6594: Add TI TPS65224 PMIC
From: Bhargav Raviprakash @ 2024-03-28 12:40 UTC (permalink / raw)
To: linux-kernel
Cc: m.nirmaladevi, lee, robh+dt, krzysztof.kozlowski+dt, conor+dt,
jpanis, devicetree, arnd, gregkh, lgirdwood, broonie,
linus.walleij, linux-gpio, linux-arm-kernel, nm, vigneshr, kristo,
eblanc, Bhargav Raviprakash, Conor Dooley
In-Reply-To: <20240328124016.161959-1-bhargav.r@ltts.com>
TPS65224 is a Power Management IC with 4 Buck regulators and 3 LDO
regulators, it includes additional features like GPIOs, watchdog, ESMs
(Error Signal Monitor), and PFSM (Pre-configurable Finite State Machine)
managing the state of the device.
In addition TPS65224 has support for 12-bit ADC and does not have RTC
unlike TPS6594.
Signed-off-by: Bhargav Raviprakash <bhargav.r@ltts.com>
Acked-by: Conor Dooley <conor.dooley@microchip.com>
---
Documentation/devicetree/bindings/mfd/ti,tps6594.yaml | 1 +
1 file changed, 1 insertion(+)
diff --git a/Documentation/devicetree/bindings/mfd/ti,tps6594.yaml b/Documentation/devicetree/bindings/mfd/ti,tps6594.yaml
index 9d43376be..6341b6070 100644
--- a/Documentation/devicetree/bindings/mfd/ti,tps6594.yaml
+++ b/Documentation/devicetree/bindings/mfd/ti,tps6594.yaml
@@ -21,6 +21,7 @@ properties:
- ti,lp8764-q1
- ti,tps6593-q1
- ti,tps6594-q1
+ - ti,tps65224-q1
reg:
description: I2C slave address or SPI chip select number.
--
2.25.1
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply related
* [PATCH v5 05/11] mfd: tps6594-i2c: Add TI TPS65224 PMIC I2C
From: Bhargav Raviprakash @ 2024-03-28 12:40 UTC (permalink / raw)
To: linux-kernel
Cc: m.nirmaladevi, lee, robh+dt, krzysztof.kozlowski+dt, conor+dt,
jpanis, devicetree, arnd, gregkh, lgirdwood, broonie,
linus.walleij, linux-gpio, linux-arm-kernel, nm, vigneshr, kristo,
eblanc, Bhargav Raviprakash
In-Reply-To: <20240328124016.161959-1-bhargav.r@ltts.com>
Add support for TPS65224 PMIC in TPS6594's I2C driver which has
significant functional overlap.
Signed-off-by: Bhargav Raviprakash <bhargav.r@ltts.com>
Acked-by: Julien Panis <jpanis@baylibre.com>
---
drivers/mfd/tps6594-i2c.c | 15 +++++++++++++--
1 file changed, 13 insertions(+), 2 deletions(-)
diff --git a/drivers/mfd/tps6594-i2c.c b/drivers/mfd/tps6594-i2c.c
index 9e2ed48b7..0d741da74 100644
--- a/drivers/mfd/tps6594-i2c.c
+++ b/drivers/mfd/tps6594-i2c.c
@@ -1,6 +1,6 @@
// SPDX-License-Identifier: GPL-2.0
/*
- * I2C access driver for TI TPS6594/TPS6593/LP8764 PMICs
+ * I2C access driver for TI TPS65224/TPS6594/TPS6593/LP8764 PMICs
*
* Copyright (C) 2023 BayLibre Incorporated - https://www.baylibre.com/
*/
@@ -192,16 +192,27 @@ static const struct regmap_config tps6594_i2c_regmap_config = {
.write = tps6594_i2c_write,
};
+static const struct regmap_config tps65224_i2c_regmap_config = {
+ .reg_bits = 16,
+ .val_bits = 8,
+ .max_register = TPS6594_REG_DWD_FAIL_CNT_REG,
+ .volatile_table = &tps65224_volatile_table,
+ .read = tps6594_i2c_read,
+ .write = tps6594_i2c_write,
+};
+
static const struct tps6594_match_data match_data[] = {
[TPS6594] = {TPS6594, &tps6594_i2c_regmap_config},
[TPS6593] = {TPS6593, &tps6594_i2c_regmap_config},
[LP8764] = {LP8764, &tps6594_i2c_regmap_config},
+ [TPS65224] = {TPS65224, &tps65224_i2c_regmap_config},
};
static const struct of_device_id tps6594_i2c_of_match_table[] = {
{ .compatible = "ti,tps6594-q1", .data = &match_data[TPS6594], },
{ .compatible = "ti,tps6593-q1", .data = &match_data[TPS6593], },
{ .compatible = "ti,lp8764-q1", .data = &match_data[LP8764], },
+ { .compatible = "ti,tps65224-q1", .data = &match_data[TPS65224], },
{}
};
MODULE_DEVICE_TABLE(of, tps6594_i2c_of_match_table);
@@ -248,5 +259,5 @@ static struct i2c_driver tps6594_i2c_driver = {
module_i2c_driver(tps6594_i2c_driver);
MODULE_AUTHOR("Julien Panis <jpanis@baylibre.com>");
-MODULE_DESCRIPTION("TPS6594 I2C Interface Driver");
+MODULE_DESCRIPTION("I2C Interface Driver for TPS65224, TPS6594/3, and LP8764");
MODULE_LICENSE("GPL");
--
2.25.1
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply related
* [PATCH v5 08/11] misc: tps6594-pfsm: Add TI TPS65224 PMIC PFSM
From: Bhargav Raviprakash @ 2024-03-28 12:40 UTC (permalink / raw)
To: linux-kernel
Cc: m.nirmaladevi, lee, robh+dt, krzysztof.kozlowski+dt, conor+dt,
jpanis, devicetree, arnd, gregkh, lgirdwood, broonie,
linus.walleij, linux-gpio, linux-arm-kernel, nm, vigneshr, kristo,
eblanc, Bhargav Raviprakash
In-Reply-To: <20240328124016.161959-1-bhargav.r@ltts.com>
Add support for TPS65224 PFSM in the TPS6594 PFSM driver as they share
significant functionality.
Signed-off-by: Bhargav Raviprakash <bhargav.r@ltts.com>
Acked-by: Julien Panis <jpanis@baylibre.com>
---
drivers/misc/tps6594-pfsm.c | 48 +++++++++++++++++++++++++++----------
1 file changed, 35 insertions(+), 13 deletions(-)
diff --git a/drivers/misc/tps6594-pfsm.c b/drivers/misc/tps6594-pfsm.c
index 88dcac814..9bcca1856 100644
--- a/drivers/misc/tps6594-pfsm.c
+++ b/drivers/misc/tps6594-pfsm.c
@@ -1,6 +1,6 @@
// SPDX-License-Identifier: GPL-2.0
/*
- * PFSM (Pre-configurable Finite State Machine) driver for TI TPS6594/TPS6593/LP8764 PMICs
+ * PFSM (Pre-configurable Finite State Machine) driver for TI TPS65224/TPS6594/TPS6593/LP8764 PMICs
*
* Copyright (C) 2023 BayLibre Incorporated - https://www.baylibre.com/
*/
@@ -39,10 +39,12 @@
*
* @miscdev: misc device infos
* @regmap: regmap for accessing the device registers
+ * @chip_id: chip identifier of the device
*/
struct tps6594_pfsm {
struct miscdevice miscdev;
struct regmap *regmap;
+ unsigned long chip_id;
};
static ssize_t tps6594_pfsm_read(struct file *f, char __user *buf,
@@ -133,21 +135,29 @@ static long tps6594_pfsm_ioctl(struct file *f, unsigned int cmd, unsigned long a
struct tps6594_pfsm *pfsm = TPS6594_FILE_TO_PFSM(f);
struct pmic_state_opt state_opt;
void __user *argp = (void __user *)arg;
+ unsigned int regmap_reg, mask;
int ret = -ENOIOCTLCMD;
switch (cmd) {
case PMIC_GOTO_STANDBY:
- /* Disable LP mode */
- ret = regmap_clear_bits(pfsm->regmap, TPS6594_REG_RTC_CTRL_2,
- TPS6594_BIT_LP_STANDBY_SEL);
- if (ret)
- return ret;
+ /* Disable LP mode on TPS6594 Family PMIC */
+ if (pfsm->chip_id != TPS65224) {
+ ret = regmap_clear_bits(pfsm->regmap, TPS6594_REG_RTC_CTRL_2,
+ TPS6594_BIT_LP_STANDBY_SEL);
+
+ if (ret)
+ return ret;
+ }
/* Force trigger */
ret = regmap_write_bits(pfsm->regmap, TPS6594_REG_FSM_I2C_TRIGGERS,
TPS6594_BIT_TRIGGER_I2C(0), TPS6594_BIT_TRIGGER_I2C(0));
break;
case PMIC_GOTO_LP_STANDBY:
+ /* TPS65224 does not support LP STANDBY */
+ if (pfsm->chip_id == TPS65224)
+ return ret;
+
/* Enable LP mode */
ret = regmap_set_bits(pfsm->regmap, TPS6594_REG_RTC_CTRL_2,
TPS6594_BIT_LP_STANDBY_SEL);
@@ -169,6 +179,10 @@ static long tps6594_pfsm_ioctl(struct file *f, unsigned int cmd, unsigned long a
TPS6594_BIT_NSLEEP1B | TPS6594_BIT_NSLEEP2B);
break;
case PMIC_SET_MCU_ONLY_STATE:
+ /* TPS65224 does not support MCU_ONLY_STATE */
+ if (pfsm->chip_id == TPS65224)
+ return ret;
+
if (copy_from_user(&state_opt, argp, sizeof(state_opt)))
return -EFAULT;
@@ -192,14 +206,20 @@ static long tps6594_pfsm_ioctl(struct file *f, unsigned int cmd, unsigned long a
return -EFAULT;
/* Configure wake-up destination */
+ if (pfsm->chip_id == TPS65224) {
+ regmap_reg = TPS65224_REG_STARTUP_CTRL;
+ mask = TPS65224_MASK_STARTUP_DEST;
+ } else {
+ regmap_reg = TPS6594_REG_RTC_CTRL_2;
+ mask = TPS6594_MASK_STARTUP_DEST;
+ }
+
if (state_opt.mcu_only_startup_dest)
- ret = regmap_write_bits(pfsm->regmap, TPS6594_REG_RTC_CTRL_2,
- TPS6594_MASK_STARTUP_DEST,
- TPS6594_STARTUP_DEST_MCU_ONLY);
+ ret = regmap_write_bits(pfsm->regmap, regmap_reg,
+ mask, TPS6594_STARTUP_DEST_MCU_ONLY);
else
- ret = regmap_write_bits(pfsm->regmap, TPS6594_REG_RTC_CTRL_2,
- TPS6594_MASK_STARTUP_DEST,
- TPS6594_STARTUP_DEST_ACTIVE);
+ ret = regmap_write_bits(pfsm->regmap, regmap_reg,
+ mask, TPS6594_STARTUP_DEST_ACTIVE);
if (ret)
return ret;
@@ -211,7 +231,8 @@ static long tps6594_pfsm_ioctl(struct file *f, unsigned int cmd, unsigned long a
/* Modify NSLEEP1-2 bits */
ret = regmap_clear_bits(pfsm->regmap, TPS6594_REG_FSM_NSLEEP_TRIGGERS,
- TPS6594_BIT_NSLEEP2B);
+ pfsm->chip_id == TPS65224 ?
+ TPS6594_BIT_NSLEEP1B : TPS6594_BIT_NSLEEP2B);
break;
}
@@ -262,6 +283,7 @@ static int tps6594_pfsm_probe(struct platform_device *pdev)
tps->chip_id, tps->reg);
pfsm->miscdev.fops = &tps6594_pfsm_fops;
pfsm->miscdev.parent = dev->parent;
+ pfsm->chip_id = tps->chip_id;
for (i = 0 ; i < pdev->num_resources ; i++) {
irq = platform_get_irq_byname(pdev, pdev->resource[i].name);
--
2.25.1
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply related
* [PATCH v5 06/11] mfd: tps6594-spi: Add TI TPS65224 PMIC SPI
From: Bhargav Raviprakash @ 2024-03-28 12:40 UTC (permalink / raw)
To: linux-kernel
Cc: m.nirmaladevi, lee, robh+dt, krzysztof.kozlowski+dt, conor+dt,
jpanis, devicetree, arnd, gregkh, lgirdwood, broonie,
linus.walleij, linux-gpio, linux-arm-kernel, nm, vigneshr, kristo,
eblanc, Bhargav Raviprakash
In-Reply-To: <20240328124016.161959-1-bhargav.r@ltts.com>
Add support for TPS65224 PMIC in TPS6594's SPI driver which has
significant functional overlap.
Signed-off-by: Bhargav Raviprakash <bhargav.r@ltts.com>
Acked-by: Julien Panis <jpanis@baylibre.com>
---
drivers/mfd/tps6594-spi.c | 17 +++++++++++++++--
1 file changed, 15 insertions(+), 2 deletions(-)
diff --git a/drivers/mfd/tps6594-spi.c b/drivers/mfd/tps6594-spi.c
index 82a1c02e3..a9cdc524f 100644
--- a/drivers/mfd/tps6594-spi.c
+++ b/drivers/mfd/tps6594-spi.c
@@ -1,6 +1,6 @@
// SPDX-License-Identifier: GPL-2.0
/*
- * SPI access driver for TI TPS6594/TPS6593/LP8764 PMICs
+ * SPI access driver for TI TPS65224/TPS6594/TPS6593/LP8764 PMICs
*
* Copyright (C) 2023 BayLibre Incorporated - https://www.baylibre.com/
*/
@@ -77,16 +77,29 @@ static const struct regmap_config tps6594_spi_regmap_config = {
.use_single_write = true,
};
+static const struct regmap_config tps65224_spi_regmap_config = {
+ .reg_bits = 16,
+ .val_bits = 8,
+ .max_register = TPS6594_REG_DWD_FAIL_CNT_REG,
+ .volatile_table = &tps65224_volatile_table,
+ .reg_read = tps6594_spi_reg_read,
+ .reg_write = tps6594_spi_reg_write,
+ .use_single_read = true,
+ .use_single_write = true,
+};
+
static const struct tps6594_match_data match_data[] = {
[TPS6594] = {TPS6594, &tps6594_spi_regmap_config},
[TPS6593] = {TPS6593, &tps6594_spi_regmap_config},
[LP8764] = {LP8764, &tps6594_spi_regmap_config},
+ [TPS65224] = {TPS65224, &tps65224_spi_regmap_config},
};
static const struct of_device_id tps6594_spi_of_match_table[] = {
{ .compatible = "ti,tps6594-q1", .data = &match_data[TPS6594], },
{ .compatible = "ti,tps6593-q1", .data = &match_data[TPS6593], },
{ .compatible = "ti,lp8764-q1", .data = &match_data[LP8764], },
+ { .compatible = "ti,tps65224-q1", .data = &match_data[TPS65224],},
{}
};
MODULE_DEVICE_TABLE(of, tps6594_spi_of_match_table);
@@ -133,5 +146,5 @@ static struct spi_driver tps6594_spi_driver = {
module_spi_driver(tps6594_spi_driver);
MODULE_AUTHOR("Julien Panis <jpanis@baylibre.com>");
-MODULE_DESCRIPTION("TPS6594 SPI Interface Driver");
+MODULE_DESCRIPTION("SPI Interface Driver for TPS65224, TPS6594/3, and LP8764");
MODULE_LICENSE("GPL");
--
2.25.1
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply related
* [PATCH v5 01/11] mfd: tps6594: Add register definitions for TI TPS65224 PMIC
From: Bhargav Raviprakash @ 2024-03-28 12:40 UTC (permalink / raw)
To: linux-kernel
Cc: m.nirmaladevi, lee, robh+dt, krzysztof.kozlowski+dt, conor+dt,
jpanis, devicetree, arnd, gregkh, lgirdwood, broonie,
linus.walleij, linux-gpio, linux-arm-kernel, nm, vigneshr, kristo,
eblanc, Bhargav Raviprakash
In-Reply-To: <20240328124016.161959-1-bhargav.r@ltts.com>
From: Nirmala Devi Mal Nadar <m.nirmaladevi@ltts.com>
Extend TPS6594 PMIC register and field definitions to support TPS65224
power management IC.
TPS65224 is software compatible to TPS6594 and can re-use many of the
same definitions, new definitions are added to support additional
controls available on TPS65224.
Signed-off-by: Nirmala Devi Mal Nadar <m.nirmaladevi@ltts.com>
Signed-off-by: Bhargav Raviprakash <bhargav.r@ltts.com>
---
include/linux/mfd/tps6594.h | 347 ++++++++++++++++++++++++++++++++++--
1 file changed, 335 insertions(+), 12 deletions(-)
diff --git a/include/linux/mfd/tps6594.h b/include/linux/mfd/tps6594.h
index 3f7c5e23c..e754c01ac 100644
--- a/include/linux/mfd/tps6594.h
+++ b/include/linux/mfd/tps6594.h
@@ -18,12 +18,13 @@ enum pmic_id {
TPS6594,
TPS6593,
LP8764,
+ TPS65224,
};
/* Macro to get page index from register address */
#define TPS6594_REG_TO_PAGE(reg) ((reg) >> 8)
-/* Registers for page 0 of TPS6594 */
+/* Registers for page 0 */
#define TPS6594_REG_DEV_REV 0x01
#define TPS6594_REG_NVM_CODE_1 0x02
@@ -56,9 +57,6 @@ enum pmic_id {
#define TPS6594_REG_GPIOX_OUT(gpio_inst) (TPS6594_REG_GPIO_OUT_1 + (gpio_inst) / 8)
#define TPS6594_REG_GPIOX_IN(gpio_inst) (TPS6594_REG_GPIO_IN_1 + (gpio_inst) / 8)
-#define TPS6594_REG_GPIO_IN_1 0x3f
-#define TPS6594_REG_GPIO_IN_2 0x40
-
#define TPS6594_REG_RAIL_SEL_1 0x41
#define TPS6594_REG_RAIL_SEL_2 0x42
#define TPS6594_REG_RAIL_SEL_3 0x43
@@ -70,13 +68,15 @@ enum pmic_id {
#define TPS6594_REG_FSM_TRIG_MASK_3 0x48
#define TPS6594_REG_MASK_BUCK1_2 0x49
+#define TPS65224_REG_MASK_BUCKS 0x49
#define TPS6594_REG_MASK_BUCK3_4 0x4a
#define TPS6594_REG_MASK_BUCK5 0x4b
#define TPS6594_REG_MASK_LDO1_2 0x4c
+#define TPS65224_REG_MASK_LDOS 0x4c
#define TPS6594_REG_MASK_LDO3_4 0x4d
#define TPS6594_REG_MASK_VMON 0x4e
-#define TPS6594_REG_MASK_GPIO1_8_FALL 0x4f
-#define TPS6594_REG_MASK_GPIO1_8_RISE 0x50
+#define TPS6594_REG_MASK_GPIO_FALL 0x4f
+#define TPS6594_REG_MASK_GPIO_RISE 0x50
#define TPS6594_REG_MASK_GPIO9_11 0x51
#define TPS6594_REG_MASK_STARTUP 0x52
#define TPS6594_REG_MASK_MISC 0x53
@@ -174,6 +174,10 @@ enum pmic_id {
#define TPS6594_REG_REGISTER_LOCK 0xa1
+#define TPS65224_REG_SRAM_ACCESS_1 0xa2
+#define TPS65224_REG_SRAM_ACCESS_2 0xa3
+#define TPS65224_REG_SRAM_ADDR_CTRL 0xa4
+#define TPS65224_REG_RECOV_CNT_PFSM_INCR 0xa5
#define TPS6594_REG_MANUFACTURING_VER 0xa6
#define TPS6594_REG_CUSTOMER_NVM_ID_REG 0xa7
@@ -182,6 +186,9 @@ enum pmic_id {
#define TPS6594_REG_SOFT_REBOOT_REG 0xab
+#define TPS65224_REG_ADC_CTRL 0xac
+#define TPS65224_REG_ADC_RESULT_REG_1 0xad
+#define TPS65224_REG_ADC_RESULT_REG_2 0xae
#define TPS6594_REG_RTC_SECONDS 0xb5
#define TPS6594_REG_RTC_MINUTES 0xb6
#define TPS6594_REG_RTC_HOURS 0xb7
@@ -199,6 +206,7 @@ enum pmic_id {
#define TPS6594_REG_RTC_CTRL_1 0xc2
#define TPS6594_REG_RTC_CTRL_2 0xc3
+#define TPS65224_REG_STARTUP_CTRL 0xc3
#define TPS6594_REG_RTC_STATUS 0xc4
#define TPS6594_REG_RTC_INTERRUPTS 0xc5
#define TPS6594_REG_RTC_COMP_LSB 0xc6
@@ -214,13 +222,17 @@ enum pmic_id {
#define TPS6594_REG_PFSM_DELAY_REG_2 0xce
#define TPS6594_REG_PFSM_DELAY_REG_3 0xcf
#define TPS6594_REG_PFSM_DELAY_REG_4 0xd0
+#define TPS65224_REG_ADC_GAIN_COMP_REG 0xd0
+#define TPS65224_REG_CRC_CALC_CONTROL 0xef
+#define TPS65224_REG_REGMAP_USER_CRC_LOW 0xf0
+#define TPS65224_REG_REGMAP_USER_CRC_HIGH 0xf1
-/* Registers for page 1 of TPS6594 */
+/* Registers for page 1 */
#define TPS6594_REG_SERIAL_IF_CONFIG 0x11a
#define TPS6594_REG_I2C1_ID 0x122
#define TPS6594_REG_I2C2_ID 0x123
-/* Registers for page 4 of TPS6594 */
+/* Registers for page 4 */
#define TPS6594_REG_WD_ANSWER_REG 0x401
#define TPS6594_REG_WD_QUESTION_ANSW_CNT 0x402
#define TPS6594_REG_WD_WIN1_CFG 0x403
@@ -241,16 +253,26 @@ enum pmic_id {
#define TPS6594_BIT_BUCK_PLDN BIT(5)
#define TPS6594_BIT_BUCK_RV_SEL BIT(7)
-/* BUCKX_CONF register field definition */
+/* TPS6594 BUCKX_CONF register field definition */
#define TPS6594_MASK_BUCK_SLEW_RATE GENMASK(2, 0)
#define TPS6594_MASK_BUCK_ILIM GENMASK(5, 3)
-/* BUCKX_PG_WINDOW register field definition */
+/* TPS65224 BUCKX_CONF register field definition */
+#define TPS65224_MASK_BUCK_SLEW_RATE GENMASK(1, 0)
+
+/* TPS6594 BUCKX_PG_WINDOW register field definition */
#define TPS6594_MASK_BUCK_OV_THR GENMASK(2, 0)
#define TPS6594_MASK_BUCK_UV_THR GENMASK(5, 3)
-/* BUCKX VSET */
-#define TPS6594_MASK_BUCKS_VSET GENMASK(7, 0)
+/* TPS65224 BUCKX_PG_WINDOW register field definition */
+#define TPS65224_MASK_BUCK_VMON_THR GENMASK(1, 0)
+
+/* TPS6594 BUCKX_VOUT register field definition */
+#define TPS6594_MASK_BUCKS_VSET GENMASK(7, 0)
+
+/* TPS65224 BUCKX_VOUT register field definition */
+#define TPS65224_MASK_BUCK1_VSET GENMASK(7, 0)
+#define TPS65224_MASK_BUCKS_VSET GENMASK(6, 0)
/* LDOX_CTRL register field definition */
#define TPS6594_BIT_LDO_EN BIT(0)
@@ -258,6 +280,7 @@ enum pmic_id {
#define TPS6594_BIT_LDO_VMON_EN BIT(4)
#define TPS6594_MASK_LDO_PLDN GENMASK(6, 5)
#define TPS6594_BIT_LDO_RV_SEL BIT(7)
+#define TPS65224_BIT_LDO_DISCHARGE_EN BIT(5)
/* LDORTC_CTRL register field definition */
#define TPS6594_BIT_LDORTC_DIS BIT(0)
@@ -271,6 +294,9 @@ enum pmic_id {
#define TPS6594_MASK_LDO_OV_THR GENMASK(2, 0)
#define TPS6594_MASK_LDO_UV_THR GENMASK(5, 3)
+/* LDOX_PG_WINDOW register field definition */
+#define TPS65224_MASK_LDO_VMON_THR GENMASK(1, 0)
+
/* VCCA_VMON_CTRL register field definition */
#define TPS6594_BIT_VMON_EN BIT(0)
#define TPS6594_BIT_VMON1_EN BIT(1)
@@ -278,10 +304,12 @@ enum pmic_id {
#define TPS6594_BIT_VMON2_EN BIT(3)
#define TPS6594_BIT_VMON2_RV_SEL BIT(4)
#define TPS6594_BIT_VMON_DEGLITCH_SEL BIT(5)
+#define TPS65224_BIT_VMON_DEGLITCH_SEL GENMASK(7, 5)
/* VCCA_PG_WINDOW register field definition */
#define TPS6594_MASK_VCCA_OV_THR GENMASK(2, 0)
#define TPS6594_MASK_VCCA_UV_THR GENMASK(5, 3)
+#define TPS65224_MASK_VCCA_VMON_THR GENMASK(1, 0)
#define TPS6594_BIT_VCCA_PG_SET BIT(6)
/* VMONX_PG_WINDOW register field definition */
@@ -289,6 +317,9 @@ enum pmic_id {
#define TPS6594_MASK_VMONX_UV_THR GENMASK(5, 3)
#define TPS6594_BIT_VMONX_RANGE BIT(6)
+/* VMONX_PG_WINDOW register field definition */
+#define TPS65224_MASK_VMONX_THR GENMASK(1, 0)
+
/* GPIOX_CONF register field definition */
#define TPS6594_BIT_GPIO_DIR BIT(0)
#define TPS6594_BIT_GPIO_OD BIT(1)
@@ -296,6 +327,8 @@ enum pmic_id {
#define TPS6594_BIT_GPIO_PU_PD_EN BIT(3)
#define TPS6594_BIT_GPIO_DEGLITCH_EN BIT(4)
#define TPS6594_MASK_GPIO_SEL GENMASK(7, 5)
+#define TPS65224_MASK_GPIO_SEL GENMASK(6, 5)
+#define TPS65224_MASK_GPIO_SEL_GPIO6 GENMASK(7, 5)
/* NPWRON_CONF register field definition */
#define TPS6594_BIT_NRSTOUT_OD BIT(0)
@@ -305,6 +338,12 @@ enum pmic_id {
#define TPS6594_BIT_ENABLE_POL BIT(5)
#define TPS6594_MASK_NPWRON_SEL GENMASK(7, 6)
+/* POWER_ON_CONFIG register field definition */
+#define TPS65224_BIT_NINT_ENDRV_PU_SEL BIT(0)
+#define TPS65224_BIT_NINT_ENDRV_SEL BIT(1)
+#define TPS65224_BIT_EN_PB_DEGL BIT(5)
+#define TPS65224_MASK_EN_PB_VSENSE_CONFIG GENMASK(7, 6)
+
/* GPIO_OUT_X register field definition */
#define TPS6594_BIT_GPIOX_OUT(gpio_inst) BIT((gpio_inst) % 8)
@@ -312,6 +351,12 @@ enum pmic_id {
#define TPS6594_BIT_GPIOX_IN(gpio_inst) BIT((gpio_inst) % 8)
#define TPS6594_BIT_NPWRON_IN BIT(3)
+/* GPIO_OUT_X register field definition */
+#define TPS65224_BIT_GPIOX_OUT(gpio_inst) BIT((gpio_inst))
+
+/* GPIO_IN_X register field definition */
+#define TPS65224_BIT_GPIOX_IN(gpio_inst) BIT((gpio_inst))
+
/* RAIL_SEL_1 register field definition */
#define TPS6594_MASK_BUCK1_GRP_SEL GENMASK(1, 0)
#define TPS6594_MASK_BUCK2_GRP_SEL GENMASK(3, 2)
@@ -343,6 +388,9 @@ enum pmic_id {
#define TPS6594_BIT_GPIOX_FSM_MASK(gpio_inst) BIT(((gpio_inst) << 1) % 8)
#define TPS6594_BIT_GPIOX_FSM_MASK_POL(gpio_inst) BIT(((gpio_inst) << 1) % 8 + 1)
+#define TPS65224_BIT_GPIOX_FSM_MASK(gpio_inst) BIT(((gpio_inst) << 1) % 6)
+#define TPS65224_BIT_GPIOX_FSM_MASK_POL(gpio_inst) BIT(((gpio_inst) << 1) % 6 + 1)
+
/* MASK_BUCKX register field definition */
#define TPS6594_BIT_BUCKX_OV_MASK(buck_inst) BIT(((buck_inst) << 2) % 8)
#define TPS6594_BIT_BUCKX_UV_MASK(buck_inst) BIT(((buck_inst) << 2) % 8 + 1)
@@ -361,22 +409,46 @@ enum pmic_id {
#define TPS6594_BIT_VMON2_OV_MASK BIT(5)
#define TPS6594_BIT_VMON2_UV_MASK BIT(6)
+/* MASK_BUCK Register field definition */
+#define TPS65224_BIT_BUCK1_UVOV_MASK BIT(0)
+#define TPS65224_BIT_BUCK2_UVOV_MASK BIT(1)
+#define TPS65224_BIT_BUCK3_UVOV_MASK BIT(2)
+#define TPS65224_BIT_BUCK4_UVOV_MASK BIT(4)
+
+/* MASK_LDO_VMON register field definition */
+#define TPS65224_BIT_LDO1_UVOV_MASK BIT(0)
+#define TPS65224_BIT_LDO2_UVOV_MASK BIT(1)
+#define TPS65224_BIT_LDO3_UVOV_MASK BIT(2)
+#define TPS65224_BIT_VCCA_UVOV_MASK BIT(4)
+#define TPS65224_BIT_VMON1_UVOV_MASK BIT(5)
+#define TPS65224_BIT_VMON2_UVOV_MASK BIT(6)
+
/* MASK_GPIOX register field definition */
#define TPS6594_BIT_GPIOX_FALL_MASK(gpio_inst) BIT((gpio_inst) < 8 ? \
(gpio_inst) : (gpio_inst) % 8)
#define TPS6594_BIT_GPIOX_RISE_MASK(gpio_inst) BIT((gpio_inst) < 8 ? \
(gpio_inst) : (gpio_inst) % 8 + 3)
+/* MASK_GPIOX register field definition */
+#define TPS65224_BIT_GPIOX_FALL_MASK(gpio_inst) BIT((gpio_inst))
+#define TPS65224_BIT_GPIOX_RISE_MASK(gpio_inst) BIT((gpio_inst))
/* MASK_STARTUP register field definition */
#define TPS6594_BIT_NPWRON_START_MASK BIT(0)
#define TPS6594_BIT_ENABLE_MASK BIT(1)
#define TPS6594_BIT_FSD_MASK BIT(4)
#define TPS6594_BIT_SOFT_REBOOT_MASK BIT(5)
+#define TPS65224_BIT_VSENSE_MASK BIT(0)
+#define TPS65224_BIT_PB_SHORT_MASK BIT(2)
/* MASK_MISC register field definition */
#define TPS6594_BIT_BIST_PASS_MASK BIT(0)
#define TPS6594_BIT_EXT_CLK_MASK BIT(1)
+#define TPS65224_BIT_REG_UNLOCK_MASK BIT(2)
#define TPS6594_BIT_TWARN_MASK BIT(3)
+#define TPS65224_BIT_PB_LONG_MASK BIT(4)
+#define TPS65224_BIT_PB_FALL_MASK BIT(5)
+#define TPS65224_BIT_PB_RISE_MASK BIT(6)
+#define TPS65224_BIT_ADC_CONV_READY_MASK BIT(7)
/* MASK_MODERATE_ERR register field definition */
#define TPS6594_BIT_BIST_FAIL_MASK BIT(1)
@@ -391,6 +463,8 @@ enum pmic_id {
#define TPS6594_BIT_ORD_SHUTDOWN_MASK BIT(1)
#define TPS6594_BIT_MCU_PWR_ERR_MASK BIT(2)
#define TPS6594_BIT_SOC_PWR_ERR_MASK BIT(3)
+#define TPS65224_BIT_COMM_ERR_MASK BIT(4)
+#define TPS65224_BIT_I2C2_ERR_MASK BIT(5)
/* MASK_COMM_ERR register field definition */
#define TPS6594_BIT_COMM_FRM_ERR_MASK BIT(0)
@@ -426,6 +500,12 @@ enum pmic_id {
#define TPS6594_BIT_BUCK3_4_INT BIT(1)
#define TPS6594_BIT_BUCK5_INT BIT(2)
+/* INT_BUCK register field definition */
+#define TPS65224_BIT_BUCK1_UVOV_INT BIT(0)
+#define TPS65224_BIT_BUCK2_UVOV_INT BIT(1)
+#define TPS65224_BIT_BUCK3_UVOV_INT BIT(2)
+#define TPS65224_BIT_BUCK4_UVOV_INT BIT(3)
+
/* INT_BUCKX register field definition */
#define TPS6594_BIT_BUCKX_OV_INT(buck_inst) BIT(((buck_inst) << 2) % 8)
#define TPS6594_BIT_BUCKX_UV_INT(buck_inst) BIT(((buck_inst) << 2) % 8 + 1)
@@ -437,6 +517,14 @@ enum pmic_id {
#define TPS6594_BIT_LDO3_4_INT BIT(1)
#define TPS6594_BIT_VCCA_INT BIT(4)
+/* INT_LDO_VMON register field definition */
+#define TPS65224_BIT_LDO1_UVOV_INT BIT(0)
+#define TPS65224_BIT_LDO2_UVOV_INT BIT(1)
+#define TPS65224_BIT_LDO3_UVOV_INT BIT(2)
+#define TPS65224_BIT_VCCA_UVOV_INT BIT(4)
+#define TPS65224_BIT_VMON1_UVOV_INT BIT(5)
+#define TPS65224_BIT_VMON2_UVOV_INT BIT(6)
+
/* INT_LDOX register field definition */
#define TPS6594_BIT_LDOX_OV_INT(ldo_inst) BIT(((ldo_inst) << 2) % 8)
#define TPS6594_BIT_LDOX_UV_INT(ldo_inst) BIT(((ldo_inst) << 2) % 8 + 1)
@@ -462,17 +550,32 @@ enum pmic_id {
/* INT_GPIOX register field definition */
#define TPS6594_BIT_GPIOX_INT(gpio_inst) BIT(gpio_inst)
+/* INT_GPIO register field definition */
+#define TPS65224_BIT_GPIO1_INT BIT(0)
+#define TPS65224_BIT_GPIO2_INT BIT(1)
+#define TPS65224_BIT_GPIO3_INT BIT(2)
+#define TPS65224_BIT_GPIO4_INT BIT(3)
+#define TPS65224_BIT_GPIO5_INT BIT(4)
+#define TPS65224_BIT_GPIO6_INT BIT(5)
+
/* INT_STARTUP register field definition */
#define TPS6594_BIT_NPWRON_START_INT BIT(0)
+#define TPS65224_BIT_VSENSE_INT BIT(0)
#define TPS6594_BIT_ENABLE_INT BIT(1)
#define TPS6594_BIT_RTC_INT BIT(2)
+#define TPS65224_BIT_PB_SHORT_INT BIT(2)
#define TPS6594_BIT_FSD_INT BIT(4)
#define TPS6594_BIT_SOFT_REBOOT_INT BIT(5)
/* INT_MISC register field definition */
#define TPS6594_BIT_BIST_PASS_INT BIT(0)
#define TPS6594_BIT_EXT_CLK_INT BIT(1)
+#define TPS65224_BIT_REG_UNLOCK_INT BIT(2)
#define TPS6594_BIT_TWARN_INT BIT(3)
+#define TPS65224_BIT_PB_LONG_INT BIT(4)
+#define TPS65224_BIT_PB_FALL_INT BIT(5)
+#define TPS65224_BIT_PB_RISE_INT BIT(6)
+#define TPS65224_BIT_ADC_CONV_READY_INT BIT(7)
/* INT_MODERATE_ERR register field definition */
#define TPS6594_BIT_TSD_ORD_INT BIT(0)
@@ -488,6 +591,7 @@ enum pmic_id {
#define TPS6594_BIT_TSD_IMM_INT BIT(0)
#define TPS6594_BIT_VCCA_OVP_INT BIT(1)
#define TPS6594_BIT_PFSM_ERR_INT BIT(2)
+#define TPS65224_BIT_BG_XMON_INT BIT(3)
/* INT_FSM_ERR register field definition */
#define TPS6594_BIT_IMM_SHUTDOWN_INT BIT(0)
@@ -496,6 +600,7 @@ enum pmic_id {
#define TPS6594_BIT_SOC_PWR_ERR_INT BIT(3)
#define TPS6594_BIT_COMM_ERR_INT BIT(4)
#define TPS6594_BIT_READBACK_ERR_INT BIT(5)
+#define TPS65224_BIT_I2C2_ERR_INT BIT(5)
#define TPS6594_BIT_ESM_INT BIT(6)
#define TPS6594_BIT_WD_INT BIT(7)
@@ -536,8 +641,18 @@ enum pmic_id {
#define TPS6594_BIT_VMON2_OV_STAT BIT(5)
#define TPS6594_BIT_VMON2_UV_STAT BIT(6)
+/* STAT_LDO_VMON register field definition */
+#define TPS65224_BIT_LDO1_UVOV_STAT BIT(0)
+#define TPS65224_BIT_LDO2_UVOV_STAT BIT(1)
+#define TPS65224_BIT_LDO3_UVOV_STAT BIT(2)
+#define TPS65224_BIT_VCCA_UVOV_STAT BIT(4)
+#define TPS65224_BIT_VMON1_UVOV_STAT BIT(5)
+#define TPS65224_BIT_VMON2_UVOV_STAT BIT(6)
+
/* STAT_STARTUP register field definition */
+#define TPS65224_BIT_VSENSE_STAT BIT(0)
#define TPS6594_BIT_ENABLE_STAT BIT(1)
+#define TPS65224_BIT_PB_LEVEL_STAT BIT(2)
/* STAT_MISC register field definition */
#define TPS6594_BIT_EXT_CLK_STAT BIT(1)
@@ -549,6 +664,7 @@ enum pmic_id {
/* STAT_SEVERE_ERR register field definition */
#define TPS6594_BIT_TSD_IMM_STAT BIT(0)
#define TPS6594_BIT_VCCA_OVP_STAT BIT(1)
+#define TPS65224_BIT_BG_XMON_STAT BIT(3)
/* STAT_READBACK_ERR register field definition */
#define TPS6594_BIT_EN_DRV_READBACK_STAT BIT(0)
@@ -597,6 +713,8 @@ enum pmic_id {
#define TPS6594_BIT_BB_CHARGER_EN BIT(0)
#define TPS6594_BIT_BB_ICHR BIT(1)
#define TPS6594_MASK_BB_VEOC GENMASK(3, 2)
+#define TPS65224_BIT_I2C1_SPI_CRC_EN BIT(4)
+#define TPS65224_BIT_I2C2_CRC_EN BIT(5)
#define TPS6594_BB_EOC_RDY BIT(7)
/* ENABLE_DRV_REG register field definition */
@@ -617,6 +735,7 @@ enum pmic_id {
#define TPS6594_BIT_NRSTOUT_SOC_IN BIT(2)
#define TPS6594_BIT_FORCE_EN_DRV_LOW BIT(3)
#define TPS6594_BIT_SPMI_LPM_EN BIT(4)
+#define TPS65224_BIT_TSD_DISABLE BIT(5)
/* RECOV_CNT_REG_1 register field definition */
#define TPS6594_MASK_RECOV_CNT GENMASK(3, 0)
@@ -671,15 +790,27 @@ enum pmic_id {
/* ESM_SOC_START_REG register field definition */
#define TPS6594_BIT_ESM_SOC_START BIT(0)
+/* ESM_MCU_START_REG register field definition */
+#define TPS65224_BIT_ESM_MCU_START BIT(0)
+
/* ESM_SOC_MODE_CFG register field definition */
#define TPS6594_MASK_ESM_SOC_ERR_CNT_TH GENMASK(3, 0)
#define TPS6594_BIT_ESM_SOC_ENDRV BIT(5)
#define TPS6594_BIT_ESM_SOC_EN BIT(6)
#define TPS6594_BIT_ESM_SOC_MODE BIT(7)
+/* ESM_MCU_MODE_CFG register field definition */
+#define TPS65224_MASK_ESM_MCU_ERR_CNT_TH GENMASK(3, 0)
+#define TPS65224_BIT_ESM_MCU_ENDRV BIT(5)
+#define TPS65224_BIT_ESM_MCU_EN BIT(6)
+#define TPS65224_BIT_ESM_MCU_MODE BIT(7)
+
/* ESM_SOC_ERR_CNT_REG register field definition */
#define TPS6594_MASK_ESM_SOC_ERR_CNT GENMASK(4, 0)
+/* ESM_MCU_ERR_CNT_REG register field definition */
+#define TPS6594_MASK_ESM_MCU_ERR_CNT GENMASK(4, 0)
+
/* REGISTER_LOCK register field definition */
#define TPS6594_BIT_REGISTER_LOCK_STATUS BIT(0)
@@ -687,6 +818,29 @@ enum pmic_id {
#define TPS6594_MASK_VMON1_SLEW_RATE GENMASK(2, 0)
#define TPS6594_MASK_VMON2_SLEW_RATE GENMASK(5, 3)
+/* SRAM_ACCESS_1 Register field definition */
+#define TPS65224_MASk_SRAM_UNLOCK_SEQ GENMASK(7, 0)
+
+/* SRAM_ACCESS_2 Register field definition */
+#define TPS65224_BIT_SRAM_WRITE_MODE BIT(0)
+#define TPS65224_BIT_OTP_PROG_USER BIT(1)
+#define TPS65224_BIT_OTP_PROG_PFSM BIT(2)
+#define TPS65224_BIT_OTP_PROG_STATUS BIT(3)
+#define TPS65224_BIT_SRAM_UNLOCKED BIT(6)
+#define TPS65224_USER_PROG_ALLOWED BIT(7)
+
+/* SRAM_ADDR_CTRL Register field definition */
+#define TPS65224_MASk_SRAM_SEL GENMASK(1, 0)
+
+/* RECOV_CNT_PFSM_INCR Register field definition */
+#define TPS65224_BIT_INCREMENT_RECOV_CNT BIT(0)
+
+/* MANUFACTURING_VER Register field definition */
+#define TPS65224_MASK_SILICON_REV GENMASK(7, 0)
+
+/* CUSTOMER_NVM_ID_REG Register field definition */
+#define TPS65224_MASK_CUSTOMER_NVM_ID GENMASK(7, 0)
+
/* SOFT_REBOOT_REG register field definition */
#define TPS6594_BIT_SOFT_REBOOT BIT(0)
@@ -755,14 +909,83 @@ enum pmic_id {
#define TPS6594_BIT_I2C2_CRC_EN BIT(2)
#define TPS6594_MASK_T_CRC GENMASK(7, 3)
+/* ADC_CTRL Register field definition */
+#define TPS65224_BIT_ADC_START BIT(0)
+#define TPS65224_BIT_ADC_CONT_CONV BIT(1)
+#define TPS65224_BIT_ADC_THERMAL_SEL BIT(2)
+#define TPS65224_BIT_ADC_RDIV_EN BIT(3)
+#define TPS65224_BIT_ADC_STATUS BIT(7)
+
+/* ADC_RESULT_REG_1 Register field definition */
+#define TPS65224_MASK_ADC_RESULT_11_4 GENMASK(7, 0)
+
+/* ADC_RESULT_REG_2 Register field definition */
+#define TPS65224_MASK_ADC_RESULT_3_0 GENMASK(7, 4)
+
+/* STARTUP_CTRL Register field definition */
+#define TPS65224_MASK_STARTUP_DEST GENMASK(6, 5)
+#define TPS65224_BIT_FIRST_STARTUP_DONE BIT(7)
+
+/* SCRATCH_PAD_REG_1 Register field definition */
+#define TPS6594_MASK_SCRATCH_PAD_1 GENMASK(7, 0)
+
+/* SCRATCH_PAD_REG_2 Register field definition */
+#define TPS6594_MASK_SCRATCH_PAD_2 GENMASK(7, 0)
+
+/* SCRATCH_PAD_REG_3 Register field definition */
+#define TPS6594_MASK_SCRATCH_PAD_3 GENMASK(7, 0)
+
+/* SCRATCH_PAD_REG_4 Register field definition */
+#define TPS6594_MASK_SCRATCH_PAD_4 GENMASK(7, 0)
+
+/* PFSM_DELAY_REG_1 Register field definition */
+#define TPS6594_MASK_PFSM_DELAY1 GENMASK(7, 0)
+
+/* PFSM_DELAY_REG_2 Register field definition */
+#define TPS6594_MASK_PFSM_DELAY2 GENMASK(7, 0)
+
+/* PFSM_DELAY_REG_3 Register field definition */
+#define TPS6594_MASK_PFSM_DELAY3 GENMASK(7, 0)
+
+/* PFSM_DELAY_REG_4 Register field definition */
+#define TPS6594_MASK_PFSM_DELAY4 GENMASK(7, 0)
+
+/* CRC_CALC_CONTROL Register field definition */
+#define TPS65224_BIT_RUN_CRC_BIST BIT(0)
+#define TPS65224_BIT_RUN_CRC_UPDATE BIT(1)
+
+/* ADC_GAIN_COMP_REG Register field definition */
+#define TPS65224_MASK_ADC_GAIN_COMP GENMASK(7, 0)
+
+/* REGMAP_USER_CRC_LOW Register field definition */
+#define TPS65224_MASK_REGMAP_USER_CRC16_LOW GENMASK(7, 0)
+
+/* REGMAP_USER_CRC_HIGH Register field definition */
+#define TPS65224_MASK_REGMAP_USER_CRC16_HIGH GENMASK(7, 0)
+
+/* WD_ANSWER_REG Register field definition */
+#define TPS6594_MASK_WD_ANSWER GENMASK(7, 0)
+
/* WD_QUESTION_ANSW_CNT register field definition */
#define TPS6594_MASK_WD_QUESTION GENMASK(3, 0)
#define TPS6594_MASK_WD_ANSW_CNT GENMASK(5, 4)
+#define TPS65224_BIT_INT_TOP_STATUS BIT(7)
+
+/* WD WIN1_CFG register field definition */
+#define TPS6594_MASK_WD_WIN1_CFG GENMASK(6, 0)
+
+/* WD WIN2_CFG register field definition */
+#define TPS6594_MASK_WD_WIN2_CFG GENMASK(6, 0)
+
+/* WD LongWin register field definition */
+#define TPS6594_MASK_WD_LONGWIN_CFG GENMASK(7, 0)
/* WD_MODE_REG register field definition */
#define TPS6594_BIT_WD_RETURN_LONGWIN BIT(0)
#define TPS6594_BIT_WD_MODE_SELECT BIT(1)
#define TPS6594_BIT_WD_PWRHOLD BIT(2)
+#define TPS65224_BIT_WD_ENDRV_SEL BIT(6)
+#define TPS65224_BIT_WD_CNT_SEL BIT(7)
/* WD_QA_CFG register field definition */
#define TPS6594_MASK_WD_QUESTION_SEED GENMASK(3, 0)
@@ -993,6 +1216,106 @@ enum tps6594_irqs {
#define TPS6594_IRQ_NAME_ALARM "alarm"
#define TPS6594_IRQ_NAME_POWERUP "powerup"
+/* IRQs */
+enum tps65224_irqs {
+ /* INT_BUCK register */
+ TPS65224_IRQ_BUCK1_UVOV,
+ TPS65224_IRQ_BUCK2_UVOV,
+ TPS65224_IRQ_BUCK3_UVOV,
+ TPS65224_IRQ_BUCK4_UVOV,
+ /* INT_LDO_VMON register */
+ TPS65224_IRQ_LDO1_UVOV,
+ TPS65224_IRQ_LDO2_UVOV,
+ TPS65224_IRQ_LDO3_UVOV,
+ TPS65224_IRQ_VCCA_UVOV,
+ TPS65224_IRQ_VMON1_UVOV,
+ TPS65224_IRQ_VMON2_UVOV,
+ /* INT_GPIO register */
+ TPS65224_IRQ_GPIO1,
+ TPS65224_IRQ_GPIO2,
+ TPS65224_IRQ_GPIO3,
+ TPS65224_IRQ_GPIO4,
+ TPS65224_IRQ_GPIO5,
+ TPS65224_IRQ_GPIO6,
+ /* INT_STARTUP register */
+ TPS65224_IRQ_VSENSE,
+ TPS65224_IRQ_ENABLE,
+ TPS65224_IRQ_PB_SHORT,
+ TPS65224_IRQ_FSD,
+ TPS65224_IRQ_SOFT_REBOOT,
+ /* INT_MISC register */
+ TPS65224_IRQ_BIST_PASS,
+ TPS65224_IRQ_EXT_CLK,
+ TPS65224_IRQ_REG_UNLOCK,
+ TPS65224_IRQ_TWARN,
+ TPS65224_IRQ_PB_LONG,
+ TPS65224_IRQ_PB_FALL,
+ TPS65224_IRQ_PB_RISE,
+ TPS65224_IRQ_ADC_CONV_READY,
+ /* INT_MODERATE_ERR register */
+ TPS65224_IRQ_TSD_ORD,
+ TPS65224_IRQ_BIST_FAIL,
+ TPS65224_IRQ_REG_CRC_ERR,
+ TPS65224_IRQ_RECOV_CNT,
+ /* INT_SEVERE_ERR register */
+ TPS65224_IRQ_TSD_IMM,
+ TPS65224_IRQ_VCCA_OVP,
+ TPS65224_IRQ_PFSM_ERR,
+ TPS65224_IRQ_BG_XMON,
+ /* INT_FSM_ERR register */
+ TPS65224_IRQ_IMM_SHUTDOWN,
+ TPS65224_IRQ_ORD_SHUTDOWN,
+ TPS65224_IRQ_MCU_PWR_ERR,
+ TPS65224_IRQ_SOC_PWR_ERR,
+ TPS65224_IRQ_COMM_ERR,
+ TPS65224_IRQ_I2C2_ERR,
+};
+
+#define TPS65224_IRQ_NAME_BUCK1_UVOV "buck1_uvov"
+#define TPS65224_IRQ_NAME_BUCK2_UVOV "buck2_uvov"
+#define TPS65224_IRQ_NAME_BUCK3_UVOV "buck3_uvov"
+#define TPS65224_IRQ_NAME_BUCK4_UVOV "buck4_uvov"
+#define TPS65224_IRQ_NAME_LDO1_UVOV "ldo1_uvov"
+#define TPS65224_IRQ_NAME_LDO2_UVOV "ldo2_uvov"
+#define TPS65224_IRQ_NAME_LDO3_UVOV "ldo3_uvov"
+#define TPS65224_IRQ_NAME_VCCA_UVOV "vcca_uvov"
+#define TPS65224_IRQ_NAME_VMON1_UVOV "vmon1_uvov"
+#define TPS65224_IRQ_NAME_VMON2_UVOV "vmon2_uvov"
+#define TPS65224_IRQ_NAME_GPIO1 "gpio1"
+#define TPS65224_IRQ_NAME_GPIO2 "gpio2"
+#define TPS65224_IRQ_NAME_GPIO3 "gpio3"
+#define TPS65224_IRQ_NAME_GPIO4 "gpio4"
+#define TPS65224_IRQ_NAME_GPIO5 "gpio5"
+#define TPS65224_IRQ_NAME_GPIO6 "gpio6"
+#define TPS65224_IRQ_NAME_VSENSE "vsense"
+#define TPS65224_IRQ_NAME_ENABLE "enable"
+#define TPS65224_IRQ_NAME_PB_SHORT "pb_short"
+#define TPS65224_IRQ_NAME_FSD "fsd"
+#define TPS65224_IRQ_NAME_SOFT_REBOOT "soft_reboot"
+#define TPS65224_IRQ_NAME_BIST_PASS "bist_pass"
+#define TPS65224_IRQ_NAME_EXT_CLK "ext_clk"
+#define TPS65224_IRQ_NAME_REG_UNLOCK "reg_unlock"
+#define TPS65224_IRQ_NAME_TWARN "twarn"
+#define TPS65224_IRQ_NAME_PB_LONG "pb_long"
+#define TPS65224_IRQ_NAME_PB_FALL "pb_fall"
+#define TPS65224_IRQ_NAME_PB_RISE "pb_rise"
+#define TPS65224_IRQ_NAME_ADC_CONV_READY "adc_conv_ready"
+#define TPS65224_IRQ_NAME_TSD_ORD "tsd_ord"
+#define TPS65224_IRQ_NAME_BIST_FAIL "bist_fail"
+#define TPS65224_IRQ_NAME_REG_CRC_ERR "reg_crc_err"
+#define TPS65224_IRQ_NAME_RECOV_CNT "recov_cnt"
+#define TPS65224_IRQ_NAME_TSD_IMM "tsd_imm"
+#define TPS65224_IRQ_NAME_VCCA_OVP "vcca_ovp"
+#define TPS65224_IRQ_NAME_PFSM_ERR "pfsm_err"
+#define TPS65224_IRQ_NAME_BG_XMON "bg_xmon"
+#define TPS65224_IRQ_NAME_IMM_SHUTDOWN "imm_shutdown"
+#define TPS65224_IRQ_NAME_ORD_SHUTDOWN "ord_shutdown"
+#define TPS65224_IRQ_NAME_MCU_PWR_ERR "mcu_pwr_err"
+#define TPS65224_IRQ_NAME_SOC_PWR_ERR "soc_pwr_err"
+#define TPS65224_IRQ_NAME_COMM_ERR "comm_err"
+#define TPS65224_IRQ_NAME_I2C2_ERR "i2c2_err"
+#define TPS65224_IRQ_NAME_POWERUP "powerup"
+
/**
* struct tps6594 - device private data structure
*
--
2.25.1
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply related
* [PATCH v5 07/11] mfd: tps6594-core: Add TI TPS65224 PMIC core
From: Bhargav Raviprakash @ 2024-03-28 12:40 UTC (permalink / raw)
To: linux-kernel
Cc: m.nirmaladevi, lee, robh+dt, krzysztof.kozlowski+dt, conor+dt,
jpanis, devicetree, arnd, gregkh, lgirdwood, broonie,
linus.walleij, linux-gpio, linux-arm-kernel, nm, vigneshr, kristo,
eblanc, Bhargav Raviprakash
In-Reply-To: <20240328124016.161959-1-bhargav.r@ltts.com>
Add functionality of the TPS65224 PMIC to the TPS6594 core driver. This
includes adding IRQ resource, MFD cells, and device initialization for
TPS65224.
Signed-off-by: Bhargav Raviprakash <bhargav.r@ltts.com>
Acked-by: Julien Panis <jpanis@baylibre.com>
---
drivers/mfd/tps6594-core.c | 237 ++++++++++++++++++++++++++++++++++---
1 file changed, 219 insertions(+), 18 deletions(-)
diff --git a/drivers/mfd/tps6594-core.c b/drivers/mfd/tps6594-core.c
index 089ab8cc8..c59f3d7e3 100644
--- a/drivers/mfd/tps6594-core.c
+++ b/drivers/mfd/tps6594-core.c
@@ -1,6 +1,6 @@
// SPDX-License-Identifier: GPL-2.0
/*
- * Core functions for TI TPS6594/TPS6593/LP8764 PMICs
+ * Core functions for TI TPS65224/TPS6594/TPS6593/LP8764 PMICs
*
* Copyright (C) 2023 BayLibre Incorporated - https://www.baylibre.com/
*/
@@ -278,16 +278,159 @@ static const unsigned int tps6594_irq_reg[] = {
TPS6594_REG_RTC_STATUS,
};
+/* TPS65224 Resources */
+
+static const struct resource tps65224_regulator_resources[] = {
+ DEFINE_RES_IRQ_NAMED(TPS65224_IRQ_BUCK1_UVOV, TPS65224_IRQ_NAME_BUCK1_UVOV),
+ DEFINE_RES_IRQ_NAMED(TPS65224_IRQ_BUCK2_UVOV, TPS65224_IRQ_NAME_BUCK2_UVOV),
+ DEFINE_RES_IRQ_NAMED(TPS65224_IRQ_BUCK3_UVOV, TPS65224_IRQ_NAME_BUCK3_UVOV),
+ DEFINE_RES_IRQ_NAMED(TPS65224_IRQ_BUCK4_UVOV, TPS65224_IRQ_NAME_BUCK4_UVOV),
+ DEFINE_RES_IRQ_NAMED(TPS65224_IRQ_LDO1_UVOV, TPS65224_IRQ_NAME_LDO1_UVOV),
+ DEFINE_RES_IRQ_NAMED(TPS65224_IRQ_LDO2_UVOV, TPS65224_IRQ_NAME_LDO2_UVOV),
+ DEFINE_RES_IRQ_NAMED(TPS65224_IRQ_LDO3_UVOV, TPS65224_IRQ_NAME_LDO3_UVOV),
+ DEFINE_RES_IRQ_NAMED(TPS65224_IRQ_VCCA_UVOV, TPS65224_IRQ_NAME_VCCA_UVOV),
+ DEFINE_RES_IRQ_NAMED(TPS65224_IRQ_VMON1_UVOV, TPS65224_IRQ_NAME_VMON1_UVOV),
+ DEFINE_RES_IRQ_NAMED(TPS65224_IRQ_VMON2_UVOV, TPS65224_IRQ_NAME_VMON2_UVOV),
+};
+
+static const struct resource tps65224_pinctrl_resources[] = {
+ DEFINE_RES_IRQ_NAMED(TPS65224_IRQ_GPIO1, TPS65224_IRQ_NAME_GPIO1),
+ DEFINE_RES_IRQ_NAMED(TPS65224_IRQ_GPIO2, TPS65224_IRQ_NAME_GPIO2),
+ DEFINE_RES_IRQ_NAMED(TPS65224_IRQ_GPIO3, TPS65224_IRQ_NAME_GPIO3),
+ DEFINE_RES_IRQ_NAMED(TPS65224_IRQ_GPIO4, TPS65224_IRQ_NAME_GPIO4),
+ DEFINE_RES_IRQ_NAMED(TPS65224_IRQ_GPIO5, TPS65224_IRQ_NAME_GPIO5),
+ DEFINE_RES_IRQ_NAMED(TPS65224_IRQ_GPIO6, TPS65224_IRQ_NAME_GPIO6),
+};
+
+static const struct resource tps65224_pfsm_resources[] = {
+ DEFINE_RES_IRQ_NAMED(TPS65224_IRQ_VSENSE, TPS65224_IRQ_NAME_VSENSE),
+ DEFINE_RES_IRQ_NAMED(TPS65224_IRQ_ENABLE, TPS65224_IRQ_NAME_ENABLE),
+ DEFINE_RES_IRQ_NAMED(TPS65224_IRQ_PB_SHORT, TPS65224_IRQ_NAME_PB_SHORT),
+ DEFINE_RES_IRQ_NAMED(TPS65224_IRQ_FSD, TPS65224_IRQ_NAME_FSD),
+ DEFINE_RES_IRQ_NAMED(TPS65224_IRQ_SOFT_REBOOT, TPS65224_IRQ_NAME_SOFT_REBOOT),
+ DEFINE_RES_IRQ_NAMED(TPS65224_IRQ_BIST_PASS, TPS65224_IRQ_NAME_BIST_PASS),
+ DEFINE_RES_IRQ_NAMED(TPS65224_IRQ_EXT_CLK, TPS65224_IRQ_NAME_EXT_CLK),
+ DEFINE_RES_IRQ_NAMED(TPS65224_IRQ_REG_UNLOCK, TPS65224_IRQ_NAME_REG_UNLOCK),
+ DEFINE_RES_IRQ_NAMED(TPS65224_IRQ_TWARN, TPS65224_IRQ_NAME_TWARN),
+ DEFINE_RES_IRQ_NAMED(TPS65224_IRQ_PB_LONG, TPS65224_IRQ_NAME_PB_LONG),
+ DEFINE_RES_IRQ_NAMED(TPS65224_IRQ_PB_FALL, TPS65224_IRQ_NAME_PB_FALL),
+ DEFINE_RES_IRQ_NAMED(TPS65224_IRQ_PB_RISE, TPS65224_IRQ_NAME_PB_RISE),
+ DEFINE_RES_IRQ_NAMED(TPS65224_IRQ_TSD_ORD, TPS65224_IRQ_NAME_TSD_ORD),
+ DEFINE_RES_IRQ_NAMED(TPS65224_IRQ_BIST_FAIL, TPS65224_IRQ_NAME_BIST_FAIL),
+ DEFINE_RES_IRQ_NAMED(TPS65224_IRQ_REG_CRC_ERR, TPS65224_IRQ_NAME_REG_CRC_ERR),
+ DEFINE_RES_IRQ_NAMED(TPS65224_IRQ_RECOV_CNT, TPS65224_IRQ_NAME_RECOV_CNT),
+ DEFINE_RES_IRQ_NAMED(TPS65224_IRQ_TSD_IMM, TPS65224_IRQ_NAME_TSD_IMM),
+ DEFINE_RES_IRQ_NAMED(TPS65224_IRQ_VCCA_OVP, TPS65224_IRQ_NAME_VCCA_OVP),
+ DEFINE_RES_IRQ_NAMED(TPS65224_IRQ_PFSM_ERR, TPS65224_IRQ_NAME_PFSM_ERR),
+ DEFINE_RES_IRQ_NAMED(TPS65224_IRQ_BG_XMON, TPS65224_IRQ_NAME_BG_XMON),
+ DEFINE_RES_IRQ_NAMED(TPS65224_IRQ_IMM_SHUTDOWN, TPS65224_IRQ_NAME_IMM_SHUTDOWN),
+ DEFINE_RES_IRQ_NAMED(TPS65224_IRQ_ORD_SHUTDOWN, TPS65224_IRQ_NAME_ORD_SHUTDOWN),
+ DEFINE_RES_IRQ_NAMED(TPS65224_IRQ_MCU_PWR_ERR, TPS65224_IRQ_NAME_MCU_PWR_ERR),
+ DEFINE_RES_IRQ_NAMED(TPS65224_IRQ_SOC_PWR_ERR, TPS65224_IRQ_NAME_SOC_PWR_ERR),
+ DEFINE_RES_IRQ_NAMED(TPS65224_IRQ_COMM_ERR, TPS65224_IRQ_NAME_COMM_ERR),
+ DEFINE_RES_IRQ_NAMED(TPS65224_IRQ_I2C2_ERR, TPS65224_IRQ_NAME_I2C2_ERR),
+};
+
+static const struct resource tps65224_adc_resources[] = {
+ DEFINE_RES_IRQ_NAMED(TPS65224_IRQ_ADC_CONV_READY, TPS65224_IRQ_NAME_ADC_CONV_READY),
+};
+
+static const struct mfd_cell tps65224_common_cells[] = {
+ MFD_CELL_RES("tps65224-adc", tps65224_adc_resources),
+ MFD_CELL_RES("tps6594-pfsm", tps65224_pfsm_resources),
+ MFD_CELL_RES("tps6594-pinctrl", tps65224_pinctrl_resources),
+ MFD_CELL_RES("tps6594-regulator", tps65224_regulator_resources),
+};
+
+static const struct regmap_irq tps65224_irqs[] = {
+ /* INT_BUCK register */
+ REGMAP_IRQ_REG(TPS65224_IRQ_BUCK1_UVOV, 0, TPS65224_BIT_BUCK1_UVOV_INT),
+ REGMAP_IRQ_REG(TPS65224_IRQ_BUCK2_UVOV, 0, TPS65224_BIT_BUCK2_UVOV_INT),
+ REGMAP_IRQ_REG(TPS65224_IRQ_BUCK3_UVOV, 0, TPS65224_BIT_BUCK3_UVOV_INT),
+ REGMAP_IRQ_REG(TPS65224_IRQ_BUCK4_UVOV, 0, TPS65224_BIT_BUCK4_UVOV_INT),
+
+ /* INT_VMON_LDO register */
+ REGMAP_IRQ_REG(TPS65224_IRQ_LDO1_UVOV, 1, TPS65224_BIT_LDO1_UVOV_INT),
+ REGMAP_IRQ_REG(TPS65224_IRQ_LDO2_UVOV, 1, TPS65224_BIT_LDO2_UVOV_INT),
+ REGMAP_IRQ_REG(TPS65224_IRQ_LDO3_UVOV, 1, TPS65224_BIT_LDO3_UVOV_INT),
+ REGMAP_IRQ_REG(TPS65224_IRQ_VCCA_UVOV, 1, TPS65224_BIT_VCCA_UVOV_INT),
+ REGMAP_IRQ_REG(TPS65224_IRQ_VMON1_UVOV, 1, TPS65224_BIT_VMON1_UVOV_INT),
+ REGMAP_IRQ_REG(TPS65224_IRQ_VMON2_UVOV, 1, TPS65224_BIT_VMON2_UVOV_INT),
+
+ /* INT_GPIO register */
+ REGMAP_IRQ_REG(TPS65224_IRQ_GPIO1, 2, TPS65224_BIT_GPIO1_INT),
+ REGMAP_IRQ_REG(TPS65224_IRQ_GPIO2, 2, TPS65224_BIT_GPIO2_INT),
+ REGMAP_IRQ_REG(TPS65224_IRQ_GPIO3, 2, TPS65224_BIT_GPIO3_INT),
+ REGMAP_IRQ_REG(TPS65224_IRQ_GPIO4, 2, TPS65224_BIT_GPIO4_INT),
+ REGMAP_IRQ_REG(TPS65224_IRQ_GPIO5, 2, TPS65224_BIT_GPIO5_INT),
+ REGMAP_IRQ_REG(TPS65224_IRQ_GPIO6, 2, TPS65224_BIT_GPIO6_INT),
+
+ /* INT_STARTUP register */
+ REGMAP_IRQ_REG(TPS65224_IRQ_VSENSE, 3, TPS65224_BIT_VSENSE_INT),
+ REGMAP_IRQ_REG(TPS65224_IRQ_ENABLE, 3, TPS6594_BIT_ENABLE_INT),
+ REGMAP_IRQ_REG(TPS65224_IRQ_PB_SHORT, 3, TPS65224_BIT_PB_SHORT_INT),
+ REGMAP_IRQ_REG(TPS65224_IRQ_FSD, 3, TPS6594_BIT_FSD_INT),
+ REGMAP_IRQ_REG(TPS65224_IRQ_SOFT_REBOOT, 3, TPS6594_BIT_SOFT_REBOOT_INT),
+
+ /* INT_MISC register */
+ REGMAP_IRQ_REG(TPS65224_IRQ_BIST_PASS, 4, TPS6594_BIT_BIST_PASS_INT),
+ REGMAP_IRQ_REG(TPS65224_IRQ_EXT_CLK, 4, TPS6594_BIT_EXT_CLK_INT),
+ REGMAP_IRQ_REG(TPS65224_IRQ_REG_UNLOCK, 4, TPS65224_BIT_REG_UNLOCK_INT),
+ REGMAP_IRQ_REG(TPS65224_IRQ_TWARN, 4, TPS6594_BIT_TWARN_INT),
+ REGMAP_IRQ_REG(TPS65224_IRQ_PB_LONG, 4, TPS65224_BIT_PB_LONG_INT),
+ REGMAP_IRQ_REG(TPS65224_IRQ_PB_FALL, 4, TPS65224_BIT_PB_FALL_INT),
+ REGMAP_IRQ_REG(TPS65224_IRQ_PB_RISE, 4, TPS65224_BIT_PB_RISE_INT),
+ REGMAP_IRQ_REG(TPS65224_IRQ_ADC_CONV_READY, 4, TPS65224_BIT_ADC_CONV_READY_INT),
+
+ /* INT_MODERATE_ERR register */
+ REGMAP_IRQ_REG(TPS65224_IRQ_TSD_ORD, 5, TPS6594_BIT_TSD_ORD_INT),
+ REGMAP_IRQ_REG(TPS65224_IRQ_BIST_FAIL, 5, TPS6594_BIT_BIST_FAIL_INT),
+ REGMAP_IRQ_REG(TPS65224_IRQ_REG_CRC_ERR, 5, TPS6594_BIT_REG_CRC_ERR_INT),
+ REGMAP_IRQ_REG(TPS65224_IRQ_RECOV_CNT, 5, TPS6594_BIT_RECOV_CNT_INT),
+
+ /* INT_SEVERE_ERR register */
+ REGMAP_IRQ_REG(TPS65224_IRQ_TSD_IMM, 6, TPS6594_BIT_TSD_IMM_INT),
+ REGMAP_IRQ_REG(TPS65224_IRQ_VCCA_OVP, 6, TPS6594_BIT_VCCA_OVP_INT),
+ REGMAP_IRQ_REG(TPS65224_IRQ_PFSM_ERR, 6, TPS6594_BIT_PFSM_ERR_INT),
+ REGMAP_IRQ_REG(TPS65224_IRQ_BG_XMON, 6, TPS65224_BIT_BG_XMON_INT),
+
+ /* INT_FSM_ERR register */
+ REGMAP_IRQ_REG(TPS65224_IRQ_IMM_SHUTDOWN, 7, TPS6594_BIT_IMM_SHUTDOWN_INT),
+ REGMAP_IRQ_REG(TPS65224_IRQ_ORD_SHUTDOWN, 7, TPS6594_BIT_ORD_SHUTDOWN_INT),
+ REGMAP_IRQ_REG(TPS65224_IRQ_MCU_PWR_ERR, 7, TPS6594_BIT_MCU_PWR_ERR_INT),
+ REGMAP_IRQ_REG(TPS65224_IRQ_SOC_PWR_ERR, 7, TPS6594_BIT_SOC_PWR_ERR_INT),
+ REGMAP_IRQ_REG(TPS65224_IRQ_COMM_ERR, 7, TPS6594_BIT_COMM_ERR_INT),
+ REGMAP_IRQ_REG(TPS65224_IRQ_I2C2_ERR, 7, TPS65224_BIT_I2C2_ERR_INT),
+};
+
+static const unsigned int tps65224_irq_reg[] = {
+ TPS6594_REG_INT_BUCK,
+ TPS6594_REG_INT_LDO_VMON,
+ TPS6594_REG_INT_GPIO,
+ TPS6594_REG_INT_STARTUP,
+ TPS6594_REG_INT_MISC,
+ TPS6594_REG_INT_MODERATE_ERR,
+ TPS6594_REG_INT_SEVERE_ERR,
+ TPS6594_REG_INT_FSM_ERR,
+};
+
static inline unsigned int tps6594_get_irq_reg(struct regmap_irq_chip_data *data,
unsigned int base, int index)
{
return tps6594_irq_reg[index];
};
+static inline unsigned int tps65224_get_irq_reg(struct regmap_irq_chip_data *data,
+ unsigned int base, int index)
+{
+ return tps65224_irq_reg[index];
+};
+
static int tps6594_handle_post_irq(void *irq_drv_data)
{
struct tps6594 *tps = irq_drv_data;
int ret = 0;
+ unsigned int regmap_reg, mask_val;
/*
* When CRC is enabled, writing to a read-only bit triggers an error,
@@ -299,10 +442,17 @@ static int tps6594_handle_post_irq(void *irq_drv_data)
* COMM_ADR_ERR_INT bit set. Clear immediately this bit to avoid raising
* a new interrupt.
*/
- if (tps->use_crc)
- ret = regmap_write_bits(tps->regmap, TPS6594_REG_INT_COMM_ERR,
- TPS6594_BIT_COMM_ADR_ERR_INT,
- TPS6594_BIT_COMM_ADR_ERR_INT);
+ if (tps->use_crc) {
+ if (tps->chip_id == TPS65224) {
+ regmap_reg = TPS6594_REG_INT_FSM_ERR;
+ mask_val = TPS6594_BIT_COMM_ERR_INT;
+ } else {
+ regmap_reg = TPS6594_REG_INT_COMM_ERR;
+ mask_val = TPS6594_BIT_COMM_ADR_ERR_INT;
+ }
+
+ ret = regmap_write_bits(tps->regmap, regmap_reg, mask_val, mask_val);
+ }
return ret;
};
@@ -319,6 +469,18 @@ static struct regmap_irq_chip tps6594_irq_chip = {
.handle_post_irq = tps6594_handle_post_irq,
};
+static struct regmap_irq_chip tps65224_irq_chip = {
+ .ack_base = TPS6594_REG_INT_BUCK,
+ .ack_invert = 1,
+ .clear_ack = 1,
+ .init_ack_masked = 1,
+ .num_regs = ARRAY_SIZE(tps65224_irq_reg),
+ .irqs = tps65224_irqs,
+ .num_irqs = ARRAY_SIZE(tps65224_irqs),
+ .get_irq_reg = tps65224_get_irq_reg,
+ .handle_post_irq = tps6594_handle_post_irq,
+};
+
static const struct regmap_range tps6594_volatile_ranges[] = {
regmap_reg_range(TPS6594_REG_INT_TOP, TPS6594_REG_STAT_READBACK_ERR),
regmap_reg_range(TPS6594_REG_RTC_STATUS, TPS6594_REG_RTC_STATUS),
@@ -330,17 +492,35 @@ const struct regmap_access_table tps6594_volatile_table = {
};
EXPORT_SYMBOL_GPL(tps6594_volatile_table);
+static const struct regmap_range tps65224_volatile_ranges[] = {
+ regmap_reg_range(TPS6594_REG_INT_TOP, TPS6594_REG_STAT_SEVERE_ERR),
+};
+
+const struct regmap_access_table tps65224_volatile_table = {
+ .yes_ranges = tps65224_volatile_ranges,
+ .n_yes_ranges = ARRAY_SIZE(tps65224_volatile_ranges),
+};
+EXPORT_SYMBOL_GPL(tps65224_volatile_table);
+
static int tps6594_check_crc_mode(struct tps6594 *tps, bool primary_pmic)
{
int ret;
+ unsigned int regmap_reg, mask_val;
+
+ if (tps->chip_id == TPS65224) {
+ regmap_reg = TPS6594_REG_CONFIG_2;
+ mask_val = TPS65224_BIT_I2C1_SPI_CRC_EN;
+ } else {
+ regmap_reg = TPS6594_REG_SERIAL_IF_CONFIG;
+ mask_val = TPS6594_BIT_I2C1_SPI_CRC_EN;
+ };
/*
* Check if CRC is enabled.
* Once CRC is enabled, it can't be disabled until next power cycle.
*/
tps->use_crc = true;
- ret = regmap_test_bits(tps->regmap, TPS6594_REG_SERIAL_IF_CONFIG,
- TPS6594_BIT_I2C1_SPI_CRC_EN);
+ ret = regmap_test_bits(tps->regmap, regmap_reg, mask_val);
if (ret == 0) {
ret = -EIO;
} else if (ret > 0) {
@@ -355,6 +535,15 @@ static int tps6594_check_crc_mode(struct tps6594 *tps, bool primary_pmic)
static int tps6594_set_crc_feature(struct tps6594 *tps)
{
int ret;
+ unsigned int regmap_reg, mask_val;
+
+ if (tps->chip_id == TPS65224) {
+ regmap_reg = TPS6594_REG_CONFIG_2;
+ mask_val = TPS65224_BIT_I2C1_SPI_CRC_EN;
+ } else {
+ regmap_reg = TPS6594_REG_FSM_I2C_TRIGGERS;
+ mask_val = TPS6594_BIT_TRIGGER_I2C(2);
+ }
ret = tps6594_check_crc_mode(tps, true);
if (ret) {
@@ -363,8 +552,7 @@ static int tps6594_set_crc_feature(struct tps6594 *tps)
* on primary PMIC.
*/
tps->use_crc = false;
- ret = regmap_write_bits(tps->regmap, TPS6594_REG_FSM_I2C_TRIGGERS,
- TPS6594_BIT_TRIGGER_I2C(2), TPS6594_BIT_TRIGGER_I2C(2));
+ ret = regmap_write_bits(tps->regmap, regmap_reg, mask_val, mask_val);
if (ret)
return ret;
@@ -420,6 +608,9 @@ int tps6594_device_init(struct tps6594 *tps, bool enable_crc)
{
struct device *dev = tps->dev;
int ret;
+ struct regmap_irq_chip *irq_chip;
+ const struct mfd_cell *cells;
+ int n_cells;
if (enable_crc) {
ret = tps6594_enable_crc(tps);
@@ -433,26 +624,35 @@ int tps6594_device_init(struct tps6594 *tps, bool enable_crc)
if (ret)
return dev_err_probe(dev, ret, "Failed to set PMIC state\n");
- tps6594_irq_chip.irq_drv_data = tps;
- tps6594_irq_chip.name = devm_kasprintf(dev, GFP_KERNEL, "%s-%ld-0x%02x",
- dev->driver->name, tps->chip_id, tps->reg);
+ if (tps->chip_id == TPS65224) {
+ irq_chip = &tps65224_irq_chip;
+ n_cells = ARRAY_SIZE(tps65224_common_cells);
+ cells = tps65224_common_cells;
+ } else {
+ irq_chip = &tps6594_irq_chip;
+ n_cells = ARRAY_SIZE(tps6594_common_cells);
+ cells = tps6594_common_cells;
+ }
+
+ irq_chip->irq_drv_data = tps;
+ irq_chip->name = devm_kasprintf(dev, GFP_KERNEL, "%s-%ld-0x%02x",
+ dev->driver->name, tps->chip_id, tps->reg);
- if (!tps6594_irq_chip.name)
+ if (!irq_chip->name)
return -ENOMEM;
ret = devm_regmap_add_irq_chip(dev, tps->regmap, tps->irq, IRQF_SHARED | IRQF_ONESHOT,
- 0, &tps6594_irq_chip, &tps->irq_data);
+ 0, irq_chip, &tps->irq_data);
if (ret)
return dev_err_probe(dev, ret, "Failed to add regmap IRQ\n");
- ret = devm_mfd_add_devices(dev, PLATFORM_DEVID_AUTO, tps6594_common_cells,
- ARRAY_SIZE(tps6594_common_cells), NULL, 0,
+ ret = devm_mfd_add_devices(dev, PLATFORM_DEVID_AUTO, cells, n_cells, NULL, 0,
regmap_irq_get_domain(tps->irq_data));
if (ret)
return dev_err_probe(dev, ret, "Failed to add common child devices\n");
- /* No RTC for LP8764 */
- if (tps->chip_id != LP8764) {
+ /* No RTC for LP8764 and TPS65224 */
+ if (tps->chip_id != LP8764 && tps->chip_id != TPS65224) {
ret = devm_mfd_add_devices(dev, PLATFORM_DEVID_AUTO, tps6594_rtc_cells,
ARRAY_SIZE(tps6594_rtc_cells), NULL, 0,
regmap_irq_get_domain(tps->irq_data));
@@ -465,5 +665,6 @@ int tps6594_device_init(struct tps6594 *tps, bool enable_crc)
EXPORT_SYMBOL_GPL(tps6594_device_init);
MODULE_AUTHOR("Julien Panis <jpanis@baylibre.com>");
+MODULE_AUTHOR("Bhargav Raviprakash <bhargav.r@ltts.com");
MODULE_DESCRIPTION("TPS6594 Driver");
MODULE_LICENSE("GPL");
--
2.25.1
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply related
* [PATCH v5 09/11] regulator: tps6594-regulator: Add TI TPS65224 PMIC regulators
From: Bhargav Raviprakash @ 2024-03-28 12:40 UTC (permalink / raw)
To: linux-kernel
Cc: m.nirmaladevi, lee, robh+dt, krzysztof.kozlowski+dt, conor+dt,
jpanis, devicetree, arnd, gregkh, lgirdwood, broonie,
linus.walleij, linux-gpio, linux-arm-kernel, nm, vigneshr, kristo,
eblanc, Bhargav Raviprakash
In-Reply-To: <20240328124016.161959-1-bhargav.r@ltts.com>
From: Nirmala Devi Mal Nadar <m.nirmaladevi@ltts.com>
Add support for TPS65224 regulators (bucks and LDOs) to TPS6594 driver as
they have significant functional overlap. TPS65224 PMIC has 4 buck
regulators and 3 LDOs. BUCK12 can operate in dual phase.
The output voltages are configurable and are meant to supply power to the
main processor and other components.
Signed-off-by: Nirmala Devi Mal Nadar <m.nirmaladevi@ltts.com>
Signed-off-by: Bhargav Raviprakash <bhargav.r@ltts.com>
---
drivers/regulator/Kconfig | 4 +-
drivers/regulator/tps6594-regulator.c | 238 +++++++++++++++++++++++---
2 files changed, 216 insertions(+), 26 deletions(-)
diff --git a/drivers/regulator/Kconfig b/drivers/regulator/Kconfig
index 7db0a29b5..1e4119f00 100644
--- a/drivers/regulator/Kconfig
+++ b/drivers/regulator/Kconfig
@@ -1563,13 +1563,15 @@ config REGULATOR_TPS6594
depends on MFD_TPS6594 && OF
default MFD_TPS6594
help
- This driver supports TPS6594 voltage regulator chips.
+ This driver supports TPS6594 series and TPS65224 voltage regulator chips.
TPS6594 series of PMICs have 5 BUCKs and 4 LDOs
voltage regulators.
BUCKs 1,2,3,4 can be used in single phase or multiphase mode.
Part number defines which single or multiphase mode is i used.
It supports software based voltage control
for different voltage domains.
+ TPS65224 PMIC has 4 BUCKs and 3 LDOs. BUCK12 can be used in dual phase.
+ All BUCKs and LDOs volatge can be controlled through software.
config REGULATOR_TPS6524X
tristate "TI TPS6524X Power regulators"
diff --git a/drivers/regulator/tps6594-regulator.c b/drivers/regulator/tps6594-regulator.c
index b7f0c8779..fd440822a 100644
--- a/drivers/regulator/tps6594-regulator.c
+++ b/drivers/regulator/tps6594-regulator.c
@@ -66,6 +66,15 @@ static struct tps6594_regulator_irq_type tps6594_ext_regulator_irq_types[] = {
REGULATOR_EVENT_OVER_VOLTAGE_WARN },
};
+static struct tps6594_regulator_irq_type tps65224_ext_regulator_irq_types[] = {
+ { TPS65224_IRQ_NAME_VCCA_UVOV, "VCCA", "voltage out of range",
+ REGULATOR_EVENT_REGULATION_OUT },
+ { TPS65224_IRQ_NAME_VMON1_UVOV, "VMON1", "voltage out of range",
+ REGULATOR_EVENT_REGULATION_OUT },
+ { TPS65224_IRQ_NAME_VMON2_UVOV, "VMON2", "voltage out of range",
+ REGULATOR_EVENT_REGULATION_OUT },
+};
+
struct tps6594_regulator_irq_data {
struct device *dev;
struct tps6594_regulator_irq_type *type;
@@ -122,6 +131,27 @@ static const struct linear_range ldos_4_ranges[] = {
REGULATOR_LINEAR_RANGE(1200000, 0x20, 0x74, 25000),
};
+/* Voltage range for TPS65224 Bucks and LDOs */
+static const struct linear_range tps65224_bucks_1_ranges[] = {
+ REGULATOR_LINEAR_RANGE(500000, 0x0a, 0x0e, 20000),
+ REGULATOR_LINEAR_RANGE(600000, 0x0f, 0x72, 5000),
+ REGULATOR_LINEAR_RANGE(1100000, 0x73, 0xaa, 10000),
+ REGULATOR_LINEAR_RANGE(1660000, 0xab, 0xfd, 20000),
+};
+
+static const struct linear_range tps65224_bucks_2_3_4_ranges[] = {
+ REGULATOR_LINEAR_RANGE(500000, 0x0, 0x1a, 25000),
+ REGULATOR_LINEAR_RANGE(1200000, 0x1b, 0x45, 50000),
+};
+
+static const struct linear_range tps65224_ldos_1_ranges[] = {
+ REGULATOR_LINEAR_RANGE(1200000, 0xC, 0x36, 50000),
+};
+
+static const struct linear_range tps65224_ldos_2_3_ranges[] = {
+ REGULATOR_LINEAR_RANGE(600000, 0x0, 0x38, 50000),
+};
+
/* Operations permitted on BUCK1/2/3/4/5 */
static const struct regulator_ops tps6594_bucks_ops = {
.is_enabled = regulator_is_enabled_regmap,
@@ -197,6 +227,38 @@ static const struct regulator_desc buck_regs[] = {
4, 0, 0, NULL, 0, 0),
};
+/* Buck configuration for TPS65224 */
+static const struct regulator_desc tps65224_buck_regs[] = {
+ TPS6594_REGULATOR("BUCK1", "buck1", TPS6594_BUCK_1,
+ REGULATOR_VOLTAGE, tps6594_bucks_ops, TPS65224_MASK_BUCK1_VSET,
+ TPS6594_REG_BUCKX_VOUT_1(0),
+ TPS65224_MASK_BUCK1_VSET,
+ TPS6594_REG_BUCKX_CTRL(0),
+ TPS6594_BIT_BUCK_EN, 0, 0, tps65224_bucks_1_ranges,
+ 4, 0, 0, NULL, 0, 0),
+ TPS6594_REGULATOR("BUCK2", "buck2", TPS6594_BUCK_2,
+ REGULATOR_VOLTAGE, tps6594_bucks_ops, TPS65224_MASK_BUCKS_VSET,
+ TPS6594_REG_BUCKX_VOUT_1(1),
+ TPS65224_MASK_BUCKS_VSET,
+ TPS6594_REG_BUCKX_CTRL(1),
+ TPS6594_BIT_BUCK_EN, 0, 0, tps65224_bucks_2_3_4_ranges,
+ 4, 0, 0, NULL, 0, 0),
+ TPS6594_REGULATOR("BUCK3", "buck3", TPS6594_BUCK_3,
+ REGULATOR_VOLTAGE, tps6594_bucks_ops, TPS65224_MASK_BUCKS_VSET,
+ TPS6594_REG_BUCKX_VOUT_1(2),
+ TPS65224_MASK_BUCKS_VSET,
+ TPS6594_REG_BUCKX_CTRL(2),
+ TPS6594_BIT_BUCK_EN, 0, 0, tps65224_bucks_2_3_4_ranges,
+ 4, 0, 0, NULL, 0, 0),
+ TPS6594_REGULATOR("BUCK4", "buck4", TPS6594_BUCK_4,
+ REGULATOR_VOLTAGE, tps6594_bucks_ops, TPS65224_MASK_BUCKS_VSET,
+ TPS6594_REG_BUCKX_VOUT_1(3),
+ TPS65224_MASK_BUCKS_VSET,
+ TPS6594_REG_BUCKX_CTRL(3),
+ TPS6594_BIT_BUCK_EN, 0, 0, tps65224_bucks_2_3_4_ranges,
+ 4, 0, 0, NULL, 0, 0),
+};
+
static struct tps6594_regulator_irq_type tps6594_buck1_irq_types[] = {
{ TPS6594_IRQ_NAME_BUCK1_OV, "BUCK1", "overvoltage", REGULATOR_EVENT_OVER_VOLTAGE_WARN },
{ TPS6594_IRQ_NAME_BUCK1_UV, "BUCK1", "undervoltage", REGULATOR_EVENT_UNDER_VOLTAGE },
@@ -269,6 +331,41 @@ static struct tps6594_regulator_irq_type tps6594_ldo4_irq_types[] = {
REGULATOR_EVENT_OVER_CURRENT },
};
+static struct tps6594_regulator_irq_type tps65224_buck1_irq_types[] = {
+ { TPS65224_IRQ_NAME_BUCK1_UVOV, "BUCK1", "voltage out of range",
+ REGULATOR_EVENT_REGULATION_OUT },
+};
+
+static struct tps6594_regulator_irq_type tps65224_buck2_irq_types[] = {
+ { TPS65224_IRQ_NAME_BUCK2_UVOV, "BUCK2", "voltage out of range",
+ REGULATOR_EVENT_REGULATION_OUT },
+};
+
+static struct tps6594_regulator_irq_type tps65224_buck3_irq_types[] = {
+ { TPS65224_IRQ_NAME_BUCK3_UVOV, "BUCK3", "voltage out of range",
+ REGULATOR_EVENT_REGULATION_OUT },
+};
+
+static struct tps6594_regulator_irq_type tps65224_buck4_irq_types[] = {
+ { TPS65224_IRQ_NAME_BUCK4_UVOV, "BUCK4", "voltage out of range",
+ REGULATOR_EVENT_REGULATION_OUT },
+};
+
+static struct tps6594_regulator_irq_type tps65224_ldo1_irq_types[] = {
+ { TPS65224_IRQ_NAME_LDO1_UVOV, "LDO1", "voltage out of range",
+ REGULATOR_EVENT_REGULATION_OUT },
+};
+
+static struct tps6594_regulator_irq_type tps65224_ldo2_irq_types[] = {
+ { TPS65224_IRQ_NAME_LDO2_UVOV, "LDO2", "voltage out of range",
+ REGULATOR_EVENT_REGULATION_OUT },
+};
+
+static struct tps6594_regulator_irq_type tps65224_ldo3_irq_types[] = {
+ { TPS65224_IRQ_NAME_LDO3_UVOV, "LDO3", "voltage out of range",
+ REGULATOR_EVENT_REGULATION_OUT },
+};
+
static struct tps6594_regulator_irq_type *tps6594_bucks_irq_types[] = {
tps6594_buck1_irq_types,
tps6594_buck2_irq_types,
@@ -284,7 +381,20 @@ static struct tps6594_regulator_irq_type *tps6594_ldos_irq_types[] = {
tps6594_ldo4_irq_types,
};
-static const struct regulator_desc multi_regs[] = {
+static struct tps6594_regulator_irq_type *tps65224_bucks_irq_types[] = {
+ tps65224_buck1_irq_types,
+ tps65224_buck2_irq_types,
+ tps65224_buck3_irq_types,
+ tps65224_buck4_irq_types,
+};
+
+static struct tps6594_regulator_irq_type *tps65224_ldos_irq_types[] = {
+ tps65224_ldo1_irq_types,
+ tps65224_ldo2_irq_types,
+ tps65224_ldo3_irq_types,
+};
+
+static const struct regulator_desc tps6594_multi_regs[] = {
TPS6594_REGULATOR("BUCK12", "buck12", TPS6594_BUCK_1,
REGULATOR_VOLTAGE, tps6594_bucks_ops, TPS6594_MASK_BUCKS_VSET,
TPS6594_REG_BUCKX_VOUT_1(1),
@@ -315,7 +425,17 @@ static const struct regulator_desc multi_regs[] = {
4, 4000, 0, NULL, 0, 0),
};
-static const struct regulator_desc ldo_regs[] = {
+static const struct regulator_desc tps65224_multi_regs[] = {
+ TPS6594_REGULATOR("BUCK12", "buck12", TPS6594_BUCK_1,
+ REGULATOR_VOLTAGE, tps6594_bucks_ops, TPS65224_MASK_BUCK1_VSET,
+ TPS6594_REG_BUCKX_VOUT_1(0),
+ TPS65224_MASK_BUCK1_VSET,
+ TPS6594_REG_BUCKX_CTRL(0),
+ TPS6594_BIT_BUCK_EN, 0, 0, tps65224_bucks_1_ranges,
+ 4, 4000, 0, NULL, 0, 0),
+};
+
+static const struct regulator_desc tps6594_ldo_regs[] = {
TPS6594_REGULATOR("LDO1", "ldo1", TPS6594_LDO_1,
REGULATOR_VOLTAGE, tps6594_ldos_1_2_3_ops, TPS6594_MASK_LDO123_VSET,
TPS6594_REG_LDOX_VOUT(0),
@@ -346,6 +466,30 @@ static const struct regulator_desc ldo_regs[] = {
1, 0, 0, NULL, 0, 0),
};
+static const struct regulator_desc tps65224_ldo_regs[] = {
+ TPS6594_REGULATOR("LDO1", "ldo1", TPS6594_LDO_1,
+ REGULATOR_VOLTAGE, tps6594_ldos_1_2_3_ops, TPS6594_MASK_LDO123_VSET,
+ TPS6594_REG_LDOX_VOUT(0),
+ TPS6594_MASK_LDO123_VSET,
+ TPS6594_REG_LDOX_CTRL(0),
+ TPS6594_BIT_LDO_EN, 0, 0, tps65224_ldos_1_ranges,
+ 1, 0, 0, NULL, 0, TPS6594_BIT_LDO_BYPASS),
+ TPS6594_REGULATOR("LDO2", "ldo2", TPS6594_LDO_2,
+ REGULATOR_VOLTAGE, tps6594_ldos_1_2_3_ops, TPS6594_MASK_LDO123_VSET,
+ TPS6594_REG_LDOX_VOUT(1),
+ TPS6594_MASK_LDO123_VSET,
+ TPS6594_REG_LDOX_CTRL(1),
+ TPS6594_BIT_LDO_EN, 0, 0, tps65224_ldos_2_3_ranges,
+ 1, 0, 0, NULL, 0, TPS6594_BIT_LDO_BYPASS),
+ TPS6594_REGULATOR("LDO3", "ldo3", TPS6594_LDO_3,
+ REGULATOR_VOLTAGE, tps6594_ldos_1_2_3_ops, TPS6594_MASK_LDO123_VSET,
+ TPS6594_REG_LDOX_VOUT(2),
+ TPS6594_MASK_LDO123_VSET,
+ TPS6594_REG_LDOX_CTRL(2),
+ TPS6594_BIT_LDO_EN, 0, 0, tps65224_ldos_2_3_ranges,
+ 1, 0, 0, NULL, 0, TPS6594_BIT_LDO_BYPASS),
+};
+
static irqreturn_t tps6594_regulator_irq_handler(int irq, void *data)
{
struct tps6594_regulator_irq_data *irq_data = data;
@@ -369,17 +513,23 @@ static irqreturn_t tps6594_regulator_irq_handler(int irq, void *data)
static int tps6594_request_reg_irqs(struct platform_device *pdev,
struct regulator_dev *rdev,
struct tps6594_regulator_irq_data *irq_data,
- struct tps6594_regulator_irq_type *tps6594_regs_irq_types,
+ struct tps6594_regulator_irq_type *regs_irq_types,
int *irq_idx)
{
struct tps6594_regulator_irq_type *irq_type;
struct tps6594 *tps = dev_get_drvdata(pdev->dev.parent);
- int j;
+ size_t j;
int irq;
int error;
+ size_t interrupt_cnt;
+
+ if (tps->chip_id == TPS6594)
+ interrupt_cnt = ARRAY_SIZE(tps6594_buck1_irq_types);
+ else
+ interrupt_cnt = ARRAY_SIZE(tps65224_buck1_irq_types);
- for (j = 0; j < REGS_INT_NB; j++) {
- irq_type = &tps6594_regs_irq_types[j];
+ for (j = 0; j < interrupt_cnt; j++) {
+ irq_type = ®s_irq_types[j];
irq = platform_get_irq_byname(pdev, irq_type->irq_name);
if (irq < 0)
return -EINVAL;
@@ -412,14 +562,31 @@ static int tps6594_regulator_probe(struct platform_device *pdev)
struct tps6594_ext_regulator_irq_data *irq_ext_reg_data;
struct tps6594_regulator_irq_type *irq_type;
u8 buck_configured[BUCK_NB] = { 0 };
+ u8 ldo_configured[LDO_NB] = { 0 };
u8 buck_multi[MULTI_PHASE_NB] = { 0 };
- static const char * const multiphases[] = {"buck12", "buck123", "buck1234", "buck34"};
+ static const char * const tps6594_multiphases[] = {"buck12", "buck123",
+ "buck1234", "buck34"};
+ static const char * const tps65224_multiphases[] = {"buck12"};
static const char *npname;
int error, i, irq, multi, delta;
int irq_idx = 0;
int buck_idx = 0;
+ unsigned int multi_phase_cnt = 0;
size_t ext_reg_irq_nb = 2;
size_t reg_irq_nb;
+ struct tps6594_regulator_irq_type **bucks_irq_types = (tps->chip_id == TPS65224) ?
+ tps65224_bucks_irq_types :
+ tps6594_bucks_irq_types;
+ const struct regulator_desc *multi_regs = (tps->chip_id == TPS65224) ?
+ tps65224_multi_regs :
+ tps6594_multi_regs;
+ struct tps6594_regulator_irq_type **ldos_irq_types = (tps->chip_id == TPS65224) ?
+ tps65224_ldos_irq_types :
+ tps6594_ldos_irq_types;
+ const struct regulator_desc *ldo_regs = (tps->chip_id == TPS65224) ?
+ tps65224_ldo_regs :
+ tps6594_ldo_regs;
+
enum {
MULTI_BUCK12,
MULTI_BUCK123,
@@ -434,6 +601,10 @@ static int tps6594_regulator_probe(struct platform_device *pdev)
config.driver_data = tps;
config.regmap = tps->regmap;
+ multi_phase_cnt = (tps->chip_id == TPS65224) ?
+ ARRAY_SIZE(tps65224_multiphases) :
+ ARRAY_SIZE(tps6594_multiphases);
+
/*
* Switch case defines different possible multi phase config
* This is based on dts buck node name.
@@ -442,13 +613,13 @@ static int tps6594_regulator_probe(struct platform_device *pdev)
* In case of Multiphase configuration, value should be defined for
* buck_configured to avoid creating bucks for every buck in multiphase
*/
- for (multi = MULTI_FIRST; multi < MULTI_NUM; multi++) {
- np = of_find_node_by_name(tps->dev->of_node, multiphases[multi]);
+ for (multi = MULTI_FIRST; multi < multi_phase_cnt; multi++) {
+ np = of_find_node_by_name(tps->dev->of_node, tps6594_multiphases[multi]);
npname = of_node_full_name(np);
np_pmic_parent = of_get_parent(of_get_parent(np));
if (of_node_cmp(of_node_full_name(np_pmic_parent), tps->dev->of_node->full_name))
continue;
- delta = strcmp(npname, multiphases[multi]);
+ delta = strcmp(npname, tps6594_multiphases[multi]);
if (!delta) {
switch (multi) {
case MULTI_BUCK12:
@@ -486,6 +657,11 @@ static int tps6594_regulator_probe(struct platform_device *pdev)
/* There is only 4 buck on LP8764 */
buck_configured[4] = 1;
reg_irq_nb = size_mul(REGS_INT_NB, (BUCK_NB - 1));
+ } else if (tps->chip_id == TPS65224) {
+ /* TPS65224 has 4 bucks and 3 LDOs. 1 Interrupt for each buck and ldo */
+ buck_configured[4] = 1;
+ ldo_configured[3] = 1;
+ reg_irq_nb = size_mul(1, (size_add((BUCK_NB - 1), (LDO_NB - 1))));
} else {
reg_irq_nb = size_mul(REGS_INT_NB, (size_add(BUCK_NB, LDO_NB)));
}
@@ -495,7 +671,7 @@ static int tps6594_regulator_probe(struct platform_device *pdev)
if (!irq_data)
return -ENOMEM;
- for (i = 0; i < MULTI_PHASE_NB; i++) {
+ for (i = 0; i < multi_phase_cnt; i++) {
if (buck_multi[i] == 0)
continue;
@@ -508,12 +684,14 @@ static int tps6594_regulator_probe(struct platform_device *pdev)
/* config multiphase buck12+buck34 */
if (i == 1)
buck_idx = 2;
+
error = tps6594_request_reg_irqs(pdev, rdev, irq_data,
- tps6594_bucks_irq_types[buck_idx], &irq_idx);
+ bucks_irq_types[buck_idx], &irq_idx);
if (error)
return error;
+
error = tps6594_request_reg_irqs(pdev, rdev, irq_data,
- tps6594_bucks_irq_types[buck_idx + 1], &irq_idx);
+ bucks_irq_types[buck_idx + 1], &irq_idx);
if (error)
return error;
@@ -537,21 +715,26 @@ static int tps6594_regulator_probe(struct platform_device *pdev)
if (buck_configured[i] == 1)
continue;
- rdev = devm_regulator_register(&pdev->dev, &buck_regs[i], &config);
+ const struct regulator_desc *buck_cfg = (tps->chip_id == TPS65224) ?
+ tps65224_buck_regs : buck_regs;
+
+ rdev = devm_regulator_register(&pdev->dev, &buck_cfg[i], &config);
if (IS_ERR(rdev))
return dev_err_probe(tps->dev, PTR_ERR(rdev),
- "failed to register %s regulator\n",
- pdev->name);
+ "failed to register %s regulator\n", pdev->name);
error = tps6594_request_reg_irqs(pdev, rdev, irq_data,
- tps6594_bucks_irq_types[i], &irq_idx);
+ bucks_irq_types[i], &irq_idx);
if (error)
return error;
}
- /* LP8764 dosen't have LDO */
+ /* LP8764 doesn't have LDO */
if (tps->chip_id != LP8764) {
- for (i = 0; i < ARRAY_SIZE(ldo_regs); i++) {
+ for (i = 0; i < LDO_NB; i++) {
+ if (ldo_configured[i] == 1)
+ continue;
+
rdev = devm_regulator_register(&pdev->dev, &ldo_regs[i], &config);
if (IS_ERR(rdev))
return dev_err_probe(tps->dev, PTR_ERR(rdev),
@@ -559,8 +742,7 @@ static int tps6594_regulator_probe(struct platform_device *pdev)
pdev->name);
error = tps6594_request_reg_irqs(pdev, rdev, irq_data,
- tps6594_ldos_irq_types[i],
- &irq_idx);
+ ldos_irq_types[i], &irq_idx);
if (error)
return error;
}
@@ -568,16 +750,21 @@ static int tps6594_regulator_probe(struct platform_device *pdev)
if (tps->chip_id == LP8764)
ext_reg_irq_nb = ARRAY_SIZE(tps6594_ext_regulator_irq_types);
+ else if (tps->chip_id == TPS65224)
+ ext_reg_irq_nb = ARRAY_SIZE(tps65224_ext_regulator_irq_types);
irq_ext_reg_data = devm_kmalloc_array(tps->dev,
- ext_reg_irq_nb,
- sizeof(struct tps6594_ext_regulator_irq_data),
- GFP_KERNEL);
+ ext_reg_irq_nb,
+ sizeof(struct tps6594_ext_regulator_irq_data),
+ GFP_KERNEL);
if (!irq_ext_reg_data)
return -ENOMEM;
for (i = 0; i < ext_reg_irq_nb; ++i) {
- irq_type = &tps6594_ext_regulator_irq_types[i];
+ if (tps->chip_id == TPS65224)
+ irq_type = &tps65224_ext_regulator_irq_types[i];
+ else
+ irq_type = &tps6594_ext_regulator_irq_types[i];
irq = platform_get_irq_byname(pdev, irq_type->irq_name);
if (irq < 0)
@@ -610,5 +797,6 @@ module_platform_driver(tps6594_regulator_driver);
MODULE_ALIAS("platform:tps6594-regulator");
MODULE_AUTHOR("Jerome Neanne <jneanne@baylibre.com>");
+MODULE_AUTHOR("Nirmala Devi Mal Nadar <m.nirmaladevi@ltts.com>");
MODULE_DESCRIPTION("TPS6594 voltage regulator driver");
MODULE_LICENSE("GPL");
--
2.25.1
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply related
* [PATCH v5 11/11] arch: arm64: dts: ti: k3-am62p5-sk: Add TPS65224 PMIC support in AM62P dts
From: Bhargav Raviprakash @ 2024-03-28 12:40 UTC (permalink / raw)
To: linux-kernel
Cc: m.nirmaladevi, lee, robh+dt, krzysztof.kozlowski+dt, conor+dt,
jpanis, devicetree, arnd, gregkh, lgirdwood, broonie,
linus.walleij, linux-gpio, linux-arm-kernel, nm, vigneshr, kristo,
eblanc, Bhargav Raviprakash
In-Reply-To: <20240328124016.161959-1-bhargav.r@ltts.com>
Add support for TPS65224 PMIC in device tree of AM62P EVM. Adds regulator
configuration, pinmux configurations and pmic device nodes.
Signed-off-by: Bhargav Raviprakash <bhargav.r@ltts.com>
---
arch/arm64/boot/dts/ti/k3-am62p5-sk.dts | 95 +++++++++++++++++++++++++
1 file changed, 95 insertions(+)
diff --git a/arch/arm64/boot/dts/ti/k3-am62p5-sk.dts b/arch/arm64/boot/dts/ti/k3-am62p5-sk.dts
index 1773c05f7..5d8e4321b 100644
--- a/arch/arm64/boot/dts/ti/k3-am62p5-sk.dts
+++ b/arch/arm64/boot/dts/ti/k3-am62p5-sk.dts
@@ -112,6 +112,16 @@ vddshv_sdio: regulator-3 {
bootph-all;
};
+ vcc_3v3_main: regulator-4 {
+ compatible = "regulator-fixed";
+ regulator-name = "vcc_3v3_main";
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ vin-supply = <&vmain_pd>;
+ regulator-always-on;
+ regulator-boot-on;
+ };
+
leds {
compatible = "gpio-leds";
pinctrl-names = "default";
@@ -580,6 +590,12 @@ &main_uart1 {
&mcu_pmx0 {
bootph-all;
+ pmic_irq_pins_default: pmic-irq-default-pins {
+ pinctrl-single,pins = <
+ AM62PX_MCU_IOPAD(0x000, PIN_INPUT, 7) /* (B10) MCU_GPIO0_0 */
+ >;
+ };
+
wkup_uart0_pins_default: wkup-uart0-default-pins {
pinctrl-single,pins = <
AM62PX_MCU_IOPAD(0x02c, PIN_INPUT, 0) /* (C7) WKUP_UART0_CTSn */
@@ -589,6 +605,13 @@ AM62PX_MCU_IOPAD(0x028, PIN_OUTPUT, 0) /* (D7) WKUP_UART0_TXD */
>;
bootph-all;
};
+
+ wkup_i2c0_pins_default: wkup-i2c0-default-pins {
+ pinctrl-single,pins = <
+ AM62PX_MCU_IOPAD(0x04c, PIN_INPUT, 0) /* (A13) WKUP_I2C0_SCL */
+ AM62PX_MCU_IOPAD(0x050, PIN_INPUT, 0) /* (C11) WKUP_I2C0_SDA */
+ >;
+ };
};
&wkup_uart0 {
@@ -599,6 +622,78 @@ &wkup_uart0 {
bootph-all;
};
+&wkup_i2c0 {
+ status = "okay";
+ pinctrl-names = "default";
+ pinctrl-0 = <&wkup_i2c0_pins_default>;
+ clock-frequency = <400000>;
+
+ tps65224: pmic@48 {
+ compatible = "ti,tps65224-q1";
+ reg = <0x48>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pmic_irq_pins_default>;
+ interrupt-parent = <&mcu_gpio0>;
+ interrupts = <0 IRQ_TYPE_EDGE_FALLING>;
+ ti,primary-pmic;
+
+ gpio-controller;
+ #gpio-cells = <2>;
+
+ buck12-supply = <&vcc_3v3_main>;
+ buck3-supply = <&vcc_3v3_main>;
+ buck4-supply = <&vcc_3v3_main>;
+
+ ldo1-supply = <&vcc_3v3_main>;
+ ldo2-supply = <&vcc_3v3_main>;
+ ldo3-supply = <&vcc1v8_sys>;
+
+ regulators {
+ vcc_core: buck12 {
+ regulator-name = "vcc_core_buck12";
+ regulator-min-microvolt = <715000>;
+ regulator-max-microvolt = <895000>;
+ regulator-always-on;
+ };
+
+ vcc1v8_sys: buck3 {
+ regulator-name = "vcc1v8_sys_buck3";
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ regulator-always-on;
+ };
+
+ vcc1v1: buck4 {
+ regulator-name = "vcc1v1_buck4";
+ regulator-min-microvolt = <1100000>;
+ regulator-max-microvolt = <1100000>;
+ regulator-always-on;
+ };
+
+ vdda1v8: ldo1 {
+ regulator-name = "vdda1v8_ldo1";
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ regulator-always-on;
+ };
+
+ dvdd3v3: ldo2 {
+ regulator-name = "dvdd3v3_ldo2";
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-always-on;
+ };
+
+ vcc_0v85: ldo3 {
+ regulator-name = "vcc_0v85_ldo3";
+ regulator-min-microvolt = <850000>;
+ regulator-max-microvolt = <850000>;
+ regulator-always-on;
+ };
+ };
+ };
+};
+
/* mcu_gpio0 and mcu_gpio_intr are reserved for mcu firmware usage */
&mcu_gpio0 {
status = "reserved";
--
2.25.1
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply related
* [PATCH v5 10/11] pinctrl: pinctrl-tps6594: Add TPS65224 PMIC pinctrl and GPIO
From: Bhargav Raviprakash @ 2024-03-28 12:40 UTC (permalink / raw)
To: linux-kernel
Cc: m.nirmaladevi, lee, robh+dt, krzysztof.kozlowski+dt, conor+dt,
jpanis, devicetree, arnd, gregkh, lgirdwood, broonie,
linus.walleij, linux-gpio, linux-arm-kernel, nm, vigneshr, kristo,
eblanc, Bhargav Raviprakash
In-Reply-To: <20240328124016.161959-1-bhargav.r@ltts.com>
From: Nirmala Devi Mal Nadar <m.nirmaladevi@ltts.com>
Add support for TPS65224 pinctrl and GPIOs to TPS6594 driver as they have
significant functional overlap.
TPS65224 PMIC has 6 GPIOS which can be configured as GPIO or other
dedicated device functions.
Signed-off-by: Nirmala Devi Mal Nadar <m.nirmaladevi@ltts.com>
Signed-off-by: Bhargav Raviprakash <bhargav.r@ltts.com>
Acked-by: Linus Walleij <linus.walleij@linaro.org>
---
drivers/pinctrl/pinctrl-tps6594.c | 275 +++++++++++++++++++++++++-----
1 file changed, 228 insertions(+), 47 deletions(-)
diff --git a/drivers/pinctrl/pinctrl-tps6594.c b/drivers/pinctrl/pinctrl-tps6594.c
index 66985e54b..f3d1c1518 100644
--- a/drivers/pinctrl/pinctrl-tps6594.c
+++ b/drivers/pinctrl/pinctrl-tps6594.c
@@ -14,8 +14,6 @@
#include <linux/mfd/tps6594.h>
-#define TPS6594_PINCTRL_PINS_NB 11
-
#define TPS6594_PINCTRL_GPIO_FUNCTION 0
#define TPS6594_PINCTRL_SCL_I2C2_CS_SPI_FUNCTION 1
#define TPS6594_PINCTRL_TRIG_WDOG_FUNCTION 1
@@ -40,17 +38,40 @@
#define TPS6594_PINCTRL_SYNCCLKOUT_FUNCTION_GPIO8 3
#define TPS6594_PINCTRL_CLK32KOUT_FUNCTION_GPIO9 3
+/* TPS65224 pin muxval */
+#define TPS65224_PINCTRL_SDA_I2C2_SDO_SPI_FUNCTION 1
+#define TPS65224_PINCTRL_SCL_I2C2_CS_SPI_FUNCTION 1
+#define TPS65224_PINCTRL_VMON1_FUNCTION 1
+#define TPS65224_PINCTRL_VMON2_FUNCTION 1
+#define TPS65224_PINCTRL_WKUP_FUNCTION 1
+#define TPS65224_PINCTRL_NSLEEP2_FUNCTION 2
+#define TPS65224_PINCTRL_NSLEEP1_FUNCTION 2
+#define TPS65224_PINCTRL_SYNCCLKIN_FUNCTION 2
+#define TPS65224_PINCTRL_NERR_MCU_FUNCTION 2
+#define TPS65224_PINCTRL_NINT_FUNCTION 3
+#define TPS65224_PINCTRL_TRIG_WDOG_FUNCTION 3
+#define TPS65224_PINCTRL_PB_FUNCTION 3
+#define TPS65224_PINCTRL_ADC_IN_FUNCTION 3
+
+/* TPS65224 Special muxval for recalcitrant pins */
+#define TPS65224_PINCTRL_NSLEEP2_FUNCTION_GPIO5 1
+#define TPS65224_PINCTRL_WKUP_FUNCTION_GPIO5 4
+#define TPS65224_PINCTRL_SYNCCLKIN_FUNCTION_GPIO5 3
+
#define TPS6594_OFFSET_GPIO_SEL 5
-#define FUNCTION(fname, v) \
+#define TPS65224_NGPIO_PER_REG 6
+#define TPS6594_NGPIO_PER_REG 8
+
+#define FUNCTION(dev_name, fname, v) \
{ \
.pinfunction = PINCTRL_PINFUNCTION(#fname, \
- tps6594_##fname##_func_group_names, \
- ARRAY_SIZE(tps6594_##fname##_func_group_names)),\
+ dev_name##_##fname##_func_group_names, \
+ ARRAY_SIZE(dev_name##_##fname##_func_group_names)),\
.muxval = v, \
}
-static const struct pinctrl_pin_desc tps6594_pins[TPS6594_PINCTRL_PINS_NB] = {
+static const struct pinctrl_pin_desc tps6594_pins[] = {
PINCTRL_PIN(0, "GPIO0"), PINCTRL_PIN(1, "GPIO1"),
PINCTRL_PIN(2, "GPIO2"), PINCTRL_PIN(3, "GPIO3"),
PINCTRL_PIN(4, "GPIO4"), PINCTRL_PIN(5, "GPIO5"),
@@ -143,30 +164,127 @@ static const char *const tps6594_syncclkin_func_group_names[] = {
"GPIO9",
};
+static const struct pinctrl_pin_desc tps65224_pins[] = {
+ PINCTRL_PIN(0, "GPIO0"), PINCTRL_PIN(1, "GPIO1"),
+ PINCTRL_PIN(2, "GPIO2"), PINCTRL_PIN(3, "GPIO3"),
+ PINCTRL_PIN(4, "GPIO4"), PINCTRL_PIN(5, "GPIO5"),
+};
+
+static const char *const tps65224_gpio_func_group_names[] = {
+ "GPIO0", "GPIO1", "GPIO2", "GPIO3", "GPIO4", "GPIO5",
+};
+
+static const char *const tps65224_sda_i2c2_sdo_spi_func_group_names[] = {
+ "GPIO0",
+};
+
+static const char *const tps65224_nsleep2_func_group_names[] = {
+ "GPIO0", "GPIO5",
+};
+
+static const char *const tps65224_nint_func_group_names[] = {
+ "GPIO0",
+};
+
+static const char *const tps65224_scl_i2c2_cs_spi_func_group_names[] = {
+ "GPIO1",
+};
+
+static const char *const tps65224_nsleep1_func_group_names[] = {
+ "GPIO1", "GPIO2", "GPIO3",
+};
+
+static const char *const tps65224_trig_wdog_func_group_names[] = {
+ "GPIO1",
+};
+
+static const char *const tps65224_vmon1_func_group_names[] = {
+ "GPIO2",
+};
+
+static const char *const tps65224_pb_func_group_names[] = {
+ "GPIO2",
+};
+
+static const char *const tps65224_vmon2_func_group_names[] = {
+ "GPIO3",
+};
+
+static const char *const tps65224_adc_in_func_group_names[] = {
+ "GPIO3", "GPIO4",
+};
+
+static const char *const tps65224_wkup_func_group_names[] = {
+ "GPIO4", "GPIO5",
+};
+
+static const char *const tps65224_syncclkin_func_group_names[] = {
+ "GPIO4", "GPIO5",
+};
+
+static const char *const tps65224_nerr_mcu_func_group_names[] = {
+ "GPIO5",
+};
+
struct tps6594_pinctrl_function {
struct pinfunction pinfunction;
u8 muxval;
};
+struct muxval_remap {
+ unsigned int group;
+ u8 muxval;
+ u8 remap;
+};
+
+struct muxval_remap tps65224_muxval_remap[] = {
+ {5, TPS6594_PINCTRL_DISABLE_WDOG_FUNCTION, TPS65224_PINCTRL_WKUP_FUNCTION_GPIO5},
+ {5, TPS65224_PINCTRL_SYNCCLKIN_FUNCTION, TPS65224_PINCTRL_SYNCCLKIN_FUNCTION_GPIO5},
+ {5, TPS65224_PINCTRL_NSLEEP2_FUNCTION, TPS65224_PINCTRL_NSLEEP2_FUNCTION_GPIO5},
+};
+
+struct muxval_remap tps6594_muxval_remap[] = {
+ {8, TPS6594_PINCTRL_DISABLE_WDOG_FUNCTION, TPS6594_PINCTRL_DISABLE_WDOG_FUNCTION_GPIO8},
+ {8, TPS6594_PINCTRL_SYNCCLKOUT_FUNCTION, TPS6594_PINCTRL_SYNCCLKOUT_FUNCTION_GPIO8},
+ {9, TPS6594_PINCTRL_CLK32KOUT_FUNCTION, TPS6594_PINCTRL_CLK32KOUT_FUNCTION_GPIO9},
+};
+
static const struct tps6594_pinctrl_function pinctrl_functions[] = {
- FUNCTION(gpio, TPS6594_PINCTRL_GPIO_FUNCTION),
- FUNCTION(nsleep1, TPS6594_PINCTRL_NSLEEP1_FUNCTION),
- FUNCTION(nsleep2, TPS6594_PINCTRL_NSLEEP2_FUNCTION),
- FUNCTION(wkup1, TPS6594_PINCTRL_WKUP1_FUNCTION),
- FUNCTION(wkup2, TPS6594_PINCTRL_WKUP2_FUNCTION),
- FUNCTION(scl_i2c2_cs_spi, TPS6594_PINCTRL_SCL_I2C2_CS_SPI_FUNCTION),
- FUNCTION(nrstout_soc, TPS6594_PINCTRL_NRSTOUT_SOC_FUNCTION),
- FUNCTION(trig_wdog, TPS6594_PINCTRL_TRIG_WDOG_FUNCTION),
- FUNCTION(sda_i2c2_sdo_spi, TPS6594_PINCTRL_SDA_I2C2_SDO_SPI_FUNCTION),
- FUNCTION(clk32kout, TPS6594_PINCTRL_CLK32KOUT_FUNCTION),
- FUNCTION(nerr_soc, TPS6594_PINCTRL_NERR_SOC_FUNCTION),
- FUNCTION(sclk_spmi, TPS6594_PINCTRL_SCLK_SPMI_FUNCTION),
- FUNCTION(sdata_spmi, TPS6594_PINCTRL_SDATA_SPMI_FUNCTION),
- FUNCTION(nerr_mcu, TPS6594_PINCTRL_NERR_MCU_FUNCTION),
- FUNCTION(syncclkout, TPS6594_PINCTRL_SYNCCLKOUT_FUNCTION),
- FUNCTION(disable_wdog, TPS6594_PINCTRL_DISABLE_WDOG_FUNCTION),
- FUNCTION(pdog, TPS6594_PINCTRL_PDOG_FUNCTION),
- FUNCTION(syncclkin, TPS6594_PINCTRL_SYNCCLKIN_FUNCTION),
+ FUNCTION(tps6594, gpio, TPS6594_PINCTRL_GPIO_FUNCTION),
+ FUNCTION(tps6594, nsleep1, TPS6594_PINCTRL_NSLEEP1_FUNCTION),
+ FUNCTION(tps6594, nsleep2, TPS6594_PINCTRL_NSLEEP2_FUNCTION),
+ FUNCTION(tps6594, wkup1, TPS6594_PINCTRL_WKUP1_FUNCTION),
+ FUNCTION(tps6594, wkup2, TPS6594_PINCTRL_WKUP2_FUNCTION),
+ FUNCTION(tps6594, scl_i2c2_cs_spi, TPS6594_PINCTRL_SCL_I2C2_CS_SPI_FUNCTION),
+ FUNCTION(tps6594, nrstout_soc, TPS6594_PINCTRL_NRSTOUT_SOC_FUNCTION),
+ FUNCTION(tps6594, trig_wdog, TPS6594_PINCTRL_TRIG_WDOG_FUNCTION),
+ FUNCTION(tps6594, sda_i2c2_sdo_spi, TPS6594_PINCTRL_SDA_I2C2_SDO_SPI_FUNCTION),
+ FUNCTION(tps6594, clk32kout, TPS6594_PINCTRL_CLK32KOUT_FUNCTION),
+ FUNCTION(tps6594, nerr_soc, TPS6594_PINCTRL_NERR_SOC_FUNCTION),
+ FUNCTION(tps6594, sclk_spmi, TPS6594_PINCTRL_SCLK_SPMI_FUNCTION),
+ FUNCTION(tps6594, sdata_spmi, TPS6594_PINCTRL_SDATA_SPMI_FUNCTION),
+ FUNCTION(tps6594, nerr_mcu, TPS6594_PINCTRL_NERR_MCU_FUNCTION),
+ FUNCTION(tps6594, syncclkout, TPS6594_PINCTRL_SYNCCLKOUT_FUNCTION),
+ FUNCTION(tps6594, disable_wdog, TPS6594_PINCTRL_DISABLE_WDOG_FUNCTION),
+ FUNCTION(tps6594, pdog, TPS6594_PINCTRL_PDOG_FUNCTION),
+ FUNCTION(tps6594, syncclkin, TPS6594_PINCTRL_SYNCCLKIN_FUNCTION),
+};
+
+static const struct tps6594_pinctrl_function tps65224_pinctrl_functions[] = {
+ FUNCTION(tps65224, gpio, TPS6594_PINCTRL_GPIO_FUNCTION),
+ FUNCTION(tps65224, sda_i2c2_sdo_spi, TPS65224_PINCTRL_SDA_I2C2_SDO_SPI_FUNCTION),
+ FUNCTION(tps65224, nsleep2, TPS65224_PINCTRL_NSLEEP2_FUNCTION),
+ FUNCTION(tps65224, nint, TPS65224_PINCTRL_NINT_FUNCTION),
+ FUNCTION(tps65224, scl_i2c2_cs_spi, TPS65224_PINCTRL_SCL_I2C2_CS_SPI_FUNCTION),
+ FUNCTION(tps65224, nsleep1, TPS65224_PINCTRL_NSLEEP1_FUNCTION),
+ FUNCTION(tps65224, trig_wdog, TPS65224_PINCTRL_TRIG_WDOG_FUNCTION),
+ FUNCTION(tps65224, vmon1, TPS65224_PINCTRL_VMON1_FUNCTION),
+ FUNCTION(tps65224, pb, TPS65224_PINCTRL_PB_FUNCTION),
+ FUNCTION(tps65224, vmon2, TPS65224_PINCTRL_VMON2_FUNCTION),
+ FUNCTION(tps65224, adc_in, TPS65224_PINCTRL_ADC_IN_FUNCTION),
+ FUNCTION(tps65224, wkup, TPS65224_PINCTRL_WKUP_FUNCTION),
+ FUNCTION(tps65224, syncclkin, TPS65224_PINCTRL_SYNCCLKIN_FUNCTION),
+ FUNCTION(tps65224, nerr_mcu, TPS65224_PINCTRL_NERR_MCU_FUNCTION),
};
struct tps6594_pinctrl {
@@ -175,6 +293,31 @@ struct tps6594_pinctrl {
struct pinctrl_dev *pctl_dev;
const struct tps6594_pinctrl_function *funcs;
const struct pinctrl_pin_desc *pins;
+ int func_cnt;
+ int num_pins;
+ u8 mux_sel_mask;
+ unsigned int remap_cnt;
+ struct muxval_remap *remap;
+};
+
+static struct tps6594_pinctrl tps65224_template_pinctrl = {
+ .funcs = tps65224_pinctrl_functions,
+ .func_cnt = ARRAY_SIZE(tps65224_pinctrl_functions),
+ .pins = tps65224_pins,
+ .num_pins = ARRAY_SIZE(tps65224_pins),
+ .mux_sel_mask = TPS65224_MASK_GPIO_SEL,
+ .remap = tps65224_muxval_remap,
+ .remap_cnt = ARRAY_SIZE(tps65224_muxval_remap),
+};
+
+static struct tps6594_pinctrl tps6594_template_pinctrl = {
+ .funcs = pinctrl_functions,
+ .func_cnt = ARRAY_SIZE(pinctrl_functions),
+ .pins = tps6594_pins,
+ .num_pins = ARRAY_SIZE(tps6594_pins),
+ .mux_sel_mask = TPS6594_MASK_GPIO_SEL,
+ .remap = tps6594_muxval_remap,
+ .remap_cnt = ARRAY_SIZE(tps6594_muxval_remap),
};
static int tps6594_gpio_regmap_xlate(struct gpio_regmap *gpio,
@@ -201,7 +344,9 @@ static int tps6594_gpio_regmap_xlate(struct gpio_regmap *gpio,
static int tps6594_pmx_func_cnt(struct pinctrl_dev *pctldev)
{
- return ARRAY_SIZE(pinctrl_functions);
+ struct tps6594_pinctrl *pinctrl = pinctrl_dev_get_drvdata(pctldev);
+
+ return pinctrl->func_cnt;
}
static const char *tps6594_pmx_func_name(struct pinctrl_dev *pctldev,
@@ -229,10 +374,16 @@ static int tps6594_pmx_set(struct tps6594_pinctrl *pinctrl, unsigned int pin,
u8 muxval)
{
u8 mux_sel_val = muxval << TPS6594_OFFSET_GPIO_SEL;
+ u8 mux_sel_mask = pinctrl->mux_sel_mask;
+
+ if (pinctrl->tps->chip_id == TPS65224 && pin == 5) {
+ /* GPIO6 has a different mask in TPS65224*/
+ mux_sel_mask = TPS65224_MASK_GPIO_SEL_GPIO6;
+ }
return regmap_update_bits(pinctrl->tps->regmap,
TPS6594_REG_GPIOX_CONF(pin),
- TPS6594_MASK_GPIO_SEL, mux_sel_val);
+ mux_sel_mask, mux_sel_val);
}
static int tps6594_pmx_set_mux(struct pinctrl_dev *pctldev,
@@ -240,16 +391,14 @@ static int tps6594_pmx_set_mux(struct pinctrl_dev *pctldev,
{
struct tps6594_pinctrl *pinctrl = pinctrl_dev_get_drvdata(pctldev);
u8 muxval = pinctrl->funcs[function].muxval;
-
- /* Some pins don't have the same muxval for the same function... */
- if (group == 8) {
- if (muxval == TPS6594_PINCTRL_DISABLE_WDOG_FUNCTION)
- muxval = TPS6594_PINCTRL_DISABLE_WDOG_FUNCTION_GPIO8;
- else if (muxval == TPS6594_PINCTRL_SYNCCLKOUT_FUNCTION)
- muxval = TPS6594_PINCTRL_SYNCCLKOUT_FUNCTION_GPIO8;
- } else if (group == 9) {
- if (muxval == TPS6594_PINCTRL_CLK32KOUT_FUNCTION)
- muxval = TPS6594_PINCTRL_CLK32KOUT_FUNCTION_GPIO9;
+ unsigned int remap_cnt = pinctrl->remap_cnt;
+ struct muxval_remap *remap = pinctrl->remap;
+
+ for (unsigned int i = 0; i < remap_cnt; i++) {
+ if (group == remap[i].group && muxval == remap[i].muxval) {
+ muxval = remap[i].remap;
+ break;
+ }
}
return tps6594_pmx_set(pinctrl, group, muxval);
@@ -276,7 +425,9 @@ static const struct pinmux_ops tps6594_pmx_ops = {
static int tps6594_groups_cnt(struct pinctrl_dev *pctldev)
{
- return ARRAY_SIZE(tps6594_pins);
+ struct tps6594_pinctrl *pinctrl = pinctrl_dev_get_drvdata(pctldev);
+
+ return pinctrl->num_pins;
}
static int tps6594_group_pins(struct pinctrl_dev *pctldev,
@@ -318,19 +469,36 @@ static int tps6594_pinctrl_probe(struct platform_device *pdev)
pctrl_desc = devm_kzalloc(dev, sizeof(*pctrl_desc), GFP_KERNEL);
if (!pctrl_desc)
return -ENOMEM;
+
+ pinctrl = devm_kzalloc(dev, sizeof(*pinctrl), GFP_KERNEL);
+ if (!pinctrl)
+ return -ENOMEM;
+
pctrl_desc->name = dev_name(dev);
pctrl_desc->owner = THIS_MODULE;
- pctrl_desc->pins = tps6594_pins;
- pctrl_desc->npins = ARRAY_SIZE(tps6594_pins);
pctrl_desc->pctlops = &tps6594_pctrl_ops;
pctrl_desc->pmxops = &tps6594_pmx_ops;
- pinctrl = devm_kzalloc(dev, sizeof(*pinctrl), GFP_KERNEL);
- if (!pinctrl)
- return -ENOMEM;
- pinctrl->tps = dev_get_drvdata(dev->parent);
- pinctrl->funcs = pinctrl_functions;
- pinctrl->pins = tps6594_pins;
+ switch (tps->chip_id) {
+ case TPS65224:
+ pctrl_desc->pins = tps65224_pins;
+ pctrl_desc->npins = ARRAY_SIZE(tps65224_pins);
+
+ *pinctrl = tps65224_template_pinctrl;
+ break;
+ case TPS6593:
+ case TPS6594:
+ pctrl_desc->pins = tps6594_pins;
+ pctrl_desc->npins = ARRAY_SIZE(tps6594_pins);
+
+ *pinctrl = tps6594_template_pinctrl;
+ break;
+ default:
+ break;
+ }
+
+ pinctrl->tps = tps;
+
pinctrl->pctl_dev = devm_pinctrl_register(dev, pctrl_desc, pinctrl);
if (IS_ERR(pinctrl->pctl_dev))
return dev_err_probe(dev, PTR_ERR(pinctrl->pctl_dev),
@@ -338,8 +506,20 @@ static int tps6594_pinctrl_probe(struct platform_device *pdev)
config.parent = tps->dev;
config.regmap = tps->regmap;
- config.ngpio = TPS6594_PINCTRL_PINS_NB;
- config.ngpio_per_reg = 8;
+ switch (tps->chip_id) {
+ case TPS65224:
+ config.ngpio = ARRAY_SIZE(tps65224_gpio_func_group_names);
+ config.ngpio_per_reg = TPS65224_NGPIO_PER_REG;
+ break;
+ case TPS6593:
+ case TPS6594:
+ config.ngpio = ARRAY_SIZE(tps6594_gpio_func_group_names);
+ config.ngpio_per_reg = TPS6594_NGPIO_PER_REG;
+ break;
+ default:
+ break;
+ }
+
config.reg_dat_base = TPS6594_REG_GPIO_IN_1;
config.reg_set_base = TPS6594_REG_GPIO_OUT_1;
config.reg_dir_out_base = TPS6594_REG_GPIOX_CONF(0);
@@ -369,5 +549,6 @@ static struct platform_driver tps6594_pinctrl_driver = {
module_platform_driver(tps6594_pinctrl_driver);
MODULE_AUTHOR("Esteban Blanc <eblanc@baylibre.com>");
+MODULE_AUTHOR("Nirmala Devi Mal Nadar <m.nirmaladevi@ltts.com>");
MODULE_DESCRIPTION("TPS6594 pinctrl and GPIO driver");
MODULE_LICENSE("GPL");
--
2.25.1
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply related
* Re: [PATCH v3 1/3] clk: samsung: introduce nMUX for MUX clks that can reparented
From: André Draszik @ 2024-03-28 12:44 UTC (permalink / raw)
To: Tudor Ambarus, peter.griffin, krzysztof.kozlowski
Cc: alim.akhtar, linux-arm-kernel, linux-samsung-soc, linux-kernel,
willmcvicker, kernel-team, s.nawrocki, cw00.choi, mturquette,
sboyd, semen.protsenko, linux-clk, jaewon02.kim
In-Reply-To: <20240328123440.1387823-2-tudor.ambarus@linaro.org>
On Thu, 2024-03-28 at 12:34 +0000, Tudor Ambarus wrote:
> All samsung MUX clocks that are defined with MUX() set the
> CLK_SET_RATE_NO_REPARENT flag in __MUX(), which prevents MUXes to be
> reparented during clk_set_rate().
>
> Introduce nMUX() for MUX clocks that can be reparented on clock rate
> change. "nMUX" comes from "n-to-1 selector", hopefully emphasising that
> the selector can change on clock rate changes. Ideally MUX/MUX_F()
> should change to not have the CLK_SET_RATE_NO_REPARENT flag set by
> default, and all their users to be updated to add the flag back
> (like in the case of DIV and GATE). But this is a very intrusive change
> and because for now only GS101 allows MUX reparenting on clock rate
> change, stick with nMUX().
>
> One user of nMUX() will be GS101. GS101 defines MUX clocks that
> are dedicated for each instance of an IP (see MUX USI). The reparenting
> of these MUX clocks will not affect other instances of the same IP or
> different IPs altogether.
>
> Signed-off-by: Tudor Ambarus <tudor.ambarus@linaro.org>
Reviewed-by: André Draszik <andre.draszik@linaro.org>
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox